8136421: JEP 243: Java-Level JVM Compiler Interface
Reviewed-by: ihse, alanb, roland, coleenp, iveresov, kvn, kbarrett
--- a/hotspot/make/bsd/makefiles/compiler1.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/bsd/makefiles/compiler1.make Thu Oct 08 12:49:30 2015 -1000
@@ -28,4 +28,7 @@
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
--- a/hotspot/make/bsd/makefiles/gcc.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/bsd/makefiles/gcc.make Thu Oct 08 12:49:30 2015 -1000
@@ -149,6 +149,7 @@
PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH)
PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH)
PCH_FLAG/unsafe.o = $(PCH_FLAG/NO_PCH)
+ PCH_FLAG/jvmciCompilerToVM.o = $(PCH_FLAG/NO_PCH)
endif
else # ($(USE_CLANG), true)
--- a/hotspot/make/bsd/makefiles/minimal1.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/bsd/makefiles/minimal1.make Thu Oct 08 12:49:30 2015 -1000
@@ -38,6 +38,7 @@
INCLUDE_NMT := false
INCLUDE_TRACE := false
INCLUDE_CDS := false
+INCLUDE_JVMCI := false
CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
CFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
--- a/hotspot/make/excludeSrc.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/excludeSrc.make Thu Oct 08 12:49:30 2015 -1000
@@ -106,6 +106,25 @@
memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
endif
+ifneq (,$(findstring $(Platform_arch_model), x86_64, sparc))
+ # JVMCI is supported only on x86_64 and SPARC.
+else
+ INCLUDE_JVMCI := false
+endif
+
+ifeq ($(INCLUDE_JVMCI), false)
+ CXXFLAGS += -DINCLUDE_JVMCI=0
+ CFLAGS += -DINCLUDE_JVMCI=0
+
+ jvmci_dir := $(HS_COMMON_SRC)/share/vm/jvmci
+ jvmci_dir_alt := $(HS_ALT_SRC)/share/vm/jvmci
+ jvmci_exclude := $(notdir $(wildcard $(jvmci_dir)/*.cpp)) \
+ $(notdir $(wildcard $(jvmci_dir_alt)/*.cpp))
+ Src_Files_EXCLUDE += $(jvmci_exclude) \
+ jvmciCodeInstaller_aarch64.cpp jvmciCodeInstaller_ppc.cpp jvmciCodeInstaller_sparc.cpp \
+ jvmciCodeInstaller_x86.cpp
+endif
+
-include $(HS_ALT_MAKE)/excludeSrc.make
.PHONY: $(HS_ALT_MAKE)/excludeSrc.make
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,121 @@
+#
+# Copyright (c) 2015, 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.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include JavaCompilation.gmk
+include SetupJavaCompilers.gmk
+
+GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.vm.ci
+SRC_DIR := $(HOTSPOT_TOPDIR)/src/jdk.vm.ci/share/classes
+
+################################################################################
+# Compile the annotation processor
+
+$(eval $(call SetupJavaCompilation, BUILD_JVMCI_OPTIONS, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ SRC := $(SRC_DIR)/jdk.vm.ci.options/src \
+ $(SRC_DIR)/jdk.vm.ci.options.processor/src \
+ $(SRC_DIR)/jdk.vm.ci.inittimer/src, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jvmci_options, \
+ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar, \
+))
+
+$(eval $(call SetupJavaCompilation, BUILD_JVMCI_SERVICE, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ SRC := $(SRC_DIR)/jdk.vm.ci.service/src \
+ $(SRC_DIR)/jdk.vm.ci.service.processor/src, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jvmci_service, \
+ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.service.jar, \
+))
+
+################################################################################
+
+PROC_SRC_SUBDIRS := \
+ jdk.vm.ci.compiler \
+ jdk.vm.ci.hotspot \
+ jdk.vm.ci.hotspot.amd64 \
+ jdk.vm.ci.hotspot.sparc \
+ #
+
+PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS))
+
+PROC_SRCS := $(filter %.java, $(call CacheFind, $(PROC_SRC_DIRS)))
+
+ALL_SRC_DIRS := $(wildcard $(SRC_DIR)/*/src)
+SOURCEPATH := $(call PathList, $(ALL_SRC_DIRS))
+PROCESSOR_PATH := $(call PathList, \
+ $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar \
+ $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.service.jar)
+
+$(GENSRC_DIR)/_gensrc_proc_done: $(PROC_SRCS) \
+ $(BUILD_JVMCI_OPTIONS) $(BUILD_JVMCI_SERVICE)
+ $(MKDIR) -p $(@D)
+ $(eval $(call ListPathsSafely,PROC_SRCS,$(@D)/_gensrc_proc_files))
+ $(JAVA_SMALL) $(NEW_JAVAC) \
+ -sourcepath $(SOURCEPATH) \
+ -implicit:none \
+ -proc:only \
+ -processorpath $(PROCESSOR_PATH) \
+ -d $(GENSRC_DIR) \
+ -s $(GENSRC_DIR) \
+ @$(@D)/_gensrc_proc_files
+ $(TOUCH) $@
+
+TARGETS += $(GENSRC_DIR)/_gensrc_proc_done
+
+################################################################################
+
+$(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
+ $(GENSRC_DIR)/_gensrc_proc_done
+ $(MKDIR) -p $(@D)
+ ($(CD) $(GENSRC_DIR)/META-INF/jvmci.options && \
+ $(RM) -f $@; \
+ for i in $$(ls); do \
+ echo $${i}_OptionDescriptors >> $@; \
+ done)
+
+TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
+
+################################################################################
+
+$(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
+ $(MKDIR) -p $(GENSRC_DIR)/META-INF/services
+ ($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
+ for i in $$($(LS)); do \
+ c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
+ $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \
+ done)
+ $(TOUCH) $@
+
+TARGETS += $(GENSRC_DIR)/_providers_converted
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: default all
--- a/hotspot/make/linux/makefiles/compiler1.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/linux/makefiles/compiler1.make Thu Oct 08 12:49:30 2015 -1000
@@ -28,4 +28,7 @@
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
--- a/hotspot/make/linux/makefiles/minimal1.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/linux/makefiles/minimal1.make Thu Oct 08 12:49:30 2015 -1000
@@ -38,6 +38,7 @@
INCLUDE_NMT := false
INCLUDE_TRACE := false
INCLUDE_CDS := false
+INCLUDE_JVMCI := false
CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
CFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
--- a/hotspot/make/solaris/makefiles/compiler1.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/solaris/makefiles/compiler1.make Thu Oct 08 12:49:30 2015 -1000
@@ -28,4 +28,7 @@
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
--- a/hotspot/make/windows/build_vm_def.sh Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/windows/build_vm_def.sh Thu Oct 08 12:49:30 2015 -1000
@@ -52,6 +52,7 @@
CAT="$MKS_HOME/cat.exe"
RM="$MKS_HOME/rm.exe"
DUMPBIN="link.exe /dump"
+export VS_UNICODE_OUTPUT=
if [ "$1" = "-nosa" ]; then
echo EXPORTS > vm.def
--- a/hotspot/make/windows/create_obj_files.sh Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/windows/create_obj_files.sh Thu Oct 08 12:49:30 2015 -1000
@@ -111,6 +111,7 @@
COMPILER2_SPECIFIC_FILES="opto libadt bcEscapeAnalyzer.cpp c2_* runtime_*"
COMPILER1_SPECIFIC_FILES="c1_*"
+JVMCI_SPECIFIC_FILES="*jvmci* *JVMCI*"
SHARK_SPECIFIC_FILES="shark"
ZERO_SPECIFIC_FILES="zero"
@@ -119,11 +120,11 @@
# Exclude per type.
case "${TYPE}" in
- "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
+ "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
"compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
"tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
- "zero") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
- "shark") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES}" ;;
+ "zero") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
+ "shark") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES}" ;;
esac
# Special handling of arch model.
--- a/hotspot/make/windows/makefiles/projectcreator.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/windows/makefiles/projectcreator.make Thu Oct 08 12:49:30 2015 -1000
@@ -145,6 +145,10 @@
-ignorePath_TARGET tiered \
-ignorePath_TARGET c1_
+ProjectCreatorIDEOptionsIgnoreJVMCI=\
+ -ignorePath_TARGET src/share/vm/jvmci \
+ -ignorePath_TARGET vm/jvmci
+
ProjectCreatorIDEOptionsIgnoreCompiler2=\
-ignorePath_TARGET compiler2 \
-ignorePath_TARGET tiered \
@@ -165,6 +169,8 @@
##################################################
ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
-define_compiler1 COMPILER1 \
+ -define_compiler1 INCLUDE_JVMCI=0 \
+$(ProjectCreatorIDEOptionsIgnoreJVMCI:TARGET=compiler1) \
$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
##################################################
--- a/hotspot/make/windows/makefiles/vm.make Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/make/windows/makefiles/vm.make Thu Oct 08 12:49:30 2015 -1000
@@ -40,7 +40,7 @@
!endif
!if "$(Variant)" == "compiler1"
-CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1"
+CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" /D INCLUDE_JVMCI=0
!endif
!if "$(Variant)" == "compiler2"
@@ -152,6 +152,7 @@
VM_PATH=$(VM_PATH);../generated/jvmtifiles
VM_PATH=$(VM_PATH);../generated/tracefiles
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/jvmci
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/compiler
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/interpreter
@@ -232,6 +233,9 @@
{$(COMMONSRC)\share\vm\classfile}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+{$(COMMONSRC)\share\vm\jvmci}.cpp.obj::
+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
{$(COMMONSRC)\share\vm\gc\parallel}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
--- a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -51,13 +51,15 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// mov rmethod, 0
// jmp -4 # to self
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
--- a/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -30,5 +30,6 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
#endif // CPU_AARCH64_VM_CPPINTERPRETERGENERATOR_AARCH64_HPP
--- a/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -48,7 +48,6 @@
address generate_CRC32_update_entry();
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind);
address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
- void lock_method(void);
void generate_stack_overflow_check(void);
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_aarch64.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ Unimplemented();
+ return 0;
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ Unimplemented();
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ return NULL;
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return false;
+}
--- a/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -102,12 +102,5 @@
}
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
- if (NativeInstruction::maybe_cpool_ref(addr())) {
- address old_addr = old_addr_for(addr(), src, dest);
- MacroAssembler::pd_patch_instruction(addr(), MacroAssembler::target_addr_for_insn(old_addr));
- }
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -473,11 +473,11 @@
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: r13 contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -535,7 +535,7 @@
// r0
// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs)
// rscratch1, rscratch2 (scratch regs)
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags(rmethod, Method::access_flags_offset());
const Address monitor_block_top(
--- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -94,10 +94,12 @@
const int IC_pos_in_java_to_interp_stub = 8;
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = NULL*/) {
#ifdef COMPILER2
- // Get the mark within main instrs section which is set to the address of the call.
- address call_addr = cbuf.insts_mark();
+ if (mark == NULL) {
+ // Get the mark within main instrs section which is set to the address of the call.
+ mark = cbuf.insts_mark();
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
@@ -117,7 +119,7 @@
// Create a static stub relocation which relates this stub
// with the call instruction at insts_call_instruction_offset in the
// instructions code-section.
- __ relocate(static_stub_Relocation::spec(call_addr));
+ __ relocate(static_stub_Relocation::spec(mark));
const int stub_start_offset = __ offset();
// Now, create the stub's code:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_ppc.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ Unimplemented();
+ return 0;
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ Unimplemented();
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ return NULL;
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return false;
+}
--- a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -125,8 +125,5 @@
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -957,11 +957,11 @@
return c2i_entrypoint;
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Load method's entry-point from method.
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
--- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -53,14 +53,15 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
-#ifdef COMPILER2
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
// set (empty), G5
// jmp -1
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
MacroAssembler _masm(&cbuf);
@@ -80,12 +81,11 @@
__ delayed()->nop();
+ assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
// Update current stubs pointer and restore code_end.
__ end_a_stub();
return base;
-#else
- ShouldNotReachHere();
-#endif
}
#undef __
--- a/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -31,6 +31,7 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
void adjust_callers_stack(Register args);
void generate_compute_interpreter_state(const Register state,
const Register prev_state,
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1164,7 +1164,7 @@
}
// Find preallocated monitor and lock method (C++ interpreter)
//
-void InterpreterGenerator::lock_method(void) {
+void CppInterpreterGenerator::lock_method() {
// Lock the current method.
// Destroys registers L2_scratch, L3_scratch, O0
//
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1650,26 +1650,73 @@
bind(skip_receiver_profile);
// The method data pointer needs to be updated to reflect the new target.
+#if INCLUDE_JVMCI
+ if (MethodProfileWidth == 0) {
+ update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+ }
+#else
update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
- bind (profile_continue);
+#endif
+ bind(profile_continue);
}
}
-void InterpreterMacroAssembler::record_klass_in_profile_helper(
- Register receiver, Register scratch,
- int start_row, Label& done, bool is_virtual_call) {
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register scratch) {
+ assert_different_registers(method, scratch);
+ if (ProfileInterpreter && MethodProfileWidth > 0) {
+ Label profile_continue;
+
+ // If no method data exists, go to profile_continue.
+ test_method_data_pointer(profile_continue);
+
+ Label done;
+ record_item_in_profile_helper(method, scratch, 0, done, MethodProfileWidth,
+ &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+ bind(done);
+
+ update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+ bind(profile_continue);
+ }
+}
+#endif // INCLUDE_JVMCI
+
+void InterpreterMacroAssembler::record_klass_in_profile_helper(Register receiver, Register scratch,
+ Label& done, bool is_virtual_call) {
if (TypeProfileWidth == 0) {
if (is_virtual_call) {
increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
}
- return;
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ increment_mdp_data_at(in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()), scratch);
+ }
+#endif
+ } else {
+ int non_profiled_offset = -1;
+ if (is_virtual_call) {
+ non_profiled_offset = in_bytes(CounterData::count_offset());
+ }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+ }
+#endif
+
+ record_item_in_profile_helper(receiver, scratch, 0, done, TypeProfileWidth,
+ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
}
-
- int last_row = VirtualCallData::row_limit() - 1;
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item,
+ Register scratch, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset) {
+ int last_row = total_rows - 1;
assert(start_row <= last_row, "must be work left to do");
- // Test this row for both the receiver and for null.
+ // Test this row for both the item and for null.
// Take any of three different outcomes:
- // 1. found receiver => increment count and goto done
+ // 1. found item => increment count and goto done
// 2. found null => keep looking for case 1, maybe allocate this cell
// 3. found something else => keep looking for cases 1 and 2
// Case 3 is handled by a recursive call.
@@ -1677,28 +1724,28 @@
Label next_test;
bool test_for_null_also = (row == start_row);
- // See if the receiver is receiver[n].
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
- test_mdp_data_at(recvr_offset, receiver, next_test, scratch);
+ // See if the item is item[n].
+ int item_offset = in_bytes(item_offset_fn(row));
+ test_mdp_data_at(item_offset, item, next_test, scratch);
// delayed()->tst(scratch);
- // The receiver is receiver[n]. Increment count[n].
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+ // The receiver is item[n]. Increment count[n].
+ int count_offset = in_bytes(item_count_offset_fn(row));
increment_mdp_data_at(count_offset, scratch);
ba_short(done);
bind(next_test);
if (test_for_null_also) {
Label found_null;
- // Failed the equality check on receiver[n]... Test for null.
+ // Failed the equality check on item[n]... Test for null.
if (start_row == last_row) {
// The only thing left to do is handle the null case.
- if (is_virtual_call) {
+ if (non_profiled_offset >= 0) {
brx(Assembler::zero, false, Assembler::pn, found_null);
delayed()->nop();
- // Receiver did not match any saved receiver and there is no empty row for it.
+ // Item did not match any saved item and there is no empty row for it.
// Increment total counter to indicate polymorphic case.
- increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
+ increment_mdp_data_at(non_profiled_offset, scratch);
ba_short(done);
bind(found_null);
} else {
@@ -1712,21 +1759,22 @@
delayed()->nop();
// Put all the "Case 3" tests here.
- record_klass_in_profile_helper(receiver, scratch, start_row + 1, done, is_virtual_call);
-
- // Found a null. Keep searching for a matching receiver,
+ record_item_in_profile_helper(item, scratch, start_row + 1, done, total_rows,
+ item_offset_fn, item_count_offset_fn, non_profiled_offset);
+
+ // Found a null. Keep searching for a matching item,
// but remember that this is an empty (unused) slot.
bind(found_null);
}
}
- // In the fall-through case, we found no matching receiver, but we
- // observed the receiver[start_row] is NULL.
-
- // Fill in the receiver field and increment the count.
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
- set_mdp_data_at(recvr_offset, receiver);
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+ // In the fall-through case, we found no matching item, but we
+ // observed the item[start_row] is NULL.
+
+ // Fill in the item field and increment the count.
+ int item_offset = in_bytes(item_offset_fn(start_row));
+ set_mdp_data_at(item_offset, item);
+ int count_offset = in_bytes(item_count_offset_fn(start_row));
mov(DataLayout::counter_increment, scratch);
set_mdp_data_at(count_offset, scratch);
if (start_row > 0) {
@@ -1739,7 +1787,7 @@
assert(ProfileInterpreter, "must be profiling");
Label done;
- record_klass_in_profile_helper(receiver, scratch, 0, done, is_virtual_call);
+ record_klass_in_profile_helper(receiver, scratch, done, is_virtual_call);
bind (done);
}
@@ -1795,7 +1843,7 @@
// The method data pointer needs to be updated.
int mdp_delta = in_bytes(BitData::bit_data_size());
if (TypeProfileCasts) {
- mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+ mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
}
update_mdp_by_constant(mdp_delta);
@@ -1813,7 +1861,7 @@
int mdp_delta = in_bytes(BitData::bit_data_size());
if (TypeProfileCasts) {
- mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+ mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
// Record the object type.
record_klass_in_profile(klass, scratch, false);
@@ -1835,7 +1883,7 @@
int count_offset = in_bytes(CounterData::count_offset());
// Back up the address, since we have already bumped the mdp.
- count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
+ count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
// *Decrement* the counter. We expect to see zero or small negatives.
increment_mdp_data_at(count_offset, scratch, true);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -30,6 +30,8 @@
// This file specializes the assember with interpreter-specific macros
+typedef ByteSize (*OffsetFunction)(uint);
+
REGISTER_DECLARATION( Register, Otos_i , O0); // tos for ints, etc
REGISTER_DECLARATION( Register, Otos_l , O0); // for longs
REGISTER_DECLARATION( Register, Otos_l1, O0); // for 1st part of longs
@@ -301,7 +303,11 @@
void record_klass_in_profile(Register receiver, Register scratch, bool is_virtual_call);
void record_klass_in_profile_helper(Register receiver, Register scratch,
- int start_row, Label& done, bool is_virtual_call);
+ Label& done, bool is_virtual_call);
+ void record_item_in_profile_helper(Register item,
+ Register scratch, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset);
void update_mdp_by_offset(int offset_of_disp, Register scratch);
void update_mdp_by_offset(Register reg, int offset_of_disp,
@@ -314,6 +320,7 @@
void profile_call(Register scratch);
void profile_final_call(Register scratch);
void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false);
+ void profile_called_method(Register method, Register scratch) NOT_JVMCI_RETURN;
void profile_ret(TosState state, Register return_bci, Register scratch);
void profile_null_seen(Register scratch);
void profile_typecheck(Register klass, Register scratch);
--- a/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,7 +37,6 @@
address generate_accessor_entry(void) { return NULL; }
address generate_empty_entry(void) { return NULL; }
address generate_Reference_get_entry(void);
- void lock_method(void);
void save_native_result(void);
void restore_native_result(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_sparc.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ if (inst->is_call() || inst->is_jump()) {
+ return pc_offset + NativeCall::instruction_size;
+ } else if (inst->is_call_reg()) {
+ return pc_offset + NativeCallReg::instruction_size;
+ } else if (inst->is_sethi()) {
+ return pc_offset + NativeFarCall::instruction_size;
+ } else {
+ fatal("unsupported type of instruction for call site");
+ return 0;
+ }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ address pc = _instructions->start() + pc_offset;
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc, rspec, 1);
+#else
+ fatal("compressed oop on 32bit");
+#endif
+ } else {
+ NativeMovConstReg* move = nativeMovConstReg_at(pc);
+ move->set_data((intptr_t) value);
+
+ // We need two relocations: one on the sethi and one on the add.
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+ _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+ }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ address pc = _instructions->start() + pc_offset;
+ NativeInstruction* inst = nativeInstruction_at(pc);
+ NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
+ if(inst->is_sethi() && inst1->is_nop()) {
+ address const_start = _constants->start();
+ address dest = _constants->start() + data_offset;
+ if(_constants_size > 0) {
+ _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+ _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+ }
+ TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+ }else {
+ int const_size = align_size_up(_constants->end()-_constants->start(), CodeEntryAlignment);
+ NativeMovRegMem* load = nativeMovRegMem_at(pc);
+ // This offset must match with SPARCLoadConstantTableBaseOp.emitCode
+ load->set_offset(- (const_size - data_offset + Assembler::min_simm13()));
+ TRACE_jvmci_3("relocating ld at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+ }
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ address pc = (address) inst;
+ if (inst->is_call()) {
+ NativeCall* call = nativeCall_at(pc);
+ call->set_destination((address) foreign_call_destination);
+ _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+ } else if (inst->is_sethi()) {
+ NativeJump* jump = nativeJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+ } else {
+ fatal(err_msg("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)));
+ }
+ TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+ Method* method = NULL;
+ // we need to check, this might also be an unresolved method
+ if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ method = getMethodFromHotSpotMethod(hotspot_method);
+ }
+#endif
+ switch (_next_call_type) {
+ case INLINE_INVOKE:
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+ break;
+ }
+ case INVOKESTATIC: {
+ assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+ break;
+ }
+ case INVOKESPECIAL: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+ break;
+ }
+ default:
+ fatal("invalid _next_call_type value");
+ break;
+ }
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ switch (mark) {
+ case POLL_NEAR:
+ fatal("unimplemented");
+ break;
+ case POLL_FAR:
+ _instructions->relocate(pc, relocInfo::poll_type);
+ break;
+ case POLL_RETURN_NEAR:
+ fatal("unimplemented");
+ break;
+ case POLL_RETURN_FAR:
+ _instructions->relocate(pc, relocInfo::poll_return_type);
+ break;
+ default:
+ fatal("invalid mark value");
+ break;
+ }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ if (jvmci_reg < RegisterImpl::number_of_registers) {
+ return as_Register(jvmci_reg)->as_VMReg();
+ } else {
+ jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+ floatRegisterNumber += MAX2(0, floatRegisterNumber-32); // Beginning with f32, only every second register is going to be addressed
+ if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
+ return as_FloatRegister(floatRegisterNumber)->as_VMReg();
+ }
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return !hotspotRegister->is_FloatRegister();
+}
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -53,6 +53,7 @@
bool is_nop() { return long_at(0) == nop_instruction(); }
bool is_call() { return is_op(long_at(0), Assembler::call_op); }
+ bool is_call_reg() { return is_op(long_at(0), Assembler::arith_op); }
bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2)
&& inv_rd(long_at(0)) != G0); }
@@ -415,6 +416,19 @@
return call;
}
+class NativeCallReg: public NativeInstruction {
+ public:
+ enum Sparc_specific_constants {
+ instruction_size = 8,
+ return_address_offset = 8,
+ instruction_offset = 0
+ };
+
+ address next_instruction_address() const {
+ return addr_at(instruction_size);
+ }
+};
+
// The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere
// instructions in the sparcv9 vm. Used to call native methods which may be loaded
// anywhere in the address space, possibly out of reach of a call instruction.
--- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -197,8 +197,5 @@
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -43,6 +43,9 @@
#include "compiler/compileBroker.hpp"
#include "shark/sharkCompiler.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
#define __ masm->
@@ -513,10 +516,10 @@
const VMRegPair *regs,
Label& skip_fixup);
void gen_i2c_adapter(int total_args_passed,
- // VMReg max_arg,
- int comp_args_on_stack, // VMRegStackSlots
- const BasicType *sig_bt,
- const VMRegPair *regs);
+ // VMReg max_arg,
+ int comp_args_on_stack, // VMRegStackSlots
+ const BasicType *sig_bt,
+ const VMRegPair *regs);
AdapterGenerator(MacroAssembler *_masm) : masm(_masm) {}
};
@@ -760,13 +763,11 @@
__ bind(L_fail);
}
-void AdapterGenerator::gen_i2c_adapter(
- int total_args_passed,
- // VMReg max_arg,
- int comp_args_on_stack, // VMRegStackSlots
- const BasicType *sig_bt,
- const VMRegPair *regs) {
-
+void AdapterGenerator::gen_i2c_adapter(int total_args_passed,
+ // VMReg max_arg,
+ int comp_args_on_stack, // VMRegStackSlots
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Generate an I2C adapter: adjust the I-frame to make space for the C-frame
// layout. Lesp was saved by the calling I-frame and will be restored on
// return. Meanwhile, outgoing arg space is all owned by the callee
@@ -990,6 +991,21 @@
// Jump to the compiled code just as if compiled code was doing it.
__ ld_ptr(G5_method, in_bytes(Method::from_compiled_offset()), G3);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ // check if this call should be routed towards a specific entry point
+ __ ld(Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), G1);
+ __ cmp(G0, G1);
+ Label no_alternative_target;
+ __ br(Assembler::equal, false, Assembler::pn, no_alternative_target);
+ __ delayed()->nop();
+
+ __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset()), G3);
+ __ st(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+
+ __ bind(no_alternative_target);
+ }
+#endif // INCLUDE_JVMCI
// 6243940 We might end up in handle_wrong_method if
// the callee is deoptimized as we race thru here. If that
@@ -1006,6 +1022,15 @@
__ delayed()->nop();
}
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
+ AdapterGenerator agen(masm);
+ agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+}
+
// ---------------------------------------------------------------
AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int total_args_passed,
@@ -1016,9 +1041,7 @@
AdapterFingerPrint* fingerprint) {
address i2c_entry = __ pc();
- AdapterGenerator agen(masm);
-
- agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+ gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
// -------------------------------------------------------------------------
@@ -1063,7 +1086,7 @@
}
address c2i_entry = __ pc();
-
+ AdapterGenerator agen(masm);
agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, L_skip_fixup);
__ flush();
@@ -2916,6 +2939,11 @@
pad += StackShadowPages*16 + 32;
}
#endif
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ pad += 1000; // Increase the buffer size when compiling for JVMCI
+ }
+#endif
#ifdef _LP64
CodeBuffer buffer("deopt_blob", 2100+pad, 512);
#else
@@ -2982,6 +3010,45 @@
__ ba(cont);
__ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
+
+#if INCLUDE_JVMCI
+ Label after_fetch_unroll_info_call;
+ int implicit_exception_uncommon_trap_offset = 0;
+ int uncommon_trap_offset = 0;
+
+ if (EnableJVMCI) {
+ masm->block_comment("BEGIN implicit_exception_uncommon_trap");
+ implicit_exception_uncommon_trap_offset = __ offset() - start;
+
+ __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset()), O7);
+ __ st_ptr(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+ __ add(O7, -8, O7);
+
+ uncommon_trap_offset = __ offset() - start;
+
+ // Save everything in sight.
+ (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
+ __ set_last_Java_frame(SP, NULL);
+
+ __ ld(G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()), O1);
+ __ sub(G0, 1, L1);
+ __ st(L1, G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()));
+
+ __ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
+ __ mov(G2_thread, O0);
+ __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
+ __ delayed()->nop();
+ oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
+ __ get_thread();
+ __ add(O7, 8, O7);
+ __ reset_last_Java_frame();
+
+ __ ba(after_fetch_unroll_info_call);
+ __ delayed()->nop(); // Delay slot
+ masm->block_comment("END implicit_exception_uncommon_trap");
+ } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
int exception_offset = __ offset() - start;
// restore G2, the trampoline destroyed it
@@ -3004,6 +3071,7 @@
int exception_in_tls_offset = __ offset() - start;
// No need to update oop_map as each call to save_live_registers will produce identical oopmap
+ // Opens a new stack frame
(void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
// Restore G2_thread
@@ -3035,7 +3103,12 @@
// Reexecute entry, similar to c2 uncommon trap
//
int reexecute_offset = __ offset() - start;
-
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+ if (EnableJVMCI && UseJVMCICompiler) {
+ // JVMCI does not use this kind of deoptimization
+ __ should_not_reach_here();
+ }
+#endif
// No need to update oop_map as each call to save_live_registers will produce identical oopmap
(void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
@@ -3059,6 +3132,11 @@
__ reset_last_Java_frame();
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ __ bind(after_fetch_unroll_info_call);
+ }
+#endif
// NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
// so this move will survive
@@ -3124,6 +3202,12 @@
masm->flush();
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words);
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+ _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+ }
+#endif
}
#ifdef COMPILER2
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -204,6 +204,20 @@
address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
address entry = __ pc();
__ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
+#if INCLUDE_JVMCI
+ // Check if we need to take lock at entry of synchronized method.
+ if (UseJVMCICompiler) {
+ Label L;
+ Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
+ __ ldbool(pending_monitor_enter_addr, Gtemp); // Load if pending monitor enter
+ __ cmp_and_br_short(Gtemp, G0, Assembler::equal, Assembler::pn, L);
+ // Clear flag.
+ __ stbool(G0, pending_monitor_enter_addr);
+ // Take lock.
+ lock_method();
+ __ bind(L);
+ }
+#endif
{ Label L;
Address exception_addr(G2_thread, Thread::pending_exception_offset());
__ ld_ptr(exception_addr, Gtemp); // Load pending exception.
@@ -349,7 +363,7 @@
// Allocate monitor and lock method (asm interpreter)
// ebx - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
__ ld(Lmethod, in_bytes(Method::access_flags_offset()), O0); // Load access flags.
#ifdef ASSERT
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,9 +37,9 @@
#ifdef _LP64
// The sethi() instruction generates lots more instructions when shell
// stack limit is unlimited, so that's why this is much bigger.
- const static int InterpreterCodeSize = 210 * K;
+ const static int InterpreterCodeSize = 260 * K;
#else
- const static int InterpreterCodeSize = 180 * K;
+ const static int InterpreterCodeSize = 230 * K;
#endif
#endif // CPU_SPARC_VM_TEMPLATEINTERPRETER_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -2949,12 +2949,14 @@
void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
+ Register Rtemp = G4_scratch;
Register Rcall = Rindex;
assert_different_registers(Rcall, G5_method, Gargs, Rret);
// get target Method* & entry point
__ lookup_virtual_method(Rrecv, Rindex, G5_method);
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
+ __ profile_called_method(G5_method, Rtemp);
__ call_from_interpreter(Rcall, Gargs, Rret);
}
@@ -3211,6 +3213,7 @@
assert_different_registers(Rcall, G5_method, Gargs, Rret);
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
+ __ profile_called_method(G5_method, Rscratch);
__ call_from_interpreter(Rcall, Gargs, Rret);
}
@@ -3486,7 +3489,8 @@
Register RspecifiedKlass = O4;
// Check for casting a NULL
- __ br_null_short(Otos_i, Assembler::pn, is_null);
+ __ br_null(Otos_i, false, Assembler::pn, is_null);
+ __ delayed()->nop();
// Get value klass in RobjKlass
__ load_klass(Otos_i, RobjKlass); // get value klass
@@ -3542,7 +3546,8 @@
Register RspecifiedKlass = O4;
// Check for casting a NULL
- __ br_null_short(Otos_i, Assembler::pt, is_null);
+ __ br_null(Otos_i, false, Assembler::pt, is_null);
+ __ delayed()->nop();
// Get value klass in RobjKlass
__ load_klass(Otos_i, RobjKlass); // get value klass
--- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,10 +37,11 @@
/******************************/ \
/* JavaFrameAnchor */ \
/******************************/ \
- volatile_nonstatic_field(JavaFrameAnchor, _flags, int)
+ volatile_nonstatic_field(JavaFrameAnchor, _flags, int) \
+ static_field(VM_Version, _features, int)
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
-
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+ declare_toplevel_type(VM_Version)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
/******************************/ \
@@ -78,7 +79,11 @@
declare_c2_constant(R_G4_num) \
declare_c2_constant(R_G5_num) \
declare_c2_constant(R_G6_num) \
- declare_c2_constant(R_G7_num)
+ declare_c2_constant(R_G7_num) \
+ declare_constant(VM_Version::vis1_instructions_m) \
+ declare_constant(VM_Version::vis2_instructions_m) \
+ declare_constant(VM_Version::vis3_instructions_m) \
+ declare_constant(VM_Version::cbcond_instructions_m)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -29,6 +29,7 @@
#include "runtime/vm_version.hpp"
class VM_Version: public Abstract_VM_Version {
+ friend class VMStructs;
protected:
enum Feature_Flag {
v8_instructions = 0,
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -878,21 +878,35 @@
// Check second byte
NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions"));
+ int vex_opcode;
// First byte
if ((0xFF & *inst) == VEX_3bytes) {
+ vex_opcode = VEX_OPCODE_MASK & *ip;
ip++; // third byte
is_64bit = ((VEX_W & *ip) == VEX_W);
+ } else {
+ vex_opcode = VEX_OPCODE_0F;
}
ip++; // opcode
// To find the end of instruction (which == end_pc_operand).
- switch (0xFF & *ip) {
- case 0x61: // pcmpestri r, r/a, #8
- case 0x70: // pshufd r, r/a, #8
- case 0x73: // psrldq r, #8
- tail_size = 1; // the imm8
- break;
- default:
- break;
+ switch (vex_opcode) {
+ case VEX_OPCODE_0F:
+ switch (0xFF & *ip) {
+ case 0x70: // pshufd r, r/a, #8
+ case 0x71: // ps[rl|ra|ll]w r, #8
+ case 0x72: // ps[rl|ra|ll]d r, #8
+ case 0x73: // ps[rl|ra|ll]q r, #8
+ case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
+ case 0xC4: // pinsrw r, r, r/a, #8
+ case 0xC5: // pextrw r/a, r, #8
+ case 0xC6: // shufp[s|d] r, r, r/a, #8
+ tail_size = 1; // the imm8
+ break;
+ }
+ break;
+ case VEX_OPCODE_0F_3A:
+ tail_size = 1;
+ break;
}
ip++; // skip opcode
debug_only(has_disp32 = true); // has both kinds of operands!
@@ -2479,7 +2493,7 @@
void Assembler::movsbl(Register dst, Register src) { // movsxb
NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
- int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+ int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
emit_int8(0x0F);
emit_int8((unsigned char)0xBE);
emit_int8((unsigned char)(0xC0 | encode));
@@ -2596,7 +2610,7 @@
void Assembler::movzbl(Register dst, Register src) { // movzxb
NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
- int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+ int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
emit_int8(0x0F);
emit_int8((unsigned char)0xB6);
emit_int8(0xC0 | encode);
@@ -6510,12 +6524,12 @@
return reg_enc;
}
-int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) {
+int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) {
if (dst_enc < 8) {
if (src_enc >= 8) {
prefix(REX_B);
src_enc -= 8;
- } else if (byteinst && src_enc >= 4) {
+ } else if ((src_is_byte && src_enc >= 4) || (dst_is_byte && dst_enc >= 4)) {
prefix(REX);
}
} else {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -536,7 +536,8 @@
VEX_OPCODE_NONE = 0x0,
VEX_OPCODE_0F = 0x1,
VEX_OPCODE_0F_38 = 0x2,
- VEX_OPCODE_0F_3A = 0x3
+ VEX_OPCODE_0F_3A = 0x3,
+ VEX_OPCODE_MASK = 0x1F
};
enum AvxVectorLen {
@@ -612,7 +613,10 @@
int prefix_and_encode(int reg_enc, bool byteinst = false);
int prefixq_and_encode(int reg_enc);
- int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false);
+ int prefix_and_encode(int dst_enc, int src_enc) {
+ return prefix_and_encode(dst_enc, false, src_enc, false);
+ }
+ int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte);
int prefixq_and_encode(int dst_enc, int src_enc);
void prefix(Register reg);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -33,7 +33,7 @@
inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { return reg_enc; }
inline int Assembler::prefixq_and_encode(int reg_enc) { return reg_enc; }
-inline int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { return dst_enc << 3 | src_enc; }
+inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) { return dst_enc << 3 | src_enc; }
inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { return dst_enc << 3 | src_enc; }
inline void Assembler::prefix(Register reg) {}
--- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -50,13 +50,15 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// movq rbx, 0
// jmp -5 # to self
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
@@ -73,6 +75,8 @@
// This is recognized as unresolved by relocs/nativeinst/ic code.
__ jump(RuntimeAddress(__ pc()));
+ assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
// Update current stubs pointer and restore insts_end.
__ end_a_stub();
return base;
@@ -104,10 +108,15 @@
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
- assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(),
+#ifdef ASSERT
+ // read the value once
+ intptr_t data = method_holder->data();
+ address destination = jump->jump_destination();
+ assert(data == 0 || data == (intptr_t)callee(),
"a) MT-unsafe modification of inline cache");
- assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry,
+ assert(destination == (address)-1 || destination == entry,
"b) MT-unsafe modification of inline cache");
+#endif
// Update stub.
method_holder->set_data((intptr_t)callee());
@@ -124,11 +133,12 @@
assert(stub != NULL, "stub not found");
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
method_holder->set_data(0);
+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
jump->set_jump_destination((address)-1);
}
+
//-----------------------------------------------------------------------------
// Non-product mode code
#ifndef PRODUCT
@@ -150,5 +160,4 @@
// Verify state.
assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
}
-
#endif // !PRODUCT
--- a/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -29,6 +29,7 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
address generate_interpreter_frame_manager(bool synchronized); // C++ interpreter only
void generate_compute_interpreter_state(const Register state,
const Register prev_state,
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -741,7 +741,7 @@
// Find preallocated monitor and lock method (C++ interpreter)
// rbx - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void CppInterpreterGenerator::lock_method() {
// assumes state == rsi/r13 == pointer to current interpreterState
// minimally destroys rax, rdx|c_rarg1, rdi
//
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -458,11 +458,11 @@
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}
@@ -683,10 +683,19 @@
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
-#endif
+#ifdef AMD64
+ } else if (is_entry_frame()) {
+ // This could be more descriptive if we use the enum in
+ // stubGenerator to map to real names but it's most important to
+ // claim these frame slots so the error checking works.
+ for (int i = 0; i < entry_frame_after_call_words; i++) {
+ values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
+ }
+#endif // AMD64
}
+#endif
}
-#endif
+#endif // !PRODUCT
intptr_t *frame::initial_deoptimization_info() {
// used to reset the saved FP
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -78,7 +78,11 @@
assert(((nmethod*)_cb)->insts_contains(_pc), "original PC must be in nmethod");
_deopt_state = is_deoptimized;
} else {
- _deopt_state = not_deoptimized;
+ if (_cb->is_deoptimization_stub()) {
+ _deopt_state = is_deoptimized;
+ } else {
+ _deopt_state = not_deoptimized;
+ }
}
}
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -46,7 +46,7 @@
// the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
// the uep and the vep doesn't get real alignment but just slops on by
// only assured that the entry instruction meets the 5 byte size requirement.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
define_pd_global(intx, CodeEntryAlignment, 32);
#else
define_pd_global(intx, CodeEntryAlignment, 16);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1502,13 +1502,39 @@
bind(skip_receiver_profile);
// The method data pointer needs to be updated to reflect the new target.
+#if INCLUDE_JVMCI
+ if (MethodProfileWidth == 0) {
+ update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+ }
+#else // INCLUDE_JVMCI
update_mdp_by_constant(mdp,
in_bytes(VirtualCallData::
virtual_call_data_size()));
+#endif // INCLUDE_JVMCI
bind(profile_continue);
}
}
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) {
+ assert_different_registers(method, mdp, reg2);
+ if (ProfileInterpreter && MethodProfileWidth > 0) {
+ Label profile_continue;
+
+ // If no method data exists, go to profile_continue.
+ test_method_data_pointer(mdp, profile_continue);
+
+ Label done;
+ record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth,
+ &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+ bind(done);
+
+ update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+ bind(profile_continue);
+ }
+}
+#endif // INCLUDE_JVMCI
+
// This routine creates a state machine for updating the multi-row
// type profile at a virtual call site (or other type-sensitive bytecode).
// The machine visits each row (of receiver/count) until the receiver type
@@ -1528,14 +1554,36 @@
if (is_virtual_call) {
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
}
- return;
- }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()));
+ }
+#endif // INCLUDE_JVMCI
+ } else {
+ int non_profiled_offset = -1;
+ if (is_virtual_call) {
+ non_profiled_offset = in_bytes(CounterData::count_offset());
+ }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+ }
+#endif // INCLUDE_JVMCI
- int last_row = VirtualCallData::row_limit() - 1;
+ record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
+ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
+ }
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
+ Register reg2, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset) {
+ int last_row = total_rows - 1;
assert(start_row <= last_row, "must be work left to do");
- // Test this row for both the receiver and for null.
+ // Test this row for both the item and for null.
// Take any of three different outcomes:
- // 1. found receiver => increment count and goto done
+ // 1. found item => increment count and goto done
// 2. found null => keep looking for case 1, maybe allocate this cell
// 3. found something else => keep looking for cases 1 and 2
// Case 3 is handled by a recursive call.
@@ -1543,30 +1591,30 @@
Label next_test;
bool test_for_null_also = (row == start_row);
- // See if the receiver is receiver[n].
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
- test_mdp_data_at(mdp, recvr_offset, receiver,
+ // See if the item is item[n].
+ int item_offset = in_bytes(item_offset_fn(row));
+ test_mdp_data_at(mdp, item_offset, item,
(test_for_null_also ? reg2 : noreg),
next_test);
- // (Reg2 now contains the receiver from the CallData.)
+ // (Reg2 now contains the item from the CallData.)
- // The receiver is receiver[n]. Increment count[n].
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+ // The item is item[n]. Increment count[n].
+ int count_offset = in_bytes(item_count_offset_fn(row));
increment_mdp_data_at(mdp, count_offset);
jmp(done);
bind(next_test);
if (test_for_null_also) {
Label found_null;
- // Failed the equality check on receiver[n]... Test for null.
+ // Failed the equality check on item[n]... Test for null.
testptr(reg2, reg2);
if (start_row == last_row) {
// The only thing left to do is handle the null case.
- if (is_virtual_call) {
+ if (non_profiled_offset >= 0) {
jccb(Assembler::zero, found_null);
- // Receiver did not match any saved receiver and there is no empty row for it.
+ // Item did not match any saved item and there is no empty row for it.
// Increment total counter to indicate polymorphic case.
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+ increment_mdp_data_at(mdp, non_profiled_offset);
jmp(done);
bind(found_null);
} else {
@@ -1578,21 +1626,22 @@
jcc(Assembler::zero, found_null);
// Put all the "Case 3" tests here.
- record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
+ record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
+ item_offset_fn, item_count_offset_fn, non_profiled_offset);
- // Found a null. Keep searching for a matching receiver,
+ // Found a null. Keep searching for a matching item,
// but remember that this is an empty (unused) slot.
bind(found_null);
}
}
- // In the fall-through case, we found no matching receiver, but we
- // observed the receiver[start_row] is NULL.
+ // In the fall-through case, we found no matching item, but we
+ // observed the item[start_row] is NULL.
- // Fill in the receiver field and increment the count.
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
- set_mdp_data_at(mdp, recvr_offset, receiver);
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+ // Fill in the item field and increment the count.
+ int item_offset = in_bytes(item_offset_fn(start_row));
+ set_mdp_data_at(mdp, item_offset, item);
+ int count_offset = in_bytes(item_count_offset_fn(start_row));
movl(reg2, DataLayout::counter_increment);
set_mdp_data_at(mdp, count_offset, reg2);
if (start_row > 0) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -32,6 +32,7 @@
// This file specializes the assember with interpreter-specific macros
+typedef ByteSize (*OffsetFunction)(uint);
class InterpreterMacroAssembler: public MacroAssembler {
@@ -251,6 +252,10 @@
void record_klass_in_profile_helper(Register receiver, Register mdp,
Register reg2, int start_row,
Label& done, bool is_virtual_call);
+ void record_item_in_profile_helper(Register item, Register mdp,
+ Register reg2, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset);
void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
@@ -264,6 +269,7 @@
void profile_virtual_call(Register receiver, Register mdp,
Register scratch2,
bool receiver_can_be_null = false);
+ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN;
void profile_ret(Register return_bci, Register mdp);
void profile_null_seen(Register mdp);
void profile_typecheck(Register mdp, Register klass, Register scratch);
--- a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -48,7 +48,6 @@
address generate_Double_longBitsToDouble_entry();
address generate_Double_doubleToRawLongBits_entry();
#endif
- void lock_method(void);
void generate_stack_overflow_check(void);
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+#include "vmreg_x86.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ if (inst->is_call() || inst->is_jump()) {
+ assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+ return (pc_offset + NativeCall::instruction_size);
+ } else if (inst->is_mov_literal64()) {
+ // mov+call instruction pair
+ jint offset = pc_offset + NativeMovConstReg::instruction_size;
+ u_char* call = (u_char*) (_instructions->start() + offset);
+ if (call[0] == Assembler::REX_B) {
+ offset += 1; /* prefix byte for extended register R8-R15 */
+ call++;
+ }
+ assert(call[0] == 0xFF, "expected call");
+ offset += 2; /* opcode byte + modrm byte */
+ return (offset);
+ } else if (inst->is_call_reg()) {
+ // the inlined vtable stub contains a "call register" instruction
+ assert(method != NULL, "only valid for virtual calls");
+ return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+ } else if (inst->is_cond_jump()) {
+ address pc = (address) (inst);
+ return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
+ } else {
+ fatal("unsupported type of instruction for call site");
+ return 0;
+ }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ address pc = _instructions->start() + pc_offset;
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+ address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+ int oop_index = _oop_recorder->find_index(value);
+ _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+ TRACE_jvmci_3("relocating (narrow oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+#else
+ fatal("compressed oop on 32bit");
+#endif
+ } else {
+ address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+ *((jobject*) operand) = value;
+ _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+ TRACE_jvmci_3("relocating (oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+ }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ address pc = _instructions->start() + pc_offset;
+
+ address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+ address next_instruction = Assembler::locate_next_instruction(pc);
+ address dest = _constants->start() + data_offset;
+
+ long disp = dest - next_instruction;
+ assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+ *((jint*) operand) = (jint) disp;
+
+ _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+ TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ if (cb->is_nmethod()) {
+ nmethod* nm = (nmethod*) cb;
+ nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+ } else {
+ nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+ }
+ _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ address pc = (address) inst;
+ if (inst->is_call()) {
+ // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+ // see also CompilerToVM.getMaxCallTargetOffset()
+ NativeCall* call = nativeCall_at(pc);
+ call->set_destination((address) foreign_call_destination);
+ _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else if (inst->is_mov_literal64()) {
+ NativeMovConstReg* mov = nativeMovConstReg_at(pc);
+ mov->set_data((intptr_t) foreign_call_destination);
+ _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+ } else if (inst->is_jump()) {
+ NativeJump* jump = nativeJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else if (inst->is_cond_jump()) {
+ address old_dest = nativeGeneralJump_at(pc)->jump_destination();
+ address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
+ *(jint*) disp += ((address) foreign_call_destination) - old_dest;
+ _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else {
+ fatal("unsupported relocation for foreign call");
+ }
+
+ TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+ Method* method = NULL;
+ // we need to check, this might also be an unresolved method
+ if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ method = getMethodFromHotSpotMethod(hotspot_method);
+ }
+#endif
+ switch (_next_call_type) {
+ case INLINE_INVOKE:
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ virtual_call_Relocation::spec(_invoke_mark_pc),
+ Assembler::call32_operand);
+ break;
+ }
+ case INVOKESTATIC: {
+ assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ relocInfo::static_call_type, Assembler::call32_operand);
+ break;
+ }
+ case INVOKESPECIAL: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void relocate_poll_near(address pc) {
+ NativeInstruction* ni = nativeInstruction_at(pc);
+ int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+ int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+ intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+ *disp = (int32_t)new_disp;
+}
+
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ switch (mark) {
+ case POLL_NEAR: {
+ relocate_poll_near(pc);
+ _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
+ break;
+ }
+ case POLL_FAR:
+ // This is a load from a register so there is no relocatable operand.
+ // We just have to ensure that the format is not disp32_operand
+ // so that poll_Relocation::fix_relocation_after_move does the right
+ // thing (i.e. ignores this relocation record)
+ _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
+ break;
+ case POLL_RETURN_NEAR: {
+ relocate_poll_near(pc);
+ _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
+ break;
+ }
+ case POLL_RETURN_FAR:
+ // see comment above for POLL_FAR
+ _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
+ break;
+ default:
+ fatal("invalid mark value");
+ break;
+ }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ if (jvmci_reg < RegisterImpl::number_of_registers) {
+ return as_Register(jvmci_reg)->as_VMReg();
+ } else {
+ jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+ if (floatRegisterNumber < XMMRegisterImpl::number_of_registers) {
+ return as_XMMRegister(floatRegisterNumber)->as_VMReg();
+ }
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_XMMRegister());
+}
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -2889,7 +2889,7 @@
}
// !defined(COMPILER2) is because of stupid core builds
-#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2)
+#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) || INCLUDE_JVMCI
void MacroAssembler::empty_FPU_stack() {
if (VM_Version::supports_mmx()) {
emms();
@@ -2897,7 +2897,7 @@
for (int i = 8; i-- > 0; ) ffree(i);
}
}
-#endif // !LP64 || C1 || !C2
+#endif // !LP64 || C1 || !C2 || INCLUDE_JVMCI
// Defines obj, preserves var_size_in_bytes
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -41,7 +41,6 @@
ICache::invalidate_word(addr_at(offset));
}
-
void NativeCall::verify() {
// Make sure code pattern is actually a call imm32 instruction.
int inst = ubyte_at(0);
@@ -474,6 +473,7 @@
//
// In C2 the 5+ byte sized instruction is enforced by code in MachPrologNode::emit.
// In C1 the restriction is enforced by CodeEmitter::method_entry
+// In JVMCI, the restriction is enforced by HotSpotFrameContext.enter(...)
//
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
// complete jump instruction (to be inserted) is in code_buffer;
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -60,6 +60,7 @@
bool is_nop() { return ubyte_at(0) == nop_instruction_code; }
inline bool is_call();
+ inline bool is_call_reg();
inline bool is_illegal();
inline bool is_return();
inline bool is_jump();
@@ -180,6 +181,24 @@
return call;
}
+class NativeCallReg: public NativeInstruction {
+ public:
+ enum Intel_specific_constants {
+ instruction_code = 0xFF,
+ instruction_offset = 0,
+ return_address_offset_norex = 2,
+ return_address_offset_rex = 3
+ };
+
+ int next_instruction_offset() const {
+ if (ubyte_at(0) == NativeCallReg::instruction_code) {
+ return return_address_offset_norex;
+ } else {
+ return return_address_offset_rex;
+ }
+ }
+};
+
// An interface for accessing/manipulating native mov reg, imm32 instructions.
// (used to manipulate inlined 32bit data dll calls, etc.)
class NativeMovConstReg: public NativeInstruction {
@@ -519,6 +538,9 @@
inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; }
+inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code ||
+ (ubyte_at(1) == NativeCallReg::instruction_code &&
+ (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code ||
ubyte_at(0) == NativeReturnX::instruction_code; }
inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code ||
@@ -527,26 +549,24 @@
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
inline bool NativeInstruction::is_safepoint_poll() {
#ifdef AMD64
- if (Assembler::is_polling_page_far()) {
- // two cases, depending on the choice of the base register in the address.
- if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
- ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
- (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
- ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
- (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
- return true;
- } else {
- return false;
- }
- } else {
- if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
- ubyte_at(1) == 0x05) { // 00 rax 101
- address fault = addr_at(6) + int_at(2);
- return os::is_poll_address(fault);
- } else {
- return false;
- }
+ // Try decoding a near safepoint first:
+ if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+ ubyte_at(1) == 0x05) { // 00 rax 101
+ address fault = addr_at(6) + int_at(2);
+ NOT_JVMCI(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
+ return os::is_poll_address(fault);
}
+ // Now try decoding a far safepoint:
+ // two cases, depending on the choice of the base register in the address.
+ if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
+ ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
+ (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
+ ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+ (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
+ NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
+ return true;
+ }
+ return false;
#else
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/registerMap_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/registerMap.hpp"
+#include "vmreg_x86.inline.hpp"
+
+address RegisterMap::pd_location(VMReg reg) const {
+ if (reg->is_XMMRegister()) {
+ int regBase = reg->value() - ConcreteRegisterImpl::max_fpr;
+ if (regBase % 4 == 0) {
+ // Reads of the low and high 16 byte parts should be handled by location itself
+ // because they have separate callee saved entries.
+ // See RegisterSaver::save_live_registers().
+ return NULL;
+ }
+ VMReg baseReg = as_XMMRegister(regBase / XMMRegisterImpl::max_slots_per_register)->as_VMReg();
+ intptr_t offset = (reg->value() - baseReg->value()) * VMRegImpl::stack_slot_size; // offset in bytes
+ if (offset >= 16) {
+ // The high part of YMM registers are saved in a their own area in the frame
+ baseReg = baseReg->next()->next()->next()->next();
+ offset -= 16;
+ }
+ address baseLocation = location(baseReg);
+ if (baseLocation != NULL) {
+ return baseLocation + offset;
+ }
+ }
+ return NULL;
+}
--- a/hotspot/src/cpu/x86/vm/registerMap_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/registerMap_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -31,11 +31,7 @@
private:
// This is the hook for finding a register in an "well-known" location,
// such as a register block of a predetermined format.
- // Since there is none, we just return NULL.
- // See registerMap_sparc.hpp for an example of grabbing registers
- // from register save areas of a standard layout.
- address pd_location(VMReg reg) const {return NULL;}
-
+ address pd_location(VMReg reg) const;
// no PD state to clear or copy:
void pd_clear() {}
void pd_initialize() {}
--- a/hotspot/src/cpu/x86/vm/register_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/register_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -69,6 +69,31 @@
return is_valid() ? names[encoding()] : "xnoreg";
}
+const char* XMMRegisterImpl::sub_word_name(int i) const {
+ const char* names[number_of_registers * 8] = {
+ "xmm0:0", "xmm0:1", "xmm0:2", "xmm0:3", "xmm0:4", "xmm0:5", "xmm0:6", "xmm0:7",
+ "xmm1:0", "xmm1:1", "xmm1:2", "xmm1:3", "xmm1:4", "xmm1:5", "xmm1:6", "xmm1:7",
+ "xmm2:0", "xmm2:1", "xmm2:2", "xmm2:3", "xmm2:4", "xmm2:5", "xmm2:6", "xmm2:7",
+ "xmm3:0", "xmm3:1", "xmm3:2", "xmm3:3", "xmm3:4", "xmm3:5", "xmm3:6", "xmm3:7",
+ "xmm4:0", "xmm4:1", "xmm4:2", "xmm4:3", "xmm4:4", "xmm4:5", "xmm4:6", "xmm4:7",
+ "xmm5:0", "xmm5:1", "xmm5:2", "xmm5:3", "xmm5:4", "xmm5:5", "xmm5:6", "xmm5:7",
+ "xmm6:0", "xmm6:1", "xmm6:2", "xmm6:3", "xmm6:4", "xmm6:5", "xmm6:6", "xmm6:7",
+ "xmm7:0", "xmm7:1", "xmm7:2", "xmm7:3", "xmm7:4", "xmm7:5", "xmm7:6", "xmm7:7",
+#ifdef AMD64
+ "xmm8:0", "xmm8:1", "xmm8:2", "xmm8:3", "xmm8:4", "xmm8:5", "xmm8:6", "xmm8:7",
+ "xmm9:0", "xmm9:1", "xmm9:2", "xmm9:3", "xmm9:4", "xmm9:5", "xmm9:6", "xmm9:7",
+ "xmm10:0", "xmm10:1", "xmm10:2", "xmm10:3", "xmm10:4", "xmm10:5", "xmm10:6", "xmm10:7",
+ "xmm11:0", "xmm11:1", "xmm11:2", "xmm11:3", "xmm11:4", "xmm11:5", "xmm11:6", "xmm11:7",
+ "xmm12:0", "xmm12:1", "xmm12:2", "xmm12:3", "xmm12:4", "xmm12:5", "xmm12:6", "xmm12:7",
+ "xmm13:0", "xmm13:1", "xmm13:2", "xmm13:3", "xmm13:4", "xmm13:5", "xmm13:6", "xmm13:7",
+ "xmm14:0", "xmm14:1", "xmm14:2", "xmm14:3", "xmm14:4", "xmm14:5", "xmm14:6", "xmm14:7",
+ "xmm15:0", "xmm15:1", "xmm15:2", "xmm15:3", "xmm15:4", "xmm15:5", "xmm15:6", "xmm15:7",
+#endif // AMD64
+ };
+ assert(i >= 0 && i < 8, "offset too large");
+ return is_valid() ? names[encoding() * 8 + i] : "xnoreg";
+}
+
const char* KRegisterImpl::name() const {
const char* names[number_of_registers] = {
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
--- a/hotspot/src/cpu/x86/vm/register_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/register_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -165,6 +165,7 @@
int encoding() const { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this )); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
const char* name() const;
+ const char* sub_word_name(int offset) const;
};
--- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -180,39 +180,17 @@
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
#ifdef _LP64
- if (!Assembler::is_polling_page_far()) {
- typedef Assembler::WhichOperand WhichOperand;
- WhichOperand which = (WhichOperand) format();
- // This format is imm but it is really disp32
- which = Assembler::disp32_operand;
+ typedef Assembler::WhichOperand WhichOperand;
+ WhichOperand which = (WhichOperand) format();
+#if !INCLUDE_JVMCI
+ assert((which == Assembler::disp32_operand) == !Assembler::is_polling_page_far(), "format not set correctly");
+#endif
+ if (which == Assembler::disp32_operand) {
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
-
- NativeInstruction* ni = nativeInstruction_at(addr());
- intptr_t new_disp = poll_addr - (intptr_t) ni;
-
- int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
- * disp = (int32_t)new_disp;
- }
-#endif // _LP64
-}
-
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-#ifdef _LP64
- if (!Assembler::is_polling_page_far()) {
- typedef Assembler::WhichOperand WhichOperand;
- WhichOperand which = (WhichOperand) format();
- // This format is imm but it is really disp32
- which = Assembler::disp32_operand;
- address orig_addr = old_addr_for(addr(), src, dest);
- NativeInstruction* oni = nativeInstruction_at(orig_addr);
- int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
- // This poll_addr is incorrect by the size of the instruction it is irrelevant
- intptr_t poll_addr = (intptr_t)oni + *orig_disp;
-
NativeInstruction* ni = nativeInstruction_at(addr());
intptr_t new_disp = poll_addr - (intptr_t) ni;
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -699,12 +699,11 @@
__ bind(L_fail);
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
-
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: rsi contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
// code goes non-entrant while we get args ready.
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -43,6 +43,9 @@
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
#define __ masm->
@@ -158,23 +161,25 @@
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
+ int ymmhi_offset = -1;
int off = 0;
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (save_vectors) {
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
if (UseAVX < 3) {
+ ymmhi_offset = additional_frame_words;
additional_frame_words += vect_words;
}
}
#else
- assert(!save_vectors, "vectors are generated only by C2");
+ assert(!save_vectors, "vectors are generated only by C2 and JVMCI");
#endif
// Always make the frame size 16-byte aligned
@@ -220,6 +225,7 @@
OopMap* map = new OopMap(frame_size_in_slots, 0);
#define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_slots)
+#define YMMHI_STACK_OFFSET(x) VMRegImpl::stack2reg((x / VMRegImpl::stack_slot_size) + ymmhi_offset)
map->set_callee_saved(STACK_OFFSET( rax_off ), rax->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rcx_off ), rcx->as_VMReg());
@@ -257,6 +263,28 @@
}
}
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ if (save_vectors) {
+ assert(ymmhi_offset != -1, "save area must exist");
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 0), xmm0->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 16), xmm1->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 32), xmm2->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 48), xmm3->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 64), xmm4->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 80), xmm5->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 96), xmm6->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(112), xmm7->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(128), xmm8->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(144), xmm9->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(160), xmm10->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(176), xmm11->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(192), xmm12->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(208), xmm13->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(224), xmm14->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(240), xmm15->as_VMReg()->next(4));
+ }
+#endif // COMPILER2 || INCLUDE_JVMCI
+
// %%% These should all be a waste but we'll keep things as they were for now
if (true) {
map->set_callee_saved(STACK_OFFSET( raxH_off ), rax->as_VMReg()->next());
@@ -307,7 +335,7 @@
// Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
// On EVEX enabled targets everything is handled in pop fpu state
if ((restore_vectors) && (UseAVX < 3)) {
assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
@@ -320,7 +348,7 @@
__ addptr(rsp, num_xmm_regs*16);
}
#else
- assert(!restore_vectors, "vectors are generated only by C2");
+ assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
#endif
// Recover CPU state
__ pop_CPU_state();
@@ -655,11 +683,11 @@
__ bind(L_fail);
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: r13 contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
@@ -752,6 +780,18 @@
// Pre-load the register-jump target early, to schedule it better.
__ movptr(r11, Address(rbx, in_bytes(Method::from_compiled_offset())));
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ // check if this call should be routed towards a specific entry point
+ __ cmpptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+ Label no_alternative_target;
+ __ jcc(Assembler::equal, no_alternative_target);
+ __ movptr(r11, Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+ __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+ __ bind(no_alternative_target);
+ }
+#endif // INCLUDE_JVMCI
+
// Now generate the shuffle code. Pick up all register args and move the
// rest through the floating point stack top.
for (int i = 0; i < total_args_passed; i++) {
@@ -2685,7 +2725,13 @@
// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
- CodeBuffer buffer("deopt_blob", 2048, 1024);
+ int pad = 0;
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ pad += 512; // Increase the buffer size when compiling for JVMCI
+ }
+#endif
+ CodeBuffer buffer("deopt_blob", 2048+pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words;
OopMap* map = NULL;
@@ -2734,6 +2780,12 @@
__ jmp(cont);
int reexecute_offset = __ pc() - start;
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+ if (EnableJVMCI && UseJVMCICompiler) {
+ // JVMCI does not use this kind of deoptimization
+ __ should_not_reach_here();
+ }
+#endif
// Reexecute case
// return address is the pc describes what bci to do re-execute at
@@ -2744,6 +2796,38 @@
__ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved
__ jmp(cont);
+#if INCLUDE_JVMCI
+ Label after_fetch_unroll_info_call;
+ int implicit_exception_uncommon_trap_offset = 0;
+ int uncommon_trap_offset = 0;
+
+ if (EnableJVMCI) {
+ implicit_exception_uncommon_trap_offset = __ pc() - start;
+
+ __ pushptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+ __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())), (int32_t)NULL_WORD);
+
+ uncommon_trap_offset = __ pc() - start;
+
+ // Save everything in sight.
+ RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+ // fetch_unroll_info needs to call last_java_frame()
+ __ set_last_Java_frame(noreg, noreg, NULL);
+
+ __ movl(c_rarg1, Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())));
+ __ movl(Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())), -1);
+
+ __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
+ __ mov(c_rarg0, r15_thread);
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
+ oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
+
+ __ reset_last_Java_frame(false, false);
+
+ __ jmp(after_fetch_unroll_info_call);
+ } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
int exception_offset = __ pc() - start;
// Prolog for exception case
@@ -2829,6 +2913,12 @@
__ reset_last_Java_frame(false, false);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ __ bind(after_fetch_unroll_info_call);
+ }
+#endif
+
// Load UnrollBlock* into rdi
__ mov(rdi, rax);
@@ -3003,6 +3093,12 @@
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+ _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+ }
+#endif
}
#ifdef COMPILER2
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -538,7 +538,7 @@
// Allocate monitor and lock method (asm interpreter)
// rbx, - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags (rbx, Method::access_flags_offset());
const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -198,13 +198,27 @@
}
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
- int step) {
+address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
address entry = __ pc();
// NULL last_sp until next java call
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
__ restore_bcp();
__ restore_locals();
+#if INCLUDE_JVMCI
+ // Check if we need to take lock at entry of synchronized method.
+ if (UseJVMCICompiler) {
+ Label L;
+ __ cmpb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+ __ jcc(Assembler::zero, L);
+ // Clear flag.
+ __ movb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+ // Satisfy calling convention for lock_method().
+ __ get_method(rbx);
+ // Take lock.
+ lock_method();
+ __ bind(L);
+ }
+#endif
// handle exceptions
{
Label L;
@@ -500,7 +514,7 @@
// rax
// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs)
// rscratch1, rscratch2 (scratch regs)
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags(rbx, Method::access_flags_offset());
const Address monitor_block_top(
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -3595,6 +3595,8 @@
__ profile_virtual_call(rax, rlocals, rdx);
// get target Method* & entry point
__ lookup_virtual_method(rax, index, method);
+ __ profile_called_method(method, rdx, rbcp);
+
__ profile_arguments_type(rdx, method, rbcp, true);
__ jump_from_interpreted(method, rdx);
}
@@ -3694,6 +3696,7 @@
__ testptr(rbx, rbx);
__ jcc(Assembler::zero, no_such_method);
+ __ profile_called_method(rbx, rbcp, rdx);
__ profile_arguments_type(rdx, rbx, rbcp, true);
// do the call
--- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,13 +37,50 @@
/******************************/ \
/* JavaFrameAnchor */ \
/******************************/ \
- volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*)
+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \
+ static_field(VM_Version, _cpuFeatures, uint64_t)
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+ declare_toplevel_type(VM_Version)
-#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
+ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \
+ declare_constant(frame::interpreter_frame_sender_sp_offset) \
+ declare_constant(frame::interpreter_frame_last_sp_offset) \
+ declare_constant(VM_Version::CPU_CX8) \
+ declare_constant(VM_Version::CPU_CMOV) \
+ declare_constant(VM_Version::CPU_FXSR) \
+ declare_constant(VM_Version::CPU_HT) \
+ declare_constant(VM_Version::CPU_MMX) \
+ declare_constant(VM_Version::CPU_3DNOW_PREFETCH) \
+ declare_constant(VM_Version::CPU_SSE) \
+ declare_constant(VM_Version::CPU_SSE2) \
+ declare_constant(VM_Version::CPU_SSE3) \
+ declare_constant(VM_Version::CPU_SSSE3) \
+ declare_constant(VM_Version::CPU_SSE4A) \
+ declare_constant(VM_Version::CPU_SSE4_1) \
+ declare_constant(VM_Version::CPU_SSE4_2) \
+ declare_constant(VM_Version::CPU_POPCNT) \
+ declare_constant(VM_Version::CPU_LZCNT) \
+ declare_constant(VM_Version::CPU_TSC) \
+ declare_constant(VM_Version::CPU_TSCINV) \
+ declare_constant(VM_Version::CPU_AVX) \
+ declare_constant(VM_Version::CPU_AVX2) \
+ declare_constant(VM_Version::CPU_AES) \
+ declare_constant(VM_Version::CPU_ERMS) \
+ declare_constant(VM_Version::CPU_CLMUL) \
+ declare_constant(VM_Version::CPU_BMI1) \
+ declare_constant(VM_Version::CPU_BMI2) \
+ declare_constant(VM_Version::CPU_RTM) \
+ declare_constant(VM_Version::CPU_ADX) \
+ declare_constant(VM_Version::CPU_AVX512F) \
+ declare_constant(VM_Version::CPU_AVX512DQ) \
+ declare_constant(VM_Version::CPU_AVX512PF) \
+ declare_constant(VM_Version::CPU_AVX512ER) \
+ declare_constant(VM_Version::CPU_AVX512CD) \
+ declare_constant(VM_Version::CPU_AVX512BW)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -787,6 +787,8 @@
FLAG_SET_DEFAULT(UseFPUForSpilling, false);
}
}
+#endif
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
@@ -803,7 +805,7 @@
// Vectors (in XMM) are only supported with SSE2+
FLAG_SET_DEFAULT(MaxVectorSize, 0);
}
-#ifdef ASSERT
+#if defined(COMPILER2) && defined(ASSERT)
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
int nreg = 2 LP64_ONLY(+2);
@@ -816,9 +818,11 @@
tty->cr();
}
}
-#endif
+#endif // COMPILER2 && ASSERT
}
+#endif // COMPILER2 || INCLUDE_JVMCI
+#ifdef COMPILER2
#ifdef _LP64
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -29,6 +29,7 @@
#include "runtime/vm_version.hpp"
class VM_Version : public Abstract_VM_Version {
+ friend class VMStructs;
public:
// cpuid result register layouts. These are all unions of a uint32_t
// (in case anyone wants access to the register as a whole) and a bitfield.
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Thu Oct 08 12:49:30 2015 -1000
@@ -2136,12 +2136,13 @@
RELOC_DISP32);
}
if (_method) {
- // Emit stub for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+ // Emit stubs for static call.
+ address mark = cbuf.insts_mark();
+ address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
if (stub == NULL) {
ciEnv::current()->record_failure("CodeCache is full");
return;
- }
+ }
}
%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.amd64;
+
+import static jdk.vm.ci.code.MemoryBarriers.*;
+import static jdk.vm.ci.code.Register.*;
+
+import java.nio.*;
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the AMD64 architecture.
+ */
+public class AMD64 extends Architecture {
+
+ public static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+ // @formatter:off
+
+ // General purpose CPU registers
+ public static final Register rax = new Register(0, 0, "rax", CPU);
+ public static final Register rcx = new Register(1, 1, "rcx", CPU);
+ public static final Register rdx = new Register(2, 2, "rdx", CPU);
+ public static final Register rbx = new Register(3, 3, "rbx", CPU);
+ public static final Register rsp = new Register(4, 4, "rsp", CPU);
+ public static final Register rbp = new Register(5, 5, "rbp", CPU);
+ public static final Register rsi = new Register(6, 6, "rsi", CPU);
+ public static final Register rdi = new Register(7, 7, "rdi", CPU);
+
+ public static final Register r8 = new Register(8, 8, "r8", CPU);
+ public static final Register r9 = new Register(9, 9, "r9", CPU);
+ public static final Register r10 = new Register(10, 10, "r10", CPU);
+ public static final Register r11 = new Register(11, 11, "r11", CPU);
+ public static final Register r12 = new Register(12, 12, "r12", CPU);
+ public static final Register r13 = new Register(13, 13, "r13", CPU);
+ public static final Register r14 = new Register(14, 14, "r14", CPU);
+ public static final Register r15 = new Register(15, 15, "r15", CPU);
+
+ public static final Register[] cpuRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15
+ };
+
+ private static final int XMM_REFERENCE_MAP_SHIFT = 2;
+
+ public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
+
+ // XMM registers
+ public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
+ public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
+ public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
+ public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
+ public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
+ public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
+ public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
+ public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
+
+ public static final Register xmm8 = new Register(24, 8, "xmm8", XMM);
+ public static final Register xmm9 = new Register(25, 9, "xmm9", XMM);
+ public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
+ public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
+ public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
+ public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
+ public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
+ public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
+
+ public static final Register[] xmmRegisters = {
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+
+ public static final Register[] cpuxmmRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+
+ /**
+ * Register used to construct an instruction-relative address.
+ */
+ public static final Register rip = new Register(32, -1, "rip", SPECIAL);
+
+ public static final Register[] allRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+ rip
+ };
+
+ // @formatter:on
+
+ /**
+ * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
+ * {@code VM_Version::cpuFeatureFlags}.
+ */
+ public static enum CPUFeature {
+ CX8,
+ CMOV,
+ FXSR,
+ HT,
+ MMX,
+ AMD_3DNOW_PREFETCH,
+ SSE,
+ SSE2,
+ SSE3,
+ SSSE3,
+ SSE4A,
+ SSE4_1,
+ SSE4_2,
+ POPCNT,
+ LZCNT,
+ TSC,
+ TSCINV,
+ AVX,
+ AVX2,
+ AES,
+ ERMS,
+ CLMUL,
+ BMI1,
+ BMI2,
+ RTM,
+ ADX,
+ AVX512F,
+ AVX512DQ,
+ AVX512PF,
+ AVX512ER,
+ AVX512CD,
+ AVX512BW
+ }
+
+ private final EnumSet<CPUFeature> features;
+
+ /**
+ * Set of flags to control code emission.
+ */
+ public static enum Flag {
+ UseCountLeadingZerosInstruction,
+ UseCountTrailingZerosInstruction
+ }
+
+ private final EnumSet<Flag> flags;
+
+ public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
+ super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
+ this.features = features;
+ this.flags = flags;
+ assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
+ }
+
+ public EnumSet<CPUFeature> getFeatures() {
+ return features;
+ }
+
+ public EnumSet<Flag> getFlags() {
+ return flags;
+ }
+
+ @Override
+ public PlatformKind getPlatformKind(JavaKind javaKind) {
+ if (javaKind.isObject()) {
+ return getWordKind();
+ } else {
+ return javaKind;
+ }
+ }
+
+ @Override
+ public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
+ if (!(platformKind instanceof JavaKind)) {
+ return false;
+ }
+
+ JavaKind kind = (JavaKind) platformKind;
+ if (category.equals(CPU)) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ case Int:
+ case Long:
+ return true;
+ }
+ } else if (category.equals(XMM)) {
+ switch (kind) {
+ case Float:
+ case Double:
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public PlatformKind getLargestStorableKind(RegisterCategory category) {
+ if (category.equals(CPU)) {
+ return JavaKind.Long;
+ } else if (category.equals(XMM)) {
+ return JavaKind.Double;
+ } else {
+ return JavaKind.Illegal;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/overview.html Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+Copyright (c) 2012, 2015, 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.
+-->
+
+</head>
+<body>
+
+The <code>jdk.vm.ci.code</code> project provides an API to the runtime's native code cache.
+It allows installation and execution of native code.
+
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Abstract base class that represents a platform specific address.
+ */
+public abstract class AbstractAddress {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.nio.*;
+import java.util.*;
+
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a CPU architecture, including information such as its endianness, CPU registers, word
+ * width, etc.
+ */
+public abstract class Architecture {
+
+ /**
+ * The number of entries required in a {@link ReferenceMap} covering all the registers that may
+ * store references. The index of a register in the reference map is given by
+ * {@link Register#getReferenceMapIndex()}.
+ */
+ private final int registerReferenceMapSize;
+
+ /**
+ * The architecture specific type of a native word.
+ */
+ private final PlatformKind wordKind;
+
+ /**
+ * The name of this architecture (e.g. "AMD64", "SPARCv9").
+ */
+ private final String name;
+
+ /**
+ * Array of all available registers on this architecture. The index of each register in this
+ * array is equal to its {@linkplain Register#number number}.
+ */
+ private final Register[] registers;
+
+ /**
+ * The byte ordering can be either little or big endian.
+ */
+ private final ByteOrder byteOrder;
+
+ /**
+ * Whether the architecture supports unaligned memory accesses.
+ */
+ private final boolean unalignedMemoryAccess;
+
+ /**
+ * Mask of the barrier constants denoting the barriers that are not required to be explicitly
+ * inserted under this architecture.
+ */
+ private final int implicitMemoryBarriers;
+
+ /**
+ * Offset in bytes from the beginning of a call instruction to the displacement.
+ */
+ private final int machineCodeCallDisplacementOffset;
+
+ /**
+ * The size of the return address pushed to the stack by a call instruction. A value of 0
+ * denotes that call linkage uses registers instead (e.g. SPARC).
+ */
+ private final int returnAddressSize;
+
+ protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
+ int registerReferenceMapSize, int returnAddressSize) {
+ this.name = name;
+ this.registers = registers;
+ this.wordKind = wordKind;
+ this.byteOrder = byteOrder;
+ this.unalignedMemoryAccess = unalignedMemoryAccess;
+ this.implicitMemoryBarriers = implicitMemoryBarriers;
+ this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
+ this.registerReferenceMapSize = registerReferenceMapSize;
+ this.returnAddressSize = returnAddressSize;
+ }
+
+ /**
+ * Converts this architecture to a string.
+ *
+ * @return the string representation of this architecture
+ */
+ @Override
+ public final String toString() {
+ return getName().toLowerCase();
+ }
+
+ public int getRegisterReferenceMapSize() {
+ return registerReferenceMapSize;
+ }
+
+ /**
+ * Gets the natural size of words (typically registers and pointers) of this architecture, in
+ * bytes.
+ */
+ public int getWordSize() {
+ return wordKind.getSizeInBytes();
+ }
+
+ public PlatformKind getWordKind() {
+ return wordKind;
+ }
+
+ /**
+ * Gets the name of this architecture.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets an array of all available registers on this architecture. The index of each register in
+ * this array is equal to its {@linkplain Register#number number}.
+ */
+ public Register[] getRegisters() {
+ return registers.clone();
+ }
+
+ public ByteOrder getByteOrder() {
+ return byteOrder;
+ }
+
+ /**
+ * @return true if the architecture supports unaligned memory accesses.
+ */
+ public boolean supportsUnalignedMemoryAccess() {
+ return unalignedMemoryAccess;
+ }
+
+ /**
+ * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
+ * denotes that call linkage uses registers instead.
+ */
+ public int getReturnAddressSize() {
+ return returnAddressSize;
+ }
+
+ /**
+ * Gets the offset in bytes from the beginning of a call instruction to the displacement.
+ */
+ public int getMachineCodeCallDisplacementOffset() {
+ return machineCodeCallDisplacementOffset;
+ }
+
+ /**
+ * Determines the barriers in a given barrier mask that are explicitly required on this
+ * architecture.
+ *
+ * @param barriers a mask of the barrier constants
+ * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
+ */
+ public final int requiredBarriers(int barriers) {
+ return barriers & ~implicitMemoryBarriers;
+ }
+
+ /**
+ * Determine whether a kind can be stored in a register of a given category.
+ *
+ * @param category the category of the register
+ * @param kind the kind that should be stored in the register
+ */
+ public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind);
+
+ /**
+ * Return the largest kind that can be stored in a register of a given category.
+ *
+ * @param category the category of the register
+ * @return the largest kind that can be stored in a register {@code category}
+ */
+ public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
+
+ /**
+ * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+ */
+ public abstract PlatformKind getPlatformKind(JavaKind javaKind);
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Architecture) {
+ Architecture that = (Architecture) obj;
+ if (this.name.equals(that.name)) {
+ assert this.byteOrder.equals(that.byteOrder);
+ assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
+ assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
+ assert this.registerReferenceMapSize == that.registerReferenceMapSize;
+ assert Arrays.equals(this.registers, that.registers);
+ assert this.returnAddressSize == that.returnAddressSize;
+ assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
+ assert this.wordKind == that.wordKind;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return name.hashCode();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+/**
+ * Exception thrown when the compiler refuses to compile a method because of problems with the
+ * method. e.g. bytecode wouldn't verify, too big, JSR/ret too complicated, etc. This exception is
+ * <i>not</i> meant to indicate problems with the compiler itself.
+ */
+public class BailoutException extends RuntimeException {
+
+ public static final long serialVersionUID = 8974598793458772L;
+ private final boolean permanent;
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ *
+ * @param args parameters to the formatter
+ */
+ public BailoutException(String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args));
+ this.permanent = true;
+ }
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ *
+ * @param args parameters to the formatter
+ */
+ public BailoutException(Throwable cause, String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args), cause);
+ this.permanent = true;
+ }
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ * @param permanent specifies whether this exception will occur again if compilation is retried
+ * @param args parameters to the formatter
+ */
+ public BailoutException(boolean permanent, String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args));
+ this.permanent = permanent;
+ }
+
+ /**
+ * @return whether this exception will occur again if compilation is retried
+ */
+ public boolean isPermanent() {
+ return permanent;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
+ * where to find the local variables, operand stack values and locked objects of the bytecode
+ * frame(s).
+ */
+public class BytecodeFrame extends BytecodePosition {
+
+ /**
+ * An array of values representing how to reconstruct the state of the Java frame. This is array
+ * is partitioned as follows:
+ * <p>
+ * <table summary="" border="1" cellpadding="5" frame="void" rules="all">
+ * <tr>
+ * <th>Start index (inclusive)</th>
+ * <th>End index (exclusive)</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td>0</td>
+ * <td>numLocals</td>
+ * <td>Local variables</td>
+ * </tr>
+ * <tr>
+ * <td>numLocals</td>
+ * <td>numLocals + numStack</td>
+ * <td>Operand stack</td>
+ * </tr>
+ * <tr>
+ * <td>numLocals + numStack</td>
+ * <td>values.length</td>
+ * <td>Locked objects</td>
+ * </tr>
+ * </table>
+ * <p>
+ * Note that the number of locals and the number of stack slots may be smaller than the maximum
+ * number of locals and stack slots as specified in the compiled method.
+ */
+ public final JavaValue[] values;
+
+ /**
+ * An array describing the Java kind of the {@link #values}. It records a kind for the locals
+ * and the operand stack.
+ */
+ public final JavaKind[] slotKinds;
+
+ /**
+ * The number of locals in the values array.
+ */
+ public final int numLocals;
+
+ /**
+ * The number of stack slots in the values array.
+ */
+ public final int numStack;
+
+ /**
+ * The number of locks in the values array.
+ */
+ public final int numLocks;
+
+ /**
+ * True if this is a position inside an exception handler before the exception object has been
+ * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
+ * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
+ * position, the interpreter will rethrow the exception instead of executing the bytecode
+ * instruction at this position.
+ */
+ public final boolean rethrowException;
+
+ public final boolean duringCall;
+
+ /**
+ * This BCI should be used for frame states that are built for code with no meaningful BCI.
+ */
+ public static final int UNKNOWN_BCI = -5;
+
+ /**
+ * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+ * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
+ * the monitor is still held.
+ */
+ public static final int UNWIND_BCI = -1;
+
+ /**
+ * The BCI for the state before starting to execute a method. Note that if the method is
+ * synchronized, the monitor is not yet held.
+ */
+ public static final int BEFORE_BCI = -2;
+
+ /**
+ * The BCI for the state after finishing the execution of a method and returning normally. Note
+ * that if the method was synchronized the monitor is already released.
+ */
+ public static final int AFTER_BCI = -3;
+
+ /**
+ * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+ * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the
+ * monitor is already released.
+ */
+ public static final int AFTER_EXCEPTION_BCI = -4;
+
+ /**
+ * This BCI should be used for states that cannot be the target of a deoptimization, like
+ * snippet frame states.
+ */
+ public static final int INVALID_FRAMESTATE_BCI = -6;
+
+ /**
+ * Determines if a given BCI matches one of the placeholder BCI constants defined in this class.
+ */
+ public static boolean isPlaceholderBci(int bci) {
+ return bci < 0;
+ }
+
+ /**
+ * Gets the name of a given placeholder BCI.
+ */
+ public static String getPlaceholderBciName(int bci) {
+ assert isPlaceholderBci(bci);
+ if (bci == BytecodeFrame.AFTER_BCI) {
+ return "AFTER_BCI";
+ } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+ return "AFTER_EXCEPTION_BCI";
+ } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+ return "INVALID_FRAMESTATE_BCI";
+ } else if (bci == BytecodeFrame.BEFORE_BCI) {
+ return "BEFORE_BCI";
+ } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+ return "UNKNOWN_BCI";
+ } else {
+ assert bci == BytecodeFrame.UNWIND_BCI;
+ return "UNWIND_BCI";
+ }
+ }
+
+ /**
+ * Creates a new frame object.
+ *
+ * @param caller the caller frame (which may be {@code null})
+ * @param method the method
+ * @param bci a BCI within the method
+ * @param rethrowException specifies if the VM should re-throw the pending exception when
+ * deopt'ing using this frame
+ * @param values the frame state {@link #values}
+ * @param numLocals the number of local variables
+ * @param numStack the depth of the stack
+ * @param numLocks the number of locked objects
+ */
+ public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
+ int numLocks) {
+ super(caller, method, bci);
+ assert values != null;
+ this.rethrowException = rethrowException;
+ this.duringCall = duringCall;
+ this.values = values;
+ this.slotKinds = slotKinds;
+ this.numLocals = numLocals;
+ this.numStack = numStack;
+ this.numLocks = numLocks;
+ assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
+ }
+
+ /**
+ * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
+ * slot following a double word item. This should really be checked in FrameState itself but
+ * because of Word type rewriting and alternative backends that can't be done.
+ */
+ public boolean validateFormat() {
+ if (caller() != null) {
+ caller().validateFormat();
+ }
+ for (int i = 0; i < numLocals + numStack; i++) {
+ if (values[i] != null) {
+ JavaKind kind = slotKinds[i];
+ if (kind.needsTwoSlots()) {
+ assert slotKinds.length > i + 1 : String.format("missing second word %s", this);
+ assert slotKinds[i + 1] == JavaKind.Illegal : this;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Gets the value representing the specified local variable.
+ *
+ * @param i the local variable index
+ * @return the value that can be used to reconstruct the local's current value
+ */
+ public JavaValue getLocalValue(int i) {
+ return values[i];
+ }
+
+ /**
+ * Gets the value representing the specified stack slot.
+ *
+ * @param i the stack index
+ * @return the value that can be used to reconstruct the stack slot's current value
+ */
+ public JavaValue getStackValue(int i) {
+ return values[i + numLocals];
+ }
+
+ /**
+ * Gets the value representing the specified lock.
+ *
+ * @param i the lock index
+ * @return the value that can be used to reconstruct the lock's current value
+ */
+ public JavaValue getLockValue(int i) {
+ return values[i + numLocals + numStack];
+ }
+
+ /**
+ * Gets the caller of this frame.
+ *
+ * @return {@code null} if this frame has no caller
+ */
+ public BytecodeFrame caller() {
+ return (BytecodeFrame) getCaller();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BytecodeFrame && super.equals(obj)) {
+ BytecodeFrame that = (BytecodeFrame) obj;
+ // @formatter:off
+ if (this.duringCall == that.duringCall &&
+ this.rethrowException == that.rethrowException &&
+ this.numLocals == that.numLocals &&
+ this.numLocks == that.numLocks &&
+ this.numStack == that.numStack &&
+ Arrays.equals(this.values, that.values)) {
+ return true;
+ }
+ // @formatter:off
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return CodeUtil.append(new StringBuilder(100), this).toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
+ * communicated from the compiler to the runtime system. A code position can be used by the runtime
+ * system to reconstruct a source-level stack trace for exceptions and to create
+ * {@linkplain BytecodeFrame frames} for deoptimization.
+ */
+public class BytecodePosition {
+
+ private final BytecodePosition caller;
+ private final ResolvedJavaMethod method;
+ private final int bci;
+
+ /**
+ * Constructs a new object representing a given parent/caller, a given method, and a given BCI.
+ *
+ * @param caller the parent position
+ * @param method the method
+ * @param bci a BCI within the method
+ */
+ public BytecodePosition(BytecodePosition caller, ResolvedJavaMethod method, int bci) {
+ assert method != null;
+ this.caller = caller;
+ this.method = method;
+ this.bci = bci;
+ }
+
+ /**
+ * Converts this code position to a string representation.
+ *
+ * @return a string representation of this code position
+ */
+ @Override
+ public String toString() {
+ return CodeUtil.append(new StringBuilder(100), this).toString();
+ }
+
+ /**
+ * Deep equality test.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj != null && getClass() == obj.getClass()) {
+ BytecodePosition that = (BytecodePosition) obj;
+ if (this.bci == that.bci && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.caller, that.caller)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getBCI();
+ }
+
+ /**
+ * @return The location within the method, as a bytecode index. The constant {@code -1} may be
+ * used to indicate the location is unknown, for example within code synthesized by the
+ * compiler.
+ */
+ public int getBCI() {
+ return bci;
+ }
+
+ /**
+ * @return The runtime interface method for this position.
+ */
+ public ResolvedJavaMethod getMethod() {
+ return method;
+ }
+
+ /**
+ * The position where this position has been called, {@code null} if none.
+ */
+ public BytecodePosition getCaller() {
+ return caller;
+ }
+
+ /**
+ * Adds a caller to the current position returning the new position.
+ */
+ public BytecodePosition addCaller(BytecodePosition link) {
+ if (getCaller() == null) {
+ return new BytecodePosition(link, getMethod(), getBCI());
+ } else {
+ return new BytecodePosition(getCaller().addCaller(link), getMethod(), getBCI());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2009, 2012, 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.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.code.ValueUtil.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * A calling convention describes the locations in which the arguments for a call are placed and the
+ * location in which the return value is placed if the call is not void.
+ */
+public class CallingConvention {
+
+ /**
+ * Constants denoting the type of a call for which a calling convention is requested.
+ */
+ public enum Type {
+ /**
+ * A request for the outgoing argument locations at a call site to Java code.
+ */
+ JavaCall(true),
+
+ /**
+ * A request for the incoming argument locations.
+ */
+ JavaCallee(false),
+
+ /**
+ * A request for the outgoing argument locations at a call site to external native code that
+ * complies with the platform ABI.
+ */
+ NativeCall(true);
+
+ /**
+ * Determines if this is a request for the outgoing argument locations at a call site.
+ */
+ public final boolean out;
+
+ public static final Type[] VALUES = values();
+
+ private Type(boolean out) {
+ this.out = out;
+ }
+ }
+
+ /**
+ * The amount of stack space (in bytes) required for the stack-based arguments of the call.
+ */
+ private final int stackSize;
+
+ private final AllocatableValue returnLocation;
+
+ /**
+ * The ordered locations in which the arguments are placed.
+ */
+ private final AllocatableValue[] argumentLocations;
+
+ /**
+ * Creates a description of the registers and stack locations used by a call.
+ *
+ * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of
+ * the call
+ * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void
+ * call
+ * @param argumentLocations the ordered locations in which the arguments are placed
+ */
+ public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
+ assert argumentLocations != null;
+ assert returnLocation != null;
+ this.argumentLocations = argumentLocations;
+ this.stackSize = stackSize;
+ this.returnLocation = returnLocation;
+ assert verify();
+ }
+
+ /**
+ * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
+ */
+ public AllocatableValue getReturn() {
+ return returnLocation;
+ }
+
+ /**
+ * Gets the location for the {@code index}'th argument.
+ */
+ public AllocatableValue getArgument(int index) {
+ return argumentLocations[index];
+ }
+
+ /**
+ * Gets the amount of stack space (in bytes) required for the stack-based arguments of the call.
+ */
+ public int getStackSize() {
+ return stackSize;
+ }
+
+ /**
+ * Gets the number of locations required for the arguments.
+ */
+ public int getArgumentCount() {
+ return argumentLocations.length;
+ }
+
+ /**
+ * Gets the locations required for the arguments.
+ */
+ public AllocatableValue[] getArguments() {
+ if (argumentLocations.length == 0) {
+ return argumentLocations;
+ }
+ return argumentLocations.clone();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("CallingConvention[");
+ String sep = "";
+ for (Value op : argumentLocations) {
+ sb.append(sep).append(op);
+ sep = ", ";
+ }
+ if (!returnLocation.equals(Value.ILLEGAL)) {
+ sb.append(" -> ").append(returnLocation);
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private boolean verify() {
+ for (int i = 0; i < argumentLocations.length; i++) {
+ Value location = argumentLocations[i];
+ assert isStackSlot(location) || isAllocatableValue(location);
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.code.CompilationResult.*;
+import jdk.vm.ci.code.DataSection.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Access to code cache related details and requirements.
+ */
+public interface CodeCacheProvider {
+
+ /**
+ * Adds the given compilation result as an implementation of the given method without making it
+ * the default implementation.
+ *
+ * @param method a method to which the executable code is begin added
+ * @param compResult the compilation result to be added
+ * @param speculationLog the speculation log to be used
+ * @return a reference to the compiled and ready-to-run code or throws a
+ * {@link BailoutException} if the code installation failed
+ */
+ InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
+
+ /**
+ * Sets the given compilation result as the default implementation of the given method.
+ *
+ * @param method a method to which the executable code is begin added
+ * @param compResult the compilation result to be added
+ * @return a reference to the compiled and ready-to-run code or null if the code installation
+ * failed
+ */
+ InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
+
+ /**
+ * Gets a name for a {@link Mark} mark.
+ */
+ default String getMarkName(Mark mark) {
+ return String.valueOf(mark.id);
+ }
+
+ /**
+ * Gets a name for the {@linkplain Call#target target} of a {@link Call}.
+ */
+ default String getTargetName(Call call) {
+ return String.valueOf(call.target);
+ }
+
+ /**
+ * Gets the register configuration to use when compiling a given method.
+ */
+ RegisterConfig getRegisterConfig();
+
+ /**
+ * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
+ * cases, even when the compiled method has no regular call instructions.
+ *
+ * @return the minimum size of the outgoing parameter area in bytes
+ */
+ int getMinimumOutgoingSize();
+
+ /**
+ * Determines if a {@link DataPatch} should be created for a given primitive constant that is
+ * part of a {@link CompilationResult}. A data patch is always created for an object constant.
+ */
+ boolean needsDataPatch(JavaConstant constant);
+
+ /**
+ * Create a {@link Data} item for one or more {@link Constant Constants}, that can be used in a
+ * {@link DataPatch}. If more than one {@link Constant} is given, then they are tightly packed
+ * into a single {@link Data} item.
+ */
+ Data createDataItem(Constant... constants);
+
+ /**
+ * Gets a description of the target architecture.
+ */
+ TargetDescription getTarget();
+
+ /**
+ * Create a new speculation log for the target runtime.
+ */
+ SpeculationLog createSpeculationLog();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2010, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
+ */
+public class CodeUtil {
+
+ public static final String NEW_LINE = String.format("%n");
+
+ public static final int K = 1024;
+ public static final int M = 1024 * 1024;
+
+ public static boolean isOdd(int n) {
+ return (n & 1) == 1;
+ }
+
+ public static boolean isEven(int n) {
+ return (n & 1) == 0;
+ }
+
+ /**
+ * Checks whether the specified integer is a power of two.
+ *
+ * @param val the value to check
+ * @return {@code true} if the value is a power of two; {@code false} otherwise
+ */
+ public static boolean isPowerOf2(int val) {
+ return val > 0 && (val & val - 1) == 0;
+ }
+
+ /**
+ * Checks whether the specified long is a power of two.
+ *
+ * @param val the value to check
+ * @return {@code true} if the value is a power of two; {@code false} otherwise
+ */
+ public static boolean isPowerOf2(long val) {
+ return val > 0 && (val & val - 1) == 0;
+ }
+
+ /**
+ * Computes the log (base 2) of the specified integer, rounding down. (E.g {@code log2(8) = 3},
+ * {@code log2(21) = 4} )
+ *
+ * @param val the value
+ * @return the log base 2 of the value
+ */
+ public static int log2(int val) {
+ assert val > 0;
+ return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(val);
+ }
+
+ /**
+ * Computes the log (base 2) of the specified long, rounding down. (E.g {@code log2(8) = 3},
+ * {@code log2(21) = 4})
+ *
+ * @param val the value
+ * @return the log base 2 of the value
+ */
+ public static int log2(long val) {
+ assert val > 0;
+ return (Long.SIZE - 1) - Long.numberOfLeadingZeros(val);
+ }
+
+ /**
+ * Narrow an integer value to a given bit width, and return the result as a signed long.
+ *
+ * @param value the value
+ * @param resultBits the result bit width
+ * @return {@code value} interpreted as {@code resultBits} bit number, encoded as signed long
+ */
+ public static long narrow(long value, int resultBits) {
+ long ret = value & mask(resultBits);
+ return signExtend(ret, resultBits);
+ }
+
+ /**
+ * Sign extend an integer.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @return a signed long with the same value as the signed {@code inputBits}-bit number
+ * {@code value}
+ */
+ public static long signExtend(long value, int inputBits) {
+ if (inputBits < 64) {
+ if ((value >>> (inputBits - 1) & 1) == 1) {
+ return value | (-1L << inputBits);
+ } else {
+ return value & ~(-1L << inputBits);
+ }
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Zero extend an integer.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @return an unsigned long with the same value as the unsigned {@code inputBits}-bit number
+ * {@code value}
+ */
+ public static long zeroExtend(long value, int inputBits) {
+ if (inputBits < 64) {
+ return value & ~(-1L << inputBits);
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Convert an integer to long.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @param unsigned whether the values should be interpreted as signed or unsigned
+ * @return a long with the same value as the {@code inputBits}-bit number {@code value}
+ */
+ public static long convert(long value, int inputBits, boolean unsigned) {
+ if (unsigned) {
+ return zeroExtend(value, inputBits);
+ } else {
+ return signExtend(value, inputBits);
+ }
+ }
+
+ /**
+ * Get a bitmask with the low {@code bits} bit set and the high {@code 64 - bits} bit clear.
+ */
+ public static long mask(int bits) {
+ assert 0 <= bits && bits <= 64;
+ if (bits == 64) {
+ return 0xffffffffffffffffL;
+ } else {
+ return (1L << bits) - 1;
+ }
+ }
+
+ /**
+ * Get the minimum value representable in a {@code bits} bit signed integer.
+ */
+ public static long minValue(int bits) {
+ assert 0 < bits && bits <= 64;
+ return -1L << (bits - 1);
+ }
+
+ /**
+ * Get the maximum value representable in a {@code bits} bit signed integer.
+ */
+ public static long maxValue(int bits) {
+ assert 0 < bits && bits <= 64;
+ return mask(bits - 1);
+ }
+
+ /**
+ * Formats the values in a frame as a tabulated string.
+ *
+ * @param frame
+ * @return the values in {@code frame} as a tabulated string
+ */
+ public static String tabulateValues(BytecodeFrame frame) {
+ int cols = Math.max(frame.numLocals, Math.max(frame.numStack, frame.numLocks));
+ assert cols > 0;
+ ArrayList<Object> cells = new ArrayList<>();
+ cells.add("");
+ for (int i = 0; i < cols; i++) {
+ cells.add(i);
+ }
+ cols++;
+ if (frame.numLocals != 0) {
+ cells.add("locals:");
+ cells.addAll(Arrays.asList(frame.values).subList(0, frame.numLocals));
+ cells.addAll(Collections.nCopies(cols - frame.numLocals - 1, ""));
+ }
+ if (frame.numStack != 0) {
+ cells.add("stack:");
+ cells.addAll(Arrays.asList(frame.values).subList(frame.numLocals, frame.numLocals + frame.numStack));
+ cells.addAll(Collections.nCopies(cols - frame.numStack - 1, ""));
+ }
+ if (frame.numLocks != 0) {
+ cells.add("locks:");
+ cells.addAll(Arrays.asList(frame.values).subList(frame.numLocals + frame.numStack, frame.values.length));
+ cells.addAll(Collections.nCopies(cols - frame.numLocks - 1, ""));
+ }
+ Object[] cellArray = cells.toArray();
+ for (int i = 0; i < cellArray.length; i++) {
+ if ((i % cols) != 0) {
+ cellArray[i] = "|" + cellArray[i];
+ }
+ }
+ return CodeUtil.tabulate(cellArray, cols, 1, 1);
+ }
+
+ /**
+ * Formats a given table as a string. The value of each cell is produced by
+ * {@link String#valueOf(Object)}.
+ *
+ * @param cells the cells of the table in row-major order
+ * @param cols the number of columns per row
+ * @param lpad the number of space padding inserted before each formatted cell value
+ * @param rpad the number of space padding inserted after each formatted cell value
+ * @return a string with one line per row and each column left-aligned
+ */
+ public static String tabulate(Object[] cells, int cols, int lpad, int rpad) {
+ int rows = (cells.length + (cols - 1)) / cols;
+ int[] colWidths = new int[cols];
+ for (int col = 0; col < cols; col++) {
+ for (int row = 0; row < rows; row++) {
+ int index = col + (row * cols);
+ if (index < cells.length) {
+ Object cell = cells[index];
+ colWidths[col] = Math.max(colWidths[col], String.valueOf(cell).length());
+ }
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ String nl = NEW_LINE;
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < cols; col++) {
+ int index = col + (row * cols);
+ if (index < cells.length) {
+ for (int i = 0; i < lpad; i++) {
+ sb.append(' ');
+ }
+ Object cell = cells[index];
+ String s = String.valueOf(cell);
+ int w = s.length();
+ sb.append(s);
+ while (w < colWidths[col]) {
+ sb.append(' ');
+ w++;
+ }
+ for (int i = 0; i < rpad; i++) {
+ sb.append(' ');
+ }
+ }
+ }
+ sb.append(nl);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Appends a formatted code position to a {@link StringBuilder}.
+ *
+ * @param sb the {@link StringBuilder} to append to
+ * @param pos the code position to format and append to {@code sb}
+ * @return the value of {@code sb}
+ */
+ public static StringBuilder append(StringBuilder sb, BytecodePosition pos) {
+ MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
+ if (pos.getCaller() != null) {
+ sb.append(NEW_LINE);
+ append(sb, pos.getCaller());
+ }
+ return sb;
+ }
+
+ /**
+ * Appends a formatted frame to a {@link StringBuilder}.
+ *
+ * @param sb the {@link StringBuilder} to append to
+ * @param frame the frame to format and append to {@code sb}
+ * @return the value of {@code sb}
+ */
+ public static StringBuilder append(StringBuilder sb, BytecodeFrame frame) {
+ MetaUtil.appendLocation(sb.append("at "), frame.getMethod(), frame.getBCI());
+ assert sb.charAt(sb.length() - 1) == ']';
+ sb.deleteCharAt(sb.length() - 1);
+ sb.append(", duringCall: ").append(frame.duringCall).append(", rethrow: ").append(frame.rethrowException).append(']');
+ if (frame.values != null && frame.values.length > 0) {
+ sb.append(NEW_LINE);
+ String table = tabulateValues(frame);
+ String[] rows = table.split(NEW_LINE);
+ for (int i = 0; i < rows.length; i++) {
+ String row = rows[i];
+ if (!row.trim().isEmpty()) {
+ sb.append(" ").append(row);
+ if (i != rows.length - 1) {
+ sb.append(NEW_LINE);
+ }
+ }
+ }
+ }
+ if (frame.caller() != null) {
+ sb.append(NEW_LINE);
+ append(sb, frame.caller());
+ } else if (frame.getCaller() != null) {
+ sb.append(NEW_LINE);
+ append(sb, frame.getCaller());
+ }
+ return sb;
+ }
+
+ public interface RefMapFormatter {
+
+ String formatStackSlot(int frameRefMapIndex);
+
+ String formatRegister(int regRefMapIndex);
+ }
+
+ /**
+ * Formats a location in a register reference map.
+ */
+ public static class DefaultRegFormatter implements RefMapFormatter {
+
+ private final Register[] registers;
+
+ public DefaultRegFormatter(Architecture arch) {
+ registers = new Register[arch.getRegisterReferenceMapSize()];
+ for (Register r : arch.getRegisters()) {
+ if (r.getReferenceMapIndex() >= 0) {
+ registers[r.getReferenceMapIndex()] = r;
+ }
+ }
+ }
+
+ public String formatStackSlot(int frameRefMapIndex) {
+ return null;
+ }
+
+ public String formatRegister(int regRefMapIndex) {
+ int i = regRefMapIndex;
+ int idx = 0;
+ while (registers[i] == null) {
+ i--;
+ idx++;
+ }
+ if (idx == 0) {
+ return registers[i].toString();
+ } else {
+ return String.format("%s+%d", registers[i].toString(), idx);
+ }
+ }
+ }
+
+ /**
+ * Formats a location present in a register or frame reference map.
+ */
+ public static class DefaultRefMapFormatter extends DefaultRegFormatter {
+
+ /**
+ * The size of a stack slot.
+ */
+ public final int slotSize;
+
+ /**
+ * The register used as the frame pointer.
+ */
+ public final Register fp;
+
+ /**
+ * The offset (in bytes) from the slot pointed to by {@link #fp} to the slot corresponding
+ * to bit 0 in the frame reference map.
+ */
+ public final int refMapToFPOffset;
+
+ public DefaultRefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) {
+ super(arch);
+ this.slotSize = slotSize;
+ this.fp = fp;
+ this.refMapToFPOffset = refMapToFPOffset;
+ }
+
+ @Override
+ public String formatStackSlot(int frameRefMapIndex) {
+ int refMapOffset = frameRefMapIndex * slotSize;
+ int fpOffset = refMapOffset + refMapToFPOffset;
+ if (fpOffset >= 0) {
+ return fp + "+" + fpOffset;
+ }
+ return fp.name + fpOffset;
+ }
+ }
+
+ public static class NumberedRefMapFormatter implements RefMapFormatter {
+
+ public String formatStackSlot(int frameRefMapIndex) {
+ return "s" + frameRefMapIndex;
+ }
+
+ public String formatRegister(int regRefMapIndex) {
+ return "r" + regRefMapIndex;
+ }
+ }
+
+ /**
+ * Appends a formatted debug info to a {@link StringBuilder}.
+ *
+ * @param sb the {@link StringBuilder} to append to
+ * @param info the debug info to format and append to {@code sb}
+ * @return the value of {@code sb}
+ */
+ public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatterArg) {
+ RefMapFormatter formatter = formatterArg;
+ if (formatter == null) {
+ formatter = new NumberedRefMapFormatter();
+ }
+ String nl = NEW_LINE;
+ ReferenceMap refMap = info.getReferenceMap();
+ if (refMap != null) {
+ sb.append(refMap.toString());
+ }
+ RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+ if (calleeSaveInfo != null) {
+ sb.append("callee-save-info:").append(nl);
+ Map<Integer, Register> map = calleeSaveInfo.slotsToRegisters(true);
+ for (Map.Entry<Integer, Register> e : map.entrySet()) {
+ sb.append(" ").append(e.getValue()).append(" -> ").append(formatter.formatStackSlot(e.getKey())).append(nl);
+ }
+ }
+ BytecodeFrame frame = info.frame();
+ if (frame != null) {
+ append(sb, frame);
+ } else if (info.getBytecodePosition() != null) {
+ append(sb, info.getBytecodePosition());
+ }
+ return sb;
+ }
+
+ /**
+ * Create a calling convention from a {@link ResolvedJavaMethod}.
+ */
+ public static CallingConvention getCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, boolean stackOnly) {
+ Signature sig = method.getSignature();
+ JavaType retType = sig.getReturnType(null);
+ int sigCount = sig.getParameterCount(false);
+ JavaType[] argTypes;
+ int argIndex = 0;
+ if (!method.isStatic()) {
+ argTypes = new JavaType[sigCount + 1];
+ argTypes[argIndex++] = method.getDeclaringClass();
+ } else {
+ argTypes = new JavaType[sigCount];
+ }
+ for (int i = 0; i < sigCount; i++) {
+ argTypes[argIndex++] = sig.getParameterType(i, null);
+ }
+
+ RegisterConfig registerConfig = codeCache.getRegisterConfig();
+ return registerConfig.getCallingConvention(type, retType, argTypes, codeCache.getTarget(), stackOnly);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1054 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+package jdk.vm.ci.code;
+
+import static java.util.Collections.*;
+import static jdk.vm.ci.meta.MetaUtil.*;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.*;
+
+/**
+ * Represents the output from compiling a method, including the compiled machine code, associated
+ * data and references, relocation information, deoptimization information, etc.
+ */
+public class CompilationResult {
+
+ /**
+ * Represents a code position with associated additional information.
+ */
+ public abstract static class Site {
+
+ /**
+ * The position (or offset) of this site with respect to the start of the target method.
+ */
+ public final int pcOffset;
+
+ public Site(int pos) {
+ this.pcOffset = pos;
+ }
+
+ @Override
+ public final int hashCode() {
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public String toString() {
+ return identityHashCodeString(this);
+ }
+
+ @Override
+ public abstract boolean equals(Object obj);
+ }
+
+ /**
+ * Represents an infopoint with associated debug info. Note that safepoints are also infopoints.
+ */
+ public static class Infopoint extends Site implements Comparable<Infopoint> {
+
+ public final DebugInfo debugInfo;
+
+ public final InfopointReason reason;
+
+ public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) {
+ super(pcOffset);
+ this.debugInfo = debugInfo;
+ this.reason = reason;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(pcOffset);
+ sb.append("[<infopoint>]");
+ appendDebugInfo(sb, debugInfo);
+ return sb.toString();
+ }
+
+ @Override
+ public int compareTo(Infopoint o) {
+ if (pcOffset < o.pcOffset) {
+ return -1;
+ } else if (pcOffset > o.pcOffset) {
+ return 1;
+ }
+ return this.reason.compareTo(o.reason);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj != null && obj.getClass() == getClass()) {
+ Infopoint that = (Infopoint) obj;
+ if (this.pcOffset == that.pcOffset && Objects.equals(this.debugInfo, that.debugInfo) && Objects.equals(this.reason, that.reason)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public enum MetaSpaceAccessType {
+ Move,
+ Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is
+ // not supported using AOT. TODO: Look at HotSpotStoreConstantOp
+ Compare; // HotSpotCompareMemoryConstantOp, HotSpotCompareConstantOp
+
+ private MetaSpaceAccessType() {
+ }
+ }
+
+ /**
+ * Represents a meta space pointer access in the code.
+ */
+ public static final class MetaSpaceAccess extends Infopoint {
+
+ private static final long serialVersionUID = 1701958512608684706L;
+
+ /**
+ * Metaspace reference.
+ */
+ public final Object reference; // Object here is a HotSpotResolvedObjectType or a
+ // HotSpotMetaSpaceConstant
+
+ public final MetaSpaceAccessType type;
+
+ /**
+ * Instruction size.
+ */
+ public final int instructionSize;
+
+ public MetaSpaceAccess(Object reference, int instructionSize, MetaSpaceAccessType type, int pcOffset, DebugInfo debugInfo) {
+ super(pcOffset, debugInfo, InfopointReason.METASPACE_ACCESS);
+ this.type = type;
+ this.reference = reference;
+ this.instructionSize = instructionSize;
+ }
+ }
+
+ /**
+ * Represents a call in the code.
+ */
+ public static final class Call extends Infopoint {
+
+ /**
+ * The target of the call.
+ */
+ public final InvokeTarget target;
+
+ /**
+ * The size of the call instruction.
+ */
+ public final int size;
+
+ /**
+ * Specifies if this call is direct or indirect. A direct call has an immediate operand
+ * encoding the absolute or relative (to the call itself) address of the target. An indirect
+ * call has a register or memory operand specifying the target address of the call.
+ */
+ public final boolean direct;
+
+ public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
+ super(pcOffset, debugInfo, InfopointReason.CALL);
+ this.size = size;
+ this.target = target;
+ this.direct = direct;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Call && super.equals(obj)) {
+ Call that = (Call) obj;
+ if (this.size == that.size && this.direct == that.direct && Objects.equals(this.target, that.target)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(pcOffset);
+ sb.append('[');
+ sb.append(target);
+ sb.append(']');
+
+ if (debugInfo != null) {
+ appendDebugInfo(sb, debugInfo);
+ }
+
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Represents some external data that is referenced by the code.
+ */
+ public abstract static class Reference {
+
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(Object obj);
+ }
+
+ public static final class ConstantReference extends Reference {
+
+ private final VMConstant constant;
+
+ public ConstantReference(VMConstant constant) {
+ this.constant = constant;
+ }
+
+ public VMConstant getConstant() {
+ return constant;
+ }
+
+ @Override
+ public String toString() {
+ return constant.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return constant.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ConstantReference) {
+ ConstantReference that = (ConstantReference) obj;
+ return Objects.equals(this.constant, that.constant);
+ }
+ return false;
+ }
+ }
+
+ public static final class DataSectionReference extends Reference {
+
+ private boolean initialized;
+ private int offset;
+
+ public DataSectionReference() {
+ // will be set after the data section layout is fixed
+ offset = 0xDEADDEAD;
+ }
+
+ public int getOffset() {
+ assert initialized;
+
+ return offset;
+ }
+
+ public void setOffset(int offset) {
+ assert !initialized;
+ initialized = true;
+
+ this.offset = offset;
+ }
+
+ @Override
+ public int hashCode() {
+ return offset;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DataSectionReference) {
+ DataSectionReference that = (DataSectionReference) obj;
+ return this.offset == that.offset;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a code site that references some data. The associated data can be either a
+ * {@link DataSectionReference reference} to the data section, or it may be an inlined
+ * {@link JavaConstant} that needs to be patched.
+ */
+ public static final class DataPatch extends Site {
+
+ public Reference reference;
+ public Object note;
+
+ public DataPatch(int pcOffset, Reference reference) {
+ super(pcOffset);
+ this.reference = reference;
+ this.note = null;
+ }
+
+ public DataPatch(int pcOffset, Reference reference, Object note) {
+ super(pcOffset);
+ this.reference = reference;
+ this.note = note;
+ }
+
+ @Override
+ public String toString() {
+ if (note != null) {
+ return String.format("%d[<data patch referring to %s>, note: %s]", pcOffset, reference.toString(), note.toString());
+ } else {
+ return String.format("%d[<data patch referring to %s>]", pcOffset, reference.toString());
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DataPatch) {
+ DataPatch that = (DataPatch) obj;
+ if (this.pcOffset == that.pcOffset && Objects.equals(this.reference, that.reference) && Objects.equals(this.note, that.note)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Provides extra information about instructions or data at specific positions in
+ * {@link CompilationResult#getTargetCode()}. This is optional information that can be used to
+ * enhance a disassembly of the code.
+ */
+ public abstract static class CodeAnnotation {
+
+ public final int position;
+
+ public CodeAnnotation(int position) {
+ this.position = position;
+ }
+
+ @Override
+ public final int hashCode() {
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public String toString() {
+ return identityHashCodeString(this);
+ }
+
+ @Override
+ public abstract boolean equals(Object obj);
+ }
+
+ /**
+ * A string comment about one or more instructions at a specific position in the code.
+ */
+ public static final class CodeComment extends CodeAnnotation {
+
+ public final String value;
+
+ public CodeComment(int position, String comment) {
+ super(position);
+ this.value = comment;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof CodeComment) {
+ CodeComment that = (CodeComment) obj;
+ if (this.position == that.position && this.value.equals(that.value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "@" + position + ": " + value;
+ }
+ }
+
+ /**
+ * Describes a table of signed offsets embedded in the code. The offsets are relative to the
+ * starting address of the table. This type of table maybe generated when translating a
+ * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch}
+ * JVM instruction).
+ *
+ * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high}
+ * inclusive.
+ */
+ public static final class JumpTable extends CodeAnnotation {
+
+ /**
+ * The low value in the key range (inclusive).
+ */
+ public final int low;
+
+ /**
+ * The high value in the key range (inclusive).
+ */
+ public final int high;
+
+ /**
+ * The size (in bytes) of each table entry.
+ */
+ public final int entrySize;
+
+ public JumpTable(int position, int low, int high, int entrySize) {
+ super(position);
+ this.low = low;
+ this.high = high;
+ this.entrySize = entrySize;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof JumpTable) {
+ JumpTable that = (JumpTable) obj;
+ if (this.position == that.position && this.entrySize == that.entrySize && this.low == that.low && this.high == that.high) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "@" + position + ": [" + low + " .. " + high + "]";
+ }
+ }
+
+ /**
+ * Represents exception handler information for a specific code position. It includes the catch
+ * code position as well as the caught exception type.
+ */
+ public static final class ExceptionHandler extends Site {
+
+ public final int handlerPos;
+
+ ExceptionHandler(int pcOffset, int handlerPos) {
+ super(pcOffset);
+ this.handlerPos = handlerPos;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%d[<exception edge to %d>]", pcOffset, handlerPos);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ExceptionHandler) {
+ ExceptionHandler that = (ExceptionHandler) obj;
+ if (this.pcOffset == that.pcOffset && this.handlerPos == that.handlerPos) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a mark in the machine code that can be used by the runtime for its own purposes. A
+ * mark can reference other marks.
+ */
+ public static final class Mark extends Site {
+
+ public final Object id;
+
+ public Mark(int pcOffset, Object id) {
+ super(pcOffset);
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ if (id == null) {
+ return String.format("%d[<mar>]", pcOffset);
+ } else if (id instanceof Integer) {
+ return String.format("%d[<mark with id %s>]", pcOffset, Integer.toHexString((Integer) id));
+ } else {
+ return String.format("%d[<mark with id %s>]", pcOffset, id.toString());
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Mark) {
+ Mark that = (Mark) obj;
+ if (this.pcOffset == that.pcOffset && Objects.equals(this.id, that.id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private int id = -1;
+
+ /**
+ * Specifies whether this compilation is a {@code +ImmutableCode} {@code +GeneratePIC}
+ * compilation.
+ */
+ private final boolean isImmutablePIC;
+
+ private int entryBCI = -1;
+
+ private final DataSection dataSection = new DataSection();
+
+ private final List<Infopoint> infopoints = new ArrayList<>();
+ private final List<DataPatch> dataPatches = new ArrayList<>();
+ private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
+ private final List<Mark> marks = new ArrayList<>();
+
+ private int totalFrameSize = -1;
+ private int customStackAreaOffset = -1;
+
+ private final String name;
+
+ /**
+ * The buffer containing the emitted machine code.
+ */
+ private byte[] targetCode;
+
+ /**
+ * The leading number of bytes in {@link #targetCode} containing the emitted machine code.
+ */
+ private int targetCodeSize;
+
+ private ArrayList<CodeAnnotation> annotations;
+
+ private Assumption[] assumptions;
+
+ /**
+ * The list of the methods whose bytecodes were used as input to the compilation. If
+ * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
+ * element of this array is the root method of the compilation.
+ */
+ private ResolvedJavaMethod[] methods;
+
+ private int bytecodeSize;
+
+ private boolean hasUnsafeAccess;
+
+ public CompilationResult() {
+ this(null);
+ }
+
+ public CompilationResult(String name) {
+ this.name = name;
+ this.isImmutablePIC = false;
+ }
+
+ public CompilationResult(boolean isImmutablePIC) {
+ this.name = null;
+ this.isImmutablePIC = isImmutablePIC;
+ }
+
+ @Override
+ public int hashCode() {
+ // CompilationResult instances should not be used as hash map keys
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public String toString() {
+ if (methods != null) {
+ return getClass().getName() + "[" + methods[0].format("%H.%n(%p)%r") + "]";
+ }
+ return identityHashCodeString(this);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj != null && obj.getClass() == getClass()) {
+ CompilationResult that = (CompilationResult) obj;
+ // @formatter:off
+ if (this.entryBCI == that.entryBCI &&
+ this.id == that.id &&
+ this.customStackAreaOffset == that.customStackAreaOffset &&
+ this.totalFrameSize == that.totalFrameSize &&
+ this.targetCodeSize == that.targetCodeSize &&
+ Objects.equals(this.name, that.name) &&
+ Objects.equals(this.annotations, that.annotations) &&
+ Objects.equals(this.dataSection, that.dataSection) &&
+ Objects.equals(this.exceptionHandlers, that.exceptionHandlers) &&
+ Objects.equals(this.dataPatches, that.dataPatches) &&
+ Objects.equals(this.infopoints, that.infopoints) &&
+ Objects.equals(this.marks, that.marks) &&
+ Arrays.equals(this.assumptions, that.assumptions) &&
+ Arrays.equals(targetCode, that.targetCode)) {
+ return true;
+ }
+ // @formatter:on
+ }
+ return false;
+ }
+
+ /**
+ * @return the compile id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @param id the compile id to set
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * @return true is this is a {@code +ImmutableCode} {@code +GeneratePIC} compilation, false
+ * otherwise.
+ */
+ public boolean isImmutablePIC() {
+ return isImmutablePIC;
+ }
+
+ /**
+ * @return the entryBCI
+ */
+ public int getEntryBCI() {
+ return entryBCI;
+ }
+
+ /**
+ * @param entryBCI the entryBCI to set
+ */
+ public void setEntryBCI(int entryBCI) {
+ this.entryBCI = entryBCI;
+ }
+
+ /**
+ * Sets the assumptions made during compilation.
+ */
+ public void setAssumptions(Assumption[] assumptions) {
+ this.assumptions = assumptions;
+ }
+
+ /**
+ * Gets the assumptions made during compilation.
+ */
+ public Assumption[] getAssumptions() {
+ return assumptions;
+ }
+
+ /**
+ * Sets the methods whose bytecodes were used as input to the compilation.
+ *
+ * @param rootMethod the root method of the compilation
+ * @param inlinedMethods the methods inlined during compilation
+ */
+ public void setMethods(ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods) {
+ assert rootMethod != null;
+ assert inlinedMethods != null;
+ if (inlinedMethods.contains(rootMethod)) {
+ methods = inlinedMethods.toArray(new ResolvedJavaMethod[inlinedMethods.size()]);
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i].equals(rootMethod)) {
+ if (i != 0) {
+ ResolvedJavaMethod tmp = methods[0];
+ methods[0] = methods[i];
+ methods[i] = tmp;
+ }
+ break;
+ }
+ }
+ } else {
+ methods = new ResolvedJavaMethod[1 + inlinedMethods.size()];
+ methods[0] = rootMethod;
+ int i = 1;
+ for (ResolvedJavaMethod m : inlinedMethods) {
+ methods[i++] = m;
+ }
+ }
+ }
+
+ /**
+ * Gets the methods whose bytecodes were used as input to the compilation.
+ *
+ * @return {@code null} if the compilation did not record method dependencies otherwise the
+ * methods whose bytecodes were used as input to the compilation with the first element
+ * being the root method of the compilation
+ */
+ public ResolvedJavaMethod[] getMethods() {
+ return methods;
+ }
+
+ public void setBytecodeSize(int bytecodeSize) {
+ this.bytecodeSize = bytecodeSize;
+ }
+
+ public int getBytecodeSize() {
+ return bytecodeSize;
+ }
+
+ public DataSection getDataSection() {
+ return dataSection;
+ }
+
+ /**
+ * The total frame size of the method in bytes. This includes the return address pushed onto the
+ * stack, if any.
+ *
+ * @return the frame size
+ */
+ public int getTotalFrameSize() {
+ assert totalFrameSize != -1 : "frame size not yet initialized!";
+ return totalFrameSize;
+ }
+
+ /**
+ * Sets the total frame size in bytes. This includes the return address pushed onto the stack,
+ * if any.
+ *
+ * @param size the size of the frame in bytes
+ */
+ public void setTotalFrameSize(int size) {
+ totalFrameSize = size;
+ }
+
+ /**
+ * Sets the machine that has been generated by the compiler.
+ *
+ * @param code the machine code generated
+ * @param size the size of the machine code
+ */
+ public void setTargetCode(byte[] code, int size) {
+ targetCode = code;
+ targetCodeSize = size;
+ }
+
+ /**
+ * Records a data patch in the code section. The data patch can refer to something in the
+ * {@link DataSectionReference data section} or directly to an {@link ConstantReference inlined
+ * constant}.
+ *
+ * @param codePos The position in the code that needs to be patched.
+ * @param ref The reference that should be inserted in the code.
+ */
+ public void recordDataPatch(int codePos, Reference ref) {
+ assert codePos >= 0 && ref != null;
+ dataPatches.add(new DataPatch(codePos, ref));
+ }
+
+ /**
+ * Records a data patch in the code section. The data patch can refer to something in the
+ * {@link DataSectionReference data section} or directly to an {@link ConstantReference inlined
+ * constant}.
+ *
+ * @param codePos The position in the code that needs to be patched.
+ * @param ref The reference that should be inserted in the code.
+ * @param note The note attached to data patch for use by post-processing tools
+ */
+ public void recordDataPatchWithNote(int codePos, Reference ref, Object note) {
+ assert codePos >= 0 && ref != null;
+ dataPatches.add(new DataPatch(codePos, ref, note));
+ }
+
+ /**
+ * Records metaspace access.
+ */
+ public void recordMetaspaceAccess(Object reference, int instructionSize, MetaSpaceAccessType type, int codePos, DebugInfo debugInfo) {
+ final MetaSpaceAccess metaspace = new MetaSpaceAccess(reference, instructionSize, type, codePos, debugInfo);
+ addInfopoint(metaspace);
+ }
+
+ /**
+ * Records a call in the code array.
+ *
+ * @param codePos the position of the call in the code array
+ * @param size the size of the call instruction
+ * @param target the being called
+ * @param debugInfo the debug info for the call
+ * @param direct specifies if this is a {@linkplain Call#direct direct} call
+ */
+ public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
+ final Call call = new Call(target, codePos, size, direct, debugInfo);
+ addInfopoint(call);
+ }
+
+ /**
+ * Records an exception handler for this method.
+ *
+ * @param codePos the position in the code that is covered by the handler
+ * @param handlerPos the position of the handler
+ */
+ public void recordExceptionHandler(int codePos, int handlerPos) {
+ assert validateExceptionHandlerAdd(codePos, handlerPos) : String.format("Duplicate exception handler for pc 0x%x handlerPos 0x%x", codePos, handlerPos);
+ exceptionHandlers.add(new ExceptionHandler(codePos, handlerPos));
+ }
+
+ /**
+ * Validate if the exception handler for codePos already exists and handlerPos is different.
+ *
+ * @param codePos
+ * @param handlerPos
+ * @return true if the validation is successful
+ */
+ private boolean validateExceptionHandlerAdd(int codePos, int handlerPos) {
+ ExceptionHandler exHandler = getExceptionHandlerForCodePos(codePos);
+ return exHandler == null || exHandler.handlerPos == handlerPos;
+ }
+
+ /**
+ * Returns the first ExceptionHandler which matches codePos.
+ *
+ * @param codePos position to search for
+ * @return first matching ExceptionHandler
+ */
+ private ExceptionHandler getExceptionHandlerForCodePos(int codePos) {
+ for (ExceptionHandler h : exceptionHandlers) {
+ if (h.pcOffset == codePos) {
+ return h;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Records an infopoint in the code array.
+ *
+ * @param codePos the position of the infopoint in the code array
+ * @param debugInfo the debug info for the infopoint
+ */
+ public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) {
+ addInfopoint(new Infopoint(codePos, debugInfo, reason));
+ }
+
+ /**
+ * Records a custom infopoint in the code section.
+ *
+ * Compiler implementations can use this method to record non-standard infopoints, which are not
+ * handled by the dedicated methods like {@link #recordCall}.
+ *
+ * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint}
+ */
+ public void addInfopoint(Infopoint infopoint) {
+ // The infopoints list must always be sorted
+ if (!infopoints.isEmpty()) {
+ Infopoint previousInfopoint = infopoints.get(infopoints.size() - 1);
+ if (previousInfopoint.pcOffset > infopoint.pcOffset) {
+ // This re-sorting should be very rare
+ Collections.sort(infopoints);
+ previousInfopoint = infopoints.get(infopoints.size() - 1);
+ }
+ if (previousInfopoint.pcOffset == infopoint.pcOffset) {
+ if (infopoint.reason.canBeOmitted()) {
+ return;
+ }
+ if (previousInfopoint.reason.canBeOmitted()) {
+ Infopoint removed = infopoints.remove(infopoints.size() - 1);
+ assert removed == previousInfopoint;
+ } else {
+ throw new RuntimeException("Infopoints that can not be omited should have distinct PCs");
+ }
+ }
+ }
+ infopoints.add(infopoint);
+ }
+
+ /**
+ * Records an instruction mark within this method.
+ *
+ * @param codePos the position in the code that is covered by the handler
+ * @param markId the identifier for this mark
+ */
+ public Mark recordMark(int codePos, Object markId) {
+ Mark mark = new Mark(codePos, markId);
+ marks.add(mark);
+ return mark;
+ }
+
+ /**
+ * Offset in bytes for the custom stack area (relative to sp).
+ *
+ * @return the offset in bytes
+ */
+ public int getCustomStackAreaOffset() {
+ return customStackAreaOffset;
+ }
+
+ /**
+ * @see #getCustomStackAreaOffset()
+ * @param offset
+ */
+ public void setCustomStackAreaOffset(int offset) {
+ customStackAreaOffset = offset;
+ }
+
+ /**
+ * @return the machine code generated for this method
+ */
+ public byte[] getTargetCode() {
+ return targetCode;
+ }
+
+ /**
+ * @return the size of the machine code generated for this method
+ */
+ public int getTargetCodeSize() {
+ return targetCodeSize;
+ }
+
+ /**
+ * @return the code annotations or {@code null} if there are none
+ */
+ public List<CodeAnnotation> getAnnotations() {
+ if (annotations == null) {
+ return Collections.emptyList();
+ }
+ return annotations;
+ }
+
+ public void addAnnotation(CodeAnnotation annotation) {
+ assert annotation != null;
+ if (annotations == null) {
+ annotations = new ArrayList<>();
+ }
+ annotations.add(annotation);
+ }
+
+ private static void appendDebugInfo(StringBuilder sb, DebugInfo info) {
+ if (info != null) {
+ ReferenceMap refMap = info.getReferenceMap();
+ if (refMap != null) {
+ sb.append(refMap.toString());
+ sb.append(']');
+ }
+ RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+ if (calleeSaveInfo != null) {
+ sb.append(" callee-save-info[");
+ String sep = "";
+ for (Map.Entry<Register, Integer> e : calleeSaveInfo.registersToSlots(true).entrySet()) {
+ sb.append(sep).append(e.getKey()).append("->").append(e.getValue());
+ sep = ", ";
+ }
+ sb.append(']');
+ }
+ BytecodePosition codePos = info.getBytecodePosition();
+ if (codePos != null) {
+ MetaUtil.appendLocation(sb.append(" "), codePos.getMethod(), codePos.getBCI());
+ if (info.hasFrame()) {
+ sb.append(" #locals=").append(info.frame().numLocals).append(" #expr=").append(info.frame().numStack);
+ if (info.frame().numLocks > 0) {
+ sb.append(" #locks=").append(info.frame().numLocks);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return the list of infopoints, sorted by {@link Site#pcOffset}
+ */
+ public List<Infopoint> getInfopoints() {
+ if (infopoints.isEmpty()) {
+ return emptyList();
+ }
+ return unmodifiableList(infopoints);
+ }
+
+ /**
+ * @return the list of data references
+ */
+ public List<DataPatch> getDataPatches() {
+ if (dataPatches.isEmpty()) {
+ return emptyList();
+ }
+ return unmodifiableList(dataPatches);
+ }
+
+ /**
+ * @return the list of exception handlers
+ */
+ public List<ExceptionHandler> getExceptionHandlers() {
+ if (exceptionHandlers.isEmpty()) {
+ return emptyList();
+ }
+ return unmodifiableList(exceptionHandlers);
+ }
+
+ /**
+ * @return the list of marks
+ */
+ public List<Mark> getMarks() {
+ if (marks.isEmpty()) {
+ return emptyList();
+ }
+ return unmodifiableList(marks);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setHasUnsafeAccess(boolean hasUnsafeAccess) {
+ this.hasUnsafeAccess = hasUnsafeAccess;
+ }
+
+ public boolean hasUnsafeAccess() {
+ return hasUnsafeAccess;
+ }
+
+ public void reset() {
+ hasUnsafeAccess = false;
+ infopoints.clear();
+ dataPatches.clear();
+ exceptionHandlers.clear();
+ marks.clear();
+ dataSection.clear();
+ if (annotations != null) {
+ annotations.clear();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.meta.MetaUtil.*;
+
+import java.nio.*;
+import java.util.*;
+import java.util.function.*;
+
+import jdk.vm.ci.code.CompilationResult.*;
+import jdk.vm.ci.code.DataSection.*;
+import jdk.vm.ci.meta.*;
+
+public final class DataSection implements Iterable<Data> {
+
+ @FunctionalInterface
+ public interface DataBuilder {
+
+ void emit(ByteBuffer buffer, Consumer<DataPatch> patch);
+
+ static DataBuilder raw(byte[] data) {
+ return (buffer, patch) -> buffer.put(data);
+ }
+
+ static DataBuilder serializable(SerializableConstant c) {
+ return (buffer, patch) -> c.serialize(buffer);
+ }
+
+ static DataBuilder zero(int size) {
+ switch (size) {
+ case 1:
+ return (buffer, patch) -> buffer.put((byte) 0);
+ case 2:
+ return (buffer, patch) -> buffer.putShort((short) 0);
+ case 4:
+ return (buffer, patch) -> buffer.putInt(0);
+ case 8:
+ return (buffer, patch) -> buffer.putLong(0L);
+ default:
+ return (buffer, patch) -> {
+ int rest = size;
+ while (rest > 8) {
+ buffer.putLong(0L);
+ rest -= 8;
+ }
+ while (rest > 0) {
+ buffer.put((byte) 0);
+ rest--;
+ }
+ };
+ }
+ }
+ }
+
+ public static final class Data {
+
+ private int alignment;
+ private final int size;
+ private final DataBuilder builder;
+
+ private DataSectionReference ref;
+
+ public Data(int alignment, int size, DataBuilder builder) {
+ this.alignment = alignment;
+ this.size = size;
+ this.builder = builder;
+
+ // initialized in DataSection.insertData(Data)
+ ref = null;
+ }
+
+ public void updateAlignment(int newAlignment) {
+ if (newAlignment == alignment) {
+ return;
+ }
+ alignment = lcm(alignment, newAlignment);
+ }
+
+ public int getAlignment() {
+ return alignment;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public DataBuilder getBuilder() {
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ // Data instances should not be used as hash map keys
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public String toString() {
+ return identityHashCodeString(this);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ assert ref != null;
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Data) {
+ Data that = (Data) obj;
+ if (this.alignment == that.alignment && this.size == that.size && this.ref.equals(that.ref)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private final ArrayList<Data> dataItems = new ArrayList<>();
+
+ private boolean finalLayout;
+ private int sectionAlignment;
+ private int sectionSize;
+
+ @Override
+ public int hashCode() {
+ // DataSection instances should not be used as hash map keys
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public String toString() {
+ return identityHashCodeString(this);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DataSection) {
+ DataSection that = (DataSection) obj;
+ if (this.finalLayout == that.finalLayout && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Insert a {@link Data} item into the data section. If the item is already in the data section,
+ * the same {@link DataSectionReference} is returned.
+ *
+ * @param data the {@link Data} item to be inserted
+ * @return a unique {@link DataSectionReference} identifying the {@link Data} item
+ */
+ public DataSectionReference insertData(Data data) {
+ assert !finalLayout;
+ if (data.ref == null) {
+ data.ref = new DataSectionReference();
+ dataItems.add(data);
+ }
+ return data.ref;
+ }
+
+ /**
+ * Compute the layout of the data section. This can be called only once, and after it has been
+ * called, the data section can no longer be modified.
+ */
+ public void finalizeLayout() {
+ assert !finalLayout;
+ finalLayout = true;
+
+ // simple heuristic: put items with larger alignment requirement first
+ dataItems.sort((a, b) -> a.alignment - b.alignment);
+
+ int position = 0;
+ for (Data d : dataItems) {
+ sectionAlignment = lcm(sectionAlignment, d.alignment);
+ position = align(position, d.alignment);
+
+ d.ref.setOffset(position);
+ position += d.size;
+ }
+
+ sectionSize = position;
+ }
+
+ public boolean isFinalized() {
+ return finalLayout;
+ }
+
+ /**
+ * Get the size of the data section. Can only be called after {@link #finalizeLayout}.
+ */
+ public int getSectionSize() {
+ assert finalLayout;
+ return sectionSize;
+ }
+
+ /**
+ * Get the minimum alignment requirement of the data section. Can only be called after
+ * {@link #finalizeLayout}.
+ */
+ public int getSectionAlignment() {
+ assert finalLayout;
+ return sectionAlignment;
+ }
+
+ /**
+ * Build the data section. Can only be called after {@link #finalizeLayout}.
+ *
+ * @param buffer The {@link ByteBuffer} where the data section should be built. The buffer must
+ * hold at least {@link #getSectionSize()} bytes.
+ * @param patch A {@link Consumer} to receive {@link DataPatch data patches} for relocations in
+ * the data section.
+ */
+ public void buildDataSection(ByteBuffer buffer, Consumer<DataPatch> patch) {
+ assert finalLayout;
+ for (Data d : dataItems) {
+ buffer.position(d.ref.getOffset());
+ d.builder.emit(buffer, patch);
+ }
+ }
+
+ public Data findData(DataSectionReference ref) {
+ for (Data d : dataItems) {
+ if (d.ref == ref) {
+ return d;
+ }
+ }
+ return null;
+ }
+
+ public Iterator<Data> iterator() {
+ return dataItems.iterator();
+ }
+
+ public static int lcm(int x, int y) {
+ if (x == 0) {
+ return y;
+ } else if (y == 0) {
+ return x;
+ }
+
+ int a = Math.max(x, y);
+ int b = Math.min(x, y);
+ while (b > 0) {
+ int tmp = a % b;
+ a = b;
+ b = tmp;
+ }
+
+ int gcd = a;
+ return x * y / gcd;
+ }
+
+ private static int align(int position, int alignment) {
+ return ((position + alignment - 1) / alignment) * alignment;
+ }
+
+ public void clear() {
+ assert !finalLayout;
+ this.dataItems.clear();
+ this.sectionAlignment = 0;
+ this.sectionSize = 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+/**
+ * Represents the debugging information for a particular point of execution. This information
+ * includes:
+ * <ul>
+ * <li>a {@linkplain #getBytecodePosition() bytecode position}</li>
+ * <li>a reference map for registers and stack slots in the current frame</li>
+ * <li>a map from bytecode locals and operand stack slots to their values or locations from which
+ * their values can be read</li>
+ * <li>a map from the registers (in the caller's frame) to the slots where they are saved in the
+ * current frame</li>
+ * </ul>
+ */
+public final class DebugInfo {
+
+ private final BytecodePosition bytecodePosition;
+ private ReferenceMap referenceMap;
+ @SuppressWarnings("unused") private final VirtualObject[] virtualObjectMapping;
+ private RegisterSaveLayout calleeSaveInfo;
+
+ /**
+ * Creates a new {@link DebugInfo} from the given values.
+ *
+ * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
+ * frame} info
+ * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values
+ */
+ public DebugInfo(BytecodePosition codePos, VirtualObject[] virtualObjectMapping) {
+ this.bytecodePosition = codePos;
+ this.virtualObjectMapping = virtualObjectMapping;
+ }
+
+ public DebugInfo(BytecodePosition codePos) {
+ this(codePos, null);
+ }
+
+ public void setReferenceMap(ReferenceMap referenceMap) {
+ this.referenceMap = referenceMap;
+ }
+
+ /**
+ * @return {@code true} if this debug information has a frame
+ */
+ public boolean hasFrame() {
+ return getBytecodePosition() instanceof BytecodeFrame;
+ }
+
+ /**
+ * Gets the deoptimization information for each inlined frame (if available).
+ *
+ * @return {@code null} if no frame de-opt info is {@linkplain #hasFrame() available}
+ */
+ public BytecodeFrame frame() {
+ if (hasFrame()) {
+ return (BytecodeFrame) getBytecodePosition();
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return CodeUtil.append(new StringBuilder(100), this, null).toString();
+ }
+
+ /**
+ * @return The code position (including all inlined methods) of this debug info. If this is a
+ * {@link BytecodeFrame} instance, then it is also the deoptimization information for
+ * each inlined frame.
+ */
+ public BytecodePosition getBytecodePosition() {
+ return bytecodePosition;
+ }
+
+ public ReferenceMap getReferenceMap() {
+ return referenceMap;
+ }
+
+ /**
+ * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
+ * the current frame.
+ */
+ public void setCalleeSaveInfo(RegisterSaveLayout calleeSaveInfo) {
+ this.calleeSaveInfo = calleeSaveInfo;
+ }
+
+ /**
+ * Gets the map from the registers (in the caller's frame) to the slots where they are saved in
+ * the current frame. If no such information is available, {@code null} is returned.
+ */
+ public RegisterSaveLayout getCalleeSaveInfo() {
+ return calleeSaveInfo;
+ }
+
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DebugInfo) {
+ DebugInfo that = (DebugInfo) obj;
+ if (Objects.equals(this.bytecodePosition, that.bytecodePosition) && Objects.equals(this.calleeSaveInfo, that.calleeSaveInfo) && Objects.equals(this.referenceMap, that.referenceMap)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InfopointReason.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * A reason for infopoint insertion.
+ */
+public enum InfopointReason {
+ UNKNOWN(false),
+ SAFEPOINT(false),
+ CALL(false),
+ IMPLICIT_EXCEPTION(false),
+ METHOD_START(true),
+ METHOD_END(true),
+ LINE_NUMBER(true),
+ METASPACE_ACCESS(true);
+
+ private InfopointReason(boolean canBeOmitted) {
+ this.canBeOmitted = canBeOmitted;
+ }
+
+ private final boolean canBeOmitted;
+
+ public boolean canBeOmitted() {
+ return canBeOmitted;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Represents a compiled instance of a method. It may have been invalidated or removed in the
+ * meantime.
+ */
+public class InstalledCode {
+
+ /**
+ * Raw address of this code blob.
+ */
+ private long address;
+
+ /**
+ * Counts how often the address field was reassigned.
+ */
+ private long version;
+
+ protected final String name;
+
+ public InstalledCode(String name) {
+ this.name = name;
+ }
+
+ public final void setAddress(long address) {
+ this.address = address;
+ version++;
+ }
+
+ /**
+ * @return the address of this code blob
+ */
+ public final long getAddress() {
+ return address;
+ }
+
+ /**
+ * @return the address of this code blob
+ */
+ public final long getVersion() {
+ return version;
+ }
+
+ /**
+ * Returns the name of this code blob.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0
+ * otherwise.
+ */
+ public long getStart() {
+ return 0;
+ }
+
+ /**
+ * Returns the number of instruction bytes for this code.
+ */
+ public long getCodeSize() {
+ return 0;
+ }
+
+ /**
+ * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
+ */
+ public byte[] getCode() {
+ return null;
+ }
+
+ /**
+ * @return true if the code represented by this object is still valid, false otherwise (may
+ * happen due to deopt, etc.)
+ */
+ public boolean isValid() {
+ return address != 0;
+ }
+
+ /**
+ * Invalidates this installed code such that any subsequent
+ * {@linkplain #executeVarargs(Object...) invocation} will throw an
+ * {@link InvalidInstalledCodeException}.
+ */
+ public void invalidate() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Executes the installed code with a variable number of arguments.
+ *
+ * @param args the array of object arguments
+ * @return the value returned by the executed code
+ */
+ @SuppressWarnings("unused")
+ public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+ throw new UnsupportedOperationException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Exception thrown by the runtime in case an invalidated machine code is called.
+ */
+public final class InvalidInstalledCodeException extends Exception {
+
+ private static final long serialVersionUID = -3540232440794244844L;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Represents a location where a value can be stored. This can be either a {@link Register} or a
+ * stack slot.
+ */
+public final class Location {
+
+ public final Register reg;
+ public final int offset;
+
+ private Location(Register reg, int offset) {
+ this.reg = reg;
+ this.offset = offset;
+ }
+
+ /**
+ * Create a {@link Location} for a register.
+ */
+ public static Location register(Register reg) {
+ return new Location(reg, 0);
+ }
+
+ /**
+ * Create a {@link Location} for a vector subregister.
+ *
+ * @param reg the {@link Register vector register}
+ * @param offset the offset in bytes into the vector register
+ */
+ public static Location subregister(Register reg, int offset) {
+ return new Location(reg, offset);
+ }
+
+ /**
+ * Create a {@link Location} for a stack slot.
+ */
+ public static Location stack(int offset) {
+ return new Location(null, offset);
+ }
+
+ public boolean isRegister() {
+ return reg != null;
+ }
+
+ public boolean isStack() {
+ return reg == null;
+ }
+
+ @Override
+ public String toString() {
+ String regName;
+ if (isRegister()) {
+ regName = reg.name + ":";
+ } else {
+ regName = "stack:";
+ }
+ return regName + offset;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Constants and intrinsic definition for memory barriers.
+ *
+ * The documentation for each constant is taken from Doug Lea's <a
+ * href="http://gee.cs.oswego.edu/dl/jmm/cookbook.html">The JSR-133 Cookbook for Compiler
+ * Writers</a>.
+ * <p>
+ * The {@code JMM_*} constants capture the memory barriers necessary to implement the Java Memory
+ * Model with respect to volatile field accesses. Their values are explained by this comment from
+ * templateTable_i486.cpp in the HotSpot source code:
+ *
+ * <pre>
+ * Volatile variables demand their effects be made known to all CPU's in
+ * order. Store buffers on most chips allow reads & writes to reorder; the
+ * JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
+ * memory barrier (i.e., it's not sufficient that the interpreter does not
+ * reorder volatile references, the hardware also must not reorder them).
+ *
+ * According to the new Java Memory Model (JMM):
+ * (1) All volatiles are serialized wrt to each other.
+ * ALSO reads & writes act as acquire & release, so:
+ * (2) A read cannot let unrelated NON-volatile memory refs that happen after
+ * the read float up to before the read. It's OK for non-volatile memory refs
+ * that happen before the volatile read to float down below it.
+ * (3) Similarly, a volatile write cannot let unrelated NON-volatile memory refs
+ * that happen BEFORE the write float down to after the write. It's OK for
+ * non-volatile memory refs that happen after the volatile write to float up
+ * before it.
+ *
+ * We only put in barriers around volatile refs (they are expensive), not
+ * _between_ memory refs (which would require us to track the flavor of the
+ * previous memory refs). Requirements (2) and (3) require some barriers
+ * before volatile stores and after volatile loads. These nearly cover
+ * requirement (1) but miss the volatile-store-volatile-load case. This final
+ * case is placed after volatile-stores although it could just as well go
+ * before volatile-loads.
+ * </pre>
+ */
+public class MemoryBarriers {
+
+ /**
+ * The sequence {@code Load1; LoadLoad; Load2} ensures that {@code Load1}'s data are loaded
+ * before data accessed by {@code Load2} and all subsequent load instructions are loaded. In
+ * general, explicit {@code LoadLoad} barriers are needed on processors that perform speculative
+ * loads and/or out-of-order processing in which waiting load instructions can bypass waiting
+ * stores. On processors that guarantee to always preserve load ordering, these barriers amount
+ * to no-ops.
+ */
+ public static final int LOAD_LOAD = 0x0001;
+
+ /**
+ * The sequence {@code Load1; LoadStore; Store2} ensures that {@code Load1}'s data are loaded
+ * before all data associated with {@code Store2} and subsequent store instructions are flushed.
+ * {@code LoadStore} barriers are needed only on those out-of-order processors in which waiting
+ * store instructions can bypass loads.
+ */
+ public static final int LOAD_STORE = 0x0002;
+
+ /**
+ * The sequence {@code Store1; StoreLoad; Load2} ensures that {@code Store1}'s data are made
+ * visible to other processors (i.e., flushed to main memory) before data accessed by
+ * {@code Load2} and all subsequent load instructions are loaded. {@code StoreLoad} barriers
+ * protect against a subsequent load incorrectly using {@code Store1}'s data value rather than
+ * that from a more recent store to the same location performed by a different processor.
+ * Because of this, on the processors discussed below, a {@code StoreLoad} is strictly necessary
+ * only for separating stores from subsequent loads of the same location(s) as were stored
+ * before the barrier. {@code StoreLoad} barriers are needed on nearly all recent
+ * multiprocessors, and are usually the most expensive kind. Part of the reason they are
+ * expensive is that they must disable mechanisms that ordinarily bypass cache to satisfy loads
+ * from write-buffers. This might be implemented by letting the buffer fully flush, among other
+ * possible stalls.
+ */
+ public static final int STORE_LOAD = 0x0004;
+
+ /**
+ * The sequence {@code Store1; StoreStore; Store2} ensures that {@code Store1}'s data are
+ * visible to other processors (i.e., flushed to memory) before the data associated with
+ * {@code Store2} and all subsequent store instructions. In general, {@code StoreStore} barriers
+ * are needed on processors that do not otherwise guarantee strict ordering of flushes from
+ * write buffers and/or caches to other processors or main memory.
+ */
+ public static final int STORE_STORE = 0x0008;
+
+ public static final int JMM_PRE_VOLATILE_WRITE = LOAD_STORE | STORE_STORE;
+ public static final int JMM_POST_VOLATILE_WRITE = STORE_LOAD | STORE_STORE;
+ public static final int JMM_PRE_VOLATILE_READ = 0;
+ public static final int JMM_POST_VOLATILE_READ = LOAD_LOAD | LOAD_STORE;
+
+ public static String barriersString(int barriers) {
+ StringBuilder sb = new StringBuilder();
+ sb.append((barriers & LOAD_LOAD) != 0 ? "LOAD_LOAD " : "");
+ sb.append((barriers & LOAD_STORE) != 0 ? "LOAD_STORE " : "");
+ sb.append((barriers & STORE_LOAD) != 0 ? "STORE_LOAD " : "");
+ sb.append((barriers & STORE_STORE) != 0 ? "STORE_STORE " : "");
+ return sb.toString().trim();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ReferenceMap.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+public abstract class ReferenceMap {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a target machine register.
+ */
+public final class Register implements Comparable<Register> {
+
+ public static final RegisterCategory SPECIAL = new RegisterCategory("SPECIAL");
+
+ /**
+ * Invalid register.
+ */
+ public static final Register None = new Register(-1, -1, "noreg", SPECIAL);
+
+ /**
+ * Frame pointer of the current method. All spill slots and outgoing stack-based arguments are
+ * addressed relative to this register.
+ */
+ public static final Register Frame = new Register(-2, -2, "framereg", SPECIAL);
+
+ public static final Register CallerFrame = new Register(-3, -3, "callerframereg", SPECIAL);
+
+ /**
+ * The identifier for this register that is unique across all the registers in a
+ * {@link Architecture}. A valid register has {@code number > 0}.
+ */
+ public final int number;
+
+ /**
+ * The mnemonic of this register.
+ */
+ public final String name;
+
+ /**
+ * The actual encoding in a target machine instruction for this register, which may or may not
+ * be the same as {@link #number}.
+ */
+ public final int encoding;
+
+ /**
+ * The assembler calls this method to get the register's encoding.
+ */
+ public int encoding() {
+ return encoding;
+ }
+
+ /**
+ * A platform specific register category that describes which values can be stored in a
+ * register.
+ */
+ private final RegisterCategory registerCategory;
+
+ /**
+ * A platform specific register type that describes which values can be stored in a register.
+ */
+ public static class RegisterCategory {
+
+ private final String name;
+
+ private final int referenceMapOffset;
+ private final int referenceMapShift;
+
+ public RegisterCategory(String name) {
+ this(name, 0, 0);
+ }
+
+ public RegisterCategory(String name, int referenceMapOffset) {
+ this(name, referenceMapOffset, 0);
+ }
+
+ public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) {
+ this.name = name;
+ this.referenceMapOffset = referenceMapOffset;
+ this.referenceMapShift = referenceMapShift;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return 23 + name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RegisterCategory) {
+ RegisterCategory that = (RegisterCategory) obj;
+ return this.referenceMapOffset == that.referenceMapOffset && this.referenceMapShift == that.referenceMapShift && this.name.equals(that.name);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Creates a {@link Register} instance.
+ *
+ * @param number unique identifier for the register
+ * @param encoding the target machine encoding for the register
+ * @param name the mnemonic name for the register
+ * @param registerCategory the register category
+ */
+ public Register(int number, int encoding, String name, RegisterCategory registerCategory) {
+ this.number = number;
+ this.name = name;
+ this.registerCategory = registerCategory;
+ this.encoding = encoding;
+ }
+
+ public RegisterCategory getRegisterCategory() {
+ return registerCategory;
+ }
+
+ /**
+ * Get the start index of this register in the {@link ReferenceMap}.
+ */
+ public int getReferenceMapIndex() {
+ return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset;
+ }
+
+ /**
+ * Gets this register as a {@linkplain RegisterValue value} with a specified kind.
+ *
+ * @param kind the specified kind
+ * @return the {@link RegisterValue}
+ */
+ public RegisterValue asValue(LIRKind kind) {
+ return new RegisterValue(kind, this);
+ }
+
+ /**
+ * Gets this register as a {@linkplain RegisterValue value} with no particular kind.
+ *
+ * @return a {@link RegisterValue} with {@link JavaKind#Illegal} kind.
+ */
+ public RegisterValue asValue() {
+ return asValue(LIRKind.Illegal);
+ }
+
+ /**
+ * Determines if this is a valid register.
+ *
+ * @return {@code true} iff this register is valid
+ */
+ public boolean isValid() {
+ return number >= 0;
+ }
+
+ /**
+ * Gets the maximum register {@linkplain #number number} in a given set of registers.
+ *
+ * @param registers the set of registers to process
+ * @return the maximum register number for any register in {@code registers}
+ */
+ public static int maxRegisterNumber(Register[] registers) {
+ int max = Integer.MIN_VALUE;
+ for (Register r : registers) {
+ if (r.number > max) {
+ max = r.number;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Gets the maximum register {@linkplain #encoding encoding} in a given set of registers.
+ *
+ * @param registers the set of registers to process
+ * @return the maximum register encoding for any register in {@code registers}
+ */
+ public static int maxRegisterEncoding(Register[] registers) {
+ int max = Integer.MIN_VALUE;
+ for (Register r : registers) {
+ if (r.encoding > max) {
+ max = r.encoding;
+ }
+ }
+ return max;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public int compareTo(Register o) {
+ if (number < o.number) {
+ return -1;
+ }
+ if (number > o.number) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return 17 + name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Register) {
+ Register other = (Register) obj;
+ if (number == other.number) {
+ assert name.equals(other.name);
+ assert encoding == other.encoding;
+ assert registerCategory.equals(other.registerCategory);
+ return true;
+ }
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010, 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+/**
+ * A collection of register attributes. The specific attribute values for a register may be local to
+ * a compilation context. For example, a {@link RegisterConfig} in use during a compilation will
+ * determine which registers are callee saved.
+ */
+public class RegisterAttributes {
+
+ private final boolean callerSave;
+ private final boolean calleeSave;
+ private final boolean allocatable;
+
+ public RegisterAttributes(boolean isCallerSave, boolean isCalleeSave, boolean isAllocatable) {
+ this.callerSave = isCallerSave;
+ this.calleeSave = isCalleeSave;
+ this.allocatable = isAllocatable;
+ }
+
+ public static final RegisterAttributes NONE = new RegisterAttributes(false, false, false);
+
+ /**
+ * Creates a map from register {@linkplain Register#number numbers} to register
+ * {@linkplain RegisterAttributes attributes} for a given register configuration and set of
+ * registers.
+ *
+ * @param registerConfig a register configuration
+ * @param registers a set of registers
+ * @return an array whose length is the max register number in {@code registers} plus 1. An
+ * element at index i holds the attributes of the register whose number is i.
+ */
+ public static RegisterAttributes[] createMap(RegisterConfig registerConfig, Register[] registers) {
+ RegisterAttributes[] map = new RegisterAttributes[registers.length];
+ for (Register reg : registers) {
+ if (reg != null) {
+ Register[] csr = registerConfig.getCalleeSaveRegisters();
+ RegisterAttributes attr = new RegisterAttributes(Arrays.asList(registerConfig.getCallerSaveRegisters()).contains(reg), csr == null ? false : Arrays.asList(csr).contains(reg),
+ Arrays.asList(registerConfig.getAllocatableRegisters()).contains(reg));
+ if (map.length <= reg.number) {
+ map = Arrays.copyOf(map, reg.number + 1);
+ }
+ map[reg.number] = attr;
+ }
+ }
+ for (int i = 0; i < map.length; i++) {
+ if (map[i] == null) {
+ map[i] = NONE;
+ }
+ }
+ return map;
+ }
+
+ /**
+ * @return Denotes a register that is available for use by a register allocator.
+ */
+ public boolean isAllocatable() {
+ return allocatable;
+ }
+
+ /**
+ * @return Denotes a register whose value preservation (if required) across a call is the
+ * responsibility of the callee.
+ */
+ public boolean isCalleeSave() {
+ return calleeSave;
+ }
+
+ /**
+ * @return Denotes a register whose value preservation (if required) across a call is the
+ * responsibility of the caller.
+ */
+ public boolean isCallerSave() {
+ return callerSave;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.code.CallingConvention.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical
+ * registers.
+ */
+public interface RegisterConfig {
+
+ /**
+ * Gets the register to be used for returning a value of a given kind.
+ */
+ Register getReturnRegister(JavaKind kind);
+
+ /**
+ * Gets the maximum allowed size of the frame.
+ */
+ default int getMaximumFrameSize() {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Gets the register to which {@link Register#Frame} and {@link Register#CallerFrame} are bound.
+ */
+ Register getFrameRegister();
+
+ /**
+ * Gets the calling convention describing how arguments are passed.
+ *
+ * @param type the type of calling convention being requested
+ * @param returnType the return type (can be null for methods returning {@code void})
+ * @param parameterTypes the types of the arguments of the call
+ * @param target the target platform
+ * @param stackOnly ignore registers
+ */
+ CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly);
+
+ /**
+ * Gets the ordered set of registers that are can be used to pass parameters according to a
+ * given calling convention.
+ *
+ * @param type the type of calling convention
+ * @param kind specifies what kind of registers is being requested
+ * @return the ordered set of registers that may be used to pass parameters in a call conforming
+ * to {@code type}
+ */
+ Register[] getCallingConventionRegisters(Type type, JavaKind kind);
+
+ /**
+ * Gets the set of all registers that might be used by the register allocator.
+ *
+ * To get the set of registers the register allocator is allowed to use see
+ * {@link RegisterAllocationConfig#getAllocatableRegisters()}
+ */
+ @SuppressWarnings("javadoc")
+ Register[] getAllocatableRegisters();
+
+ /**
+ * Filters a set of registers and returns only those that can be used by the register allocator
+ * for a value of a particular kind.
+ */
+ Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers);
+
+ /**
+ * Gets the registers whose values must be preserved by a method across any call it makes.
+ */
+ Register[] getCallerSaveRegisters();
+
+ /**
+ * Gets the registers whose values must be preserved by the callee.
+ */
+ Register[] getCalleeSaveRegisters();
+
+ /**
+ * Gets a map from register {@linkplain Register#number numbers} to register
+ * {@linkplain RegisterAttributes attributes} for this register configuration.
+ *
+ * @return an array where an element at index i holds the attributes of the register whose
+ * number is i
+ */
+ RegisterAttributes[] getAttributesMap();
+
+ /**
+ * Gets the register corresponding to a runtime-defined role.
+ *
+ * @param id the identifier of a runtime-defined register role
+ * @return the register playing the role specified by {@code id}
+ */
+ Register getRegisterForRole(int id);
+
+ /**
+ * Determines if all {@link #getAllocatableRegisters() allocatable} registers are
+ * {@link #getCallerSaveRegisters() caller saved}.
+ */
+ boolean areAllAllocatableRegistersCallerSaved();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+/**
+ * A map from registers to frame slots. This can be used to describe where callee saved registers
+ * are saved in a callee's frame.
+ */
+public final class RegisterSaveLayout {
+
+ /**
+ * Keys.
+ */
+ private final Register[] registers;
+
+ /**
+ * Slot indexes relative to stack pointer.
+ */
+ private final int[] slots;
+
+ /**
+ * Creates a map from registers to frame slots.
+ *
+ * @param registers the keys in the map
+ * @param slots frame slot index for each register in {@code registers}
+ */
+ public RegisterSaveLayout(Register[] registers, int[] slots) {
+ assert registers.length == slots.length;
+ this.registers = registers;
+ this.slots = slots;
+ assert registersToSlots(false).size() == registers.length : "non-unique registers";
+ assert new HashSet<>(registersToSlots(false).values()).size() == slots.length : "non-unqiue slots";
+ }
+
+ /**
+ * Gets the frame slot index for a given register.
+ *
+ * @param register register to get the frame slot index for
+ * @return frame slot index
+ */
+ public int registerToSlot(Register register) {
+ for (int i = 0; i < registers.length; i++) {
+ if (register.equals(registers[i])) {
+ return slots[i];
+ }
+ }
+ throw new IllegalArgumentException(register + " not saved by this layout: " + this);
+ }
+
+ /**
+ * Gets this layout information as a {@link Map} from registers to slots.
+ */
+ public Map<Register, Integer> registersToSlots(boolean sorted) {
+ Map<Register, Integer> result;
+ if (sorted) {
+ result = new TreeMap<>();
+ } else {
+ result = new HashMap<>();
+ }
+ for (int i = 0; i < registers.length; i++) {
+ result.put(registers[i], slots[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Gets this layout information as a {@link Map} from slots to registers.
+ */
+ public Map<Integer, Register> slotsToRegisters(boolean sorted) {
+ Map<Integer, Register> result;
+ if (sorted) {
+ result = new TreeMap<>();
+ } else {
+ result = new HashMap<>();
+ }
+ for (int i = 0; i < registers.length; i++) {
+ result.put(slots[i], registers[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RegisterSaveLayout) {
+ RegisterSaveLayout that = (RegisterSaveLayout) obj;
+ if (Arrays.equals(registers, that.registers) && Arrays.equals(slots, that.slots)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return registersToSlots(true).toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance
+ * of {@link RegisterValue} for each ({@link Register}, {@link JavaKind}) pair. Use
+ * {@link Register#asValue(LIRKind)} to retrieve the canonical {@link RegisterValue} instance for a
+ * given (register,kind) pair.
+ */
+public final class RegisterValue extends AllocatableValue {
+
+ private final Register reg;
+
+ /**
+ * Should only be called from {@link Register#Register} to ensure canonicalization.
+ */
+ protected RegisterValue(LIRKind kind, Register register) {
+ super(kind);
+ this.reg = register;
+ }
+
+ @Override
+ public String toString() {
+ return getRegister().name + getKindSuffix();
+ }
+
+ /**
+ * @return the register that contains the value
+ */
+ public Register getRegister() {
+ return reg;
+ }
+
+ @Override
+ public int hashCode() {
+ return 29 * super.hashCode() + reg.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RegisterValue) {
+ RegisterValue other = (RegisterValue) obj;
+ return super.equals(obj) && reg.equals(other.reg);
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Class representing a exception with a stack trace of the currently processed position in the
+ * compiled Java program instead of the stack trace of the compiler. The exception of the compiler
+ * is saved as the cause of this exception.
+ */
+public abstract class SourceStackTrace extends BailoutException {
+ private static final long serialVersionUID = 2144811793442316776L;
+
+ public static SourceStackTrace create(Throwable cause, String format, StackTraceElement[] elements) {
+ return new SourceStackTrace(cause, format) {
+
+ private static final long serialVersionUID = 6279381376051787907L;
+
+ @Override
+ public final synchronized Throwable fillInStackTrace() {
+ assert elements != null;
+ setStackTrace(elements);
+ return this;
+ }
+ };
+ }
+
+ private SourceStackTrace(Throwable cause, String format) {
+ super(cause, format);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.code.ValueUtil.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents lock information in the debug information.
+ */
+public final class StackLockValue implements JavaValue {
+
+ private JavaValue owner;
+ private StackSlotValue slot;
+ private final boolean eliminated;
+
+ public StackLockValue(JavaValue object, StackSlotValue slot, boolean eliminated) {
+ this.owner = object;
+ this.slot = slot;
+ this.eliminated = eliminated;
+ }
+
+ public JavaValue getOwner() {
+ return owner;
+ }
+
+ public void setOwner(JavaValue newOwner) {
+ this.owner = newOwner;
+ }
+
+ public Value getSlot() {
+ return slot;
+ }
+
+ public boolean isEliminated() {
+ return eliminated;
+ }
+
+ @Override
+ public String toString() {
+ return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 43;
+ int result = super.hashCode();
+ result = prime * result + (eliminated ? 1231 : 1237);
+ result = prime * result + owner.hashCode();
+ result = prime * result + slot.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof StackLockValue) {
+ StackLockValue other = (StackLockValue) obj;
+ return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot);
+ }
+ return false;
+ }
+
+ public void setSlot(StackSlotValue stackSlot) {
+ assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
+ slot = stackSlot;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
+ * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
+ */
+public final class StackSlot extends StackSlotValue {
+
+ private final int offset;
+ private final boolean addFrameSize;
+
+ /**
+ * Gets a {@link StackSlot} instance representing a stack slot at a given index holding a value
+ * of a given kind.
+ *
+ * @param kind The kind of the value stored in the stack slot.
+ * @param offset The offset of the stack slot (in bytes)
+ * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the
+ * beginning of the frame (stack pointer + total frame size).
+ */
+ public static StackSlot get(LIRKind kind, int offset, boolean addFrameSize) {
+ assert addFrameSize || offset >= 0;
+ return new StackSlot(kind, offset, addFrameSize);
+ }
+
+ /**
+ * Private constructor to enforce use of {@link #get(LIRKind, int, boolean)} so that a cache can
+ * be used.
+ */
+ private StackSlot(LIRKind kind, int offset, boolean addFrameSize) {
+ super(kind);
+ this.offset = offset;
+ this.addFrameSize = addFrameSize;
+ }
+
+ /**
+ * Gets the offset of this stack slot, relative to the stack pointer.
+ *
+ * @return The offset of this slot (in bytes).
+ */
+ public int getOffset(int totalFrameSize) {
+ assert totalFrameSize > 0 || !addFrameSize;
+ int result = offset + (addFrameSize ? totalFrameSize : 0);
+ assert result >= 0;
+ return result;
+ }
+
+ public boolean isInCallerFrame() {
+ return addFrameSize && offset >= 0;
+ }
+
+ public int getRawOffset() {
+ return offset;
+ }
+
+ public boolean getRawAddFrameSize() {
+ return addFrameSize;
+ }
+
+ @Override
+ public String toString() {
+ if (!addFrameSize) {
+ return "out:" + offset + getKindSuffix();
+ } else if (offset >= 0) {
+ return "in:" + offset + getKindSuffix();
+ } else {
+ return "stack:" + (-offset) + getKindSuffix();
+ }
+ }
+
+ /**
+ * Gets this stack slot used to pass an argument from the perspective of a caller.
+ */
+ public StackSlot asOutArg() {
+ assert offset >= 0;
+ if (addFrameSize) {
+ return get(getLIRKind(), offset, false);
+ }
+ return this;
+ }
+
+ /**
+ * Gets this stack slot used to pass an argument from the perspective of a callee.
+ */
+ public StackSlot asInArg() {
+ assert offset >= 0;
+ if (!addFrameSize) {
+ return get(getLIRKind(), offset, true);
+ }
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 37;
+ int result = super.hashCode();
+ result = prime * result + (addFrameSize ? 1231 : 1237);
+ result = prime * result + offset;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof StackSlot) {
+ StackSlot other = (StackSlot) obj;
+ return super.equals(obj) && addFrameSize == other.addFrameSize && offset == other.offset;
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlotValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Common base class for {@linkplain StackSlot real} and {@linkplain VirtualStackSlot virtual} stack
+ * slots.
+ */
+public abstract class StackSlotValue extends AllocatableValue {
+
+ public StackSlotValue(LIRKind lirKind) {
+ super(lirKind);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.meta.MetaUtil.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the target machine for a compiler, including the CPU architecture, the size of
+ * pointers and references, alignment of stacks, caches, etc.
+ */
+public class TargetDescription {
+
+ public final Architecture arch;
+
+ /**
+ * Specifies if this is a multi-processor system.
+ */
+ public final boolean isMP;
+
+ /**
+ * Specifies if this target supports encoding objects inline in the machine code.
+ */
+ public final boolean inlineObjects;
+
+ /**
+ * The machine word size on this target.
+ */
+ public final int wordSize;
+
+ /**
+ * The kind to be used for representing raw pointers and CPU registers.
+ */
+ public final JavaKind wordKind;
+
+ /**
+ * The stack alignment requirement of the platform. For example, from Appendix D of <a
+ * href="http://www.intel.com/Assets/PDF/manual/248966.pdf">Intel 64 and IA-32 Architectures
+ * Optimization Reference Manual</a>:
+ *
+ * <pre>
+ * "It is important to ensure that the stack frame is aligned to a
+ * 16-byte boundary upon function entry to keep local __m128 data,
+ * parameters, and XMM register spill locations aligned throughout
+ * a function invocation."
+ * </pre>
+ */
+ public final int stackAlignment;
+
+ /**
+ * Maximum constant displacement at which a memory access can no longer be an implicit null
+ * check.
+ */
+ public final int implicitNullCheckLimit;
+
+ public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) {
+ this.arch = arch;
+ this.isMP = isMP;
+ this.wordSize = arch.getWordSize();
+ this.wordKind = JavaKind.fromWordSize(wordSize);
+ this.stackAlignment = stackAlignment;
+ this.implicitNullCheckLimit = implicitNullCheckLimit;
+ this.inlineObjects = inlineObjects;
+ }
+
+ @Override
+ public final int hashCode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TargetDescription) {
+ TargetDescription that = (TargetDescription) obj;
+ // @formatter:off
+ if (this.implicitNullCheckLimit == that.implicitNullCheckLimit &&
+ this.inlineObjects == that.inlineObjects &&
+ this.isMP == that.isMP &&
+ this.stackAlignment == that.stackAlignment &&
+ this.wordKind.equals(that.wordKind) &&
+ this.wordSize == that.wordSize &&
+ this.arch.equals(that.arch)) {
+ return true;
+ }
+ // @formatter:on
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return identityHashCodeString(this);
+ }
+
+ public int getSizeInBytes(PlatformKind kind) {
+ return kind.getSizeInBytes();
+ }
+
+ public LIRKind getLIRKind(JavaKind javaKind) {
+ PlatformKind platformKind = arch.getPlatformKind(javaKind);
+ if (javaKind.isObject()) {
+ return LIRKind.reference(platformKind);
+ } else {
+ return LIRKind.value(platformKind);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2011, 2011, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.math.*;
+
+//JaCoCo Exclude
+
+/**
+ * Utilities for unsigned comparisons. All methods have correct, but slow, standard Java
+ * implementations so that they can be used with compilers not supporting the intrinsics.
+ */
+public class UnsignedMath {
+
+ private static final long MASK = 0xffffffffL;
+
+ /**
+ * Unsigned comparison aboveThan for two numbers.
+ */
+ public static boolean aboveThan(int a, int b) {
+ return (a & MASK) > (b & MASK);
+ }
+
+ /**
+ * Unsigned comparison aboveOrEqual for two numbers.
+ */
+ public static boolean aboveOrEqual(int a, int b) {
+ return (a & MASK) >= (b & MASK);
+ }
+
+ /**
+ * Unsigned comparison belowThan for two numbers.
+ */
+ public static boolean belowThan(int a, int b) {
+ return (a & MASK) < (b & MASK);
+ }
+
+ /**
+ * Unsigned comparison belowOrEqual for two numbers.
+ */
+ public static boolean belowOrEqual(int a, int b) {
+ return (a & MASK) <= (b & MASK);
+ }
+
+ /**
+ * Unsigned comparison aboveThan for two numbers.
+ */
+ public static boolean aboveThan(long a, long b) {
+ return (a > b) ^ ((a < 0) != (b < 0));
+ }
+
+ /**
+ * Unsigned comparison aboveOrEqual for two numbers.
+ */
+ public static boolean aboveOrEqual(long a, long b) {
+ return (a >= b) ^ ((a < 0) != (b < 0));
+ }
+
+ /**
+ * Unsigned comparison belowThan for two numbers.
+ */
+ public static boolean belowThan(long a, long b) {
+ return (a < b) ^ ((a < 0) != (b < 0));
+ }
+
+ /**
+ * Unsigned comparison belowOrEqual for two numbers.
+ */
+ public static boolean belowOrEqual(long a, long b) {
+ return (a <= b) ^ ((a < 0) != (b < 0));
+ }
+
+ /**
+ * Unsigned division for two numbers.
+ */
+ public static int divide(int a, int b) {
+ return (int) ((a & MASK) / (b & MASK));
+ }
+
+ /**
+ * Unsigned remainder for two numbers.
+ */
+ public static int remainder(int a, int b) {
+ return (int) ((a & MASK) % (b & MASK));
+ }
+
+ /**
+ * Unsigned division for two numbers.
+ */
+ public static long divide(long a, long b) {
+ return bi(a).divide(bi(b)).longValue();
+ }
+
+ /**
+ * Unsigned remainder for two numbers.
+ */
+ public static long remainder(long a, long b) {
+ return bi(a).remainder(bi(b)).longValue();
+ }
+
+ private static BigInteger bi(long unsigned) {
+ return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Utility class for working with the {@link Value} class and its subclasses.
+ */
+public final class ValueUtil {
+
+ public static boolean isIllegal(Value value) {
+ assert value != null;
+ return Value.ILLEGAL.equals(value);
+ }
+
+ public static boolean isIllegalJavaValue(JavaValue value) {
+ assert value != null;
+ return Value.ILLEGAL.equals(value);
+ }
+
+ public static boolean isLegal(Value value) {
+ return !isIllegal(value);
+ }
+
+ public static boolean isVirtualObject(JavaValue value) {
+ assert value != null;
+ return value instanceof VirtualObject;
+ }
+
+ public static VirtualObject asVirtualObject(JavaValue value) {
+ assert value != null;
+ return (VirtualObject) value;
+ }
+
+ public static boolean isConstantJavaValue(JavaValue value) {
+ assert value != null;
+ return value instanceof JavaConstant;
+ }
+
+ public static boolean isAllocatableValue(Value value) {
+ assert value != null;
+ return value instanceof AllocatableValue;
+ }
+
+ public static AllocatableValue asAllocatableValue(Value value) {
+ assert value != null;
+ return (AllocatableValue) value;
+ }
+
+ public static boolean isStackSlot(Value value) {
+ assert value != null;
+ return value instanceof StackSlot;
+ }
+
+ public static StackSlot asStackSlot(Value value) {
+ assert value != null;
+ return (StackSlot) value;
+ }
+
+ public static boolean isStackSlotValue(Value value) {
+ assert value != null;
+ return value instanceof StackSlotValue;
+ }
+
+ public static StackSlotValue asStackSlotValue(Value value) {
+ assert value != null;
+ return (StackSlotValue) value;
+ }
+
+ public static boolean isVirtualStackSlot(Value value) {
+ assert value != null;
+ return value instanceof VirtualStackSlot;
+ }
+
+ public static VirtualStackSlot asVirtualStackSlot(Value value) {
+ assert value != null;
+ return (VirtualStackSlot) value;
+ }
+
+ public static boolean isRegister(Value value) {
+ assert value != null;
+ return value instanceof RegisterValue;
+ }
+
+ public static Register asRegister(Value value) {
+ return asRegisterValue(value).getRegister();
+ }
+
+ public static RegisterValue asRegisterValue(Value value) {
+ assert value != null;
+ return (RegisterValue) value;
+ }
+
+ public static Register asRegister(Value value, PlatformKind kind) {
+ if (value.getPlatformKind() != kind) {
+ throw new InternalError("needed: " + kind + " got: " + value.getPlatformKind());
+ } else {
+ return asRegister(value);
+ }
+ }
+
+ public static boolean sameRegister(Value v1, Value v2) {
+ return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2));
+ }
+
+ public static boolean sameRegister(Value v1, Value v2, Value v3) {
+ return sameRegister(v1, v2) && sameRegister(v1, v3);
+ }
+
+ /**
+ * Checks if all the provided values are different physical registers. The parameters can be
+ * either {@link Register registers}, {@link Value values} or arrays of them. All values that
+ * are not {@link RegisterValue registers} are ignored.
+ */
+ public static boolean differentRegisters(Object... values) {
+ List<Register> registers = collectRegisters(values, new ArrayList<Register>());
+ for (int i = 1; i < registers.size(); i++) {
+ Register r1 = registers.get(i);
+ for (int j = 0; j < i; j++) {
+ Register r2 = registers.get(j);
+ if (r1.equals(r2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static List<Register> collectRegisters(Object[] values, List<Register> registers) {
+ for (Object o : values) {
+ if (o instanceof Register) {
+ registers.add((Register) o);
+ } else if (o instanceof Value) {
+ if (isRegister((Value) o)) {
+ registers.add(asRegister((Value) o));
+ }
+ } else if (o instanceof Object[]) {
+ collectRegisters((Object[]) o, registers);
+ } else {
+ throw new IllegalArgumentException("Not a Register or Value: " + o);
+ }
+ }
+ return registers;
+ }
+
+ /**
+ * Subtract sets of registers (x - y).
+ *
+ * @param x a set of register to subtract from.
+ * @param y a set of registers to subtract.
+ * @return resulting set of registers (x - y).
+ */
+ public static Value[] subtractRegisters(Value[] x, Value[] y) {
+ ArrayList<Value> result = new ArrayList<>(x.length);
+ for (Value i : x) {
+ boolean append = true;
+ for (Value j : y) {
+ if (ValueUtil.sameRegister(i, j)) {
+ append = false;
+ break;
+ }
+ }
+ if (append) {
+ result.add(i);
+ }
+ }
+ Value[] resultArray = new Value[result.size()];
+ return result.toArray(resultArray);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2010, 2015, 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * An instance of this class represents an object whose allocation was removed by escape analysis.
+ * The information stored in the {@link VirtualObject} is used during deoptimization to recreate the
+ * object.
+ */
+public final class VirtualObject implements JavaValue {
+
+ private final ResolvedJavaType type;
+ private JavaValue[] values;
+ private JavaKind[] slotKinds;
+ private final int id;
+
+ /**
+ * Creates a new {@link VirtualObject} for the given type, with the given fields. If
+ * {@code type} is an instance class then {@code values} provides the values for the fields
+ * returned by {@link ResolvedJavaType#getInstanceFields(boolean) getInstanceFields(true)}. If
+ * {@code type} is an array then the length of the values array determines the reallocated array
+ * length.
+ *
+ * @param type the type of the object whose allocation was removed during compilation. This can
+ * be either an instance of an array type.
+ * @param id a unique id that identifies the object within the debug information for one
+ * position in the compiled code.
+ * @return a new {@link VirtualObject} instance.
+ */
+ public static VirtualObject get(ResolvedJavaType type, int id) {
+ return new VirtualObject(type, id);
+ }
+
+ private VirtualObject(ResolvedJavaType type, int id) {
+ this.type = type;
+ this.id = id;
+ }
+
+ private static StringBuilder appendValue(StringBuilder buf, JavaValue value, Set<VirtualObject> visited) {
+ if (value instanceof VirtualObject) {
+ VirtualObject vo = (VirtualObject) value;
+ buf.append("vobject:").append(vo.type.toJavaName(false)).append(':').append(vo.id);
+ if (!visited.contains(vo)) {
+ visited.add(vo);
+ buf.append('{');
+ if (vo.values == null) {
+ buf.append("<uninitialized>");
+ } else {
+ if (vo.type.isArray()) {
+ for (int i = 0; i < vo.values.length; i++) {
+ if (i != 0) {
+ buf.append(',');
+ }
+ buf.append(i).append('=');
+ appendValue(buf, vo.values[i], visited);
+ }
+ } else {
+ ResolvedJavaField[] fields = vo.type.getInstanceFields(true);
+ assert fields.length == vo.values.length : vo.type + ", fields=" + Arrays.toString(fields) + ", values=" + Arrays.toString(vo.values);
+ for (int i = 0; i < vo.values.length; i++) {
+ if (i != 0) {
+ buf.append(',');
+ }
+ buf.append(fields[i].getName()).append('=');
+ appendValue(buf, vo.values[i], visited);
+ }
+ }
+ }
+ buf.append('}');
+ }
+ } else {
+ buf.append(value);
+ }
+ return buf;
+ }
+
+ @Override
+ public String toString() {
+ Set<VirtualObject> visited = Collections.newSetFromMap(new IdentityHashMap<VirtualObject, Boolean>());
+ return appendValue(new StringBuilder(), this, visited).toString();
+ }
+
+ /**
+ * Returns the type of the object whose allocation was removed during compilation. This can be
+ * either an instance of an array type.
+ */
+ public ResolvedJavaType getType() {
+ return type;
+ }
+
+ /**
+ * Returns an array containing all the values to be stored into the object when it is recreated.
+ */
+ public JavaValue[] getValues() {
+ return values;
+ }
+
+ /**
+ * Returns an array containing the Java kind of all values in the object.
+ */
+ public JavaKind[] getSlotKinds() {
+ return slotKinds;
+ }
+
+ /**
+ * Returns the unique id that identifies the object within the debug information for one
+ * position in the compiled code.
+ */
+ public int getId() {
+ return id;
+ }
+
+ private boolean checkValues() {
+ assert (values == null) == (slotKinds == null);
+ if (values != null) {
+ assert values.length == slotKinds.length;
+ if (!type.isArray()) {
+ ResolvedJavaField[] fields = type.getInstanceFields(true);
+ int fieldIndex = 0;
+ for (int i = 0; i < values.length; i++) {
+ ResolvedJavaField field = fields[fieldIndex++];
+ JavaKind valKind = slotKinds[i].getStackKind();
+ if (field.getJavaKind() == JavaKind.Object) {
+ assert valKind.isObject() : field + ": " + valKind + " != " + field.getJavaKind();
+ } else {
+ if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && field.getJavaKind() == JavaKind.Int) {
+ assert fields[fieldIndex].getJavaKind() == JavaKind.Int;
+ fieldIndex++;
+ } else {
+ assert valKind == field.getJavaKind().getStackKind() : field + ": " + valKind + " != " + field.getJavaKind();
+ }
+ }
+ }
+ assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
+ } else {
+ JavaKind componentKind = type.getComponentType().getJavaKind().getStackKind();
+ if (componentKind == JavaKind.Object) {
+ for (int i = 0; i < values.length; i++) {
+ assert slotKinds[i].isObject() : slotKinds[i] + " != " + componentKind;
+ }
+ } else {
+ for (int i = 0; i < values.length; i++) {
+ assert slotKinds[i] == componentKind || componentKind.getBitCount() >= slotKinds[i].getBitCount() ||
+ (componentKind == JavaKind.Int && slotKinds[i].getBitCount() >= JavaKind.Int.getBitCount()) : slotKinds[i] + " != " + componentKind;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Overwrites the current set of values with a new one.
+ *
+ * @param values an array containing all the values to be stored into the object when it is
+ * recreated.
+ * @param slotKinds an array containing the Java kinds of the values.
+ */
+ public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
+ this.values = values;
+ this.slotKinds = slotKinds;
+ assert checkValues();
+ }
+
+ @Override
+ public int hashCode() {
+ return 42 + type.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof VirtualObject) {
+ VirtualObject l = (VirtualObject) o;
+ if (!l.type.equals(type) || l.values.length != values.length) {
+ return false;
+ }
+ for (int i = 0; i < values.length; i++) {
+ /*
+ * Virtual objects can form cycles. Calling equals() could therefore lead to
+ * infinite recursion.
+ */
+ if (!same(values[i], l.values[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean same(Object o1, Object o2) {
+ return o1 == o2;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * {@link VirtualStackSlot}s are stack slots that are not yet fixed to specific frame offset. They
+ * are replaced by real {@link StackSlot}s with a fixed position in the frame before code emission.
+ */
+public abstract class VirtualStackSlot extends StackSlotValue {
+
+ private final int id;
+
+ public VirtualStackSlot(int id, LIRKind lirKind) {
+ super(lirKind);
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "vstack:" + id + getKindSuffix();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + id;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ VirtualStackSlot other = (VirtualStackSlot) obj;
+ if (id != other.id) {
+ return false;
+ }
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010, 2012, 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.
+ */
+/**
+ * Package that defines the interface between a Java application that wants to install code and the
+ * runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider}
+ * interface. The method
+ * {@link jdk.vm.ci.code.CodeCacheProvider#addMethod(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
+ * can be used to install code for a given method.
+ */
+package jdk.vm.ci.code;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.code.stack;
+
+import jdk.vm.ci.meta.*;
+
+public interface InspectedFrame {
+
+ /**
+ * Returns the value of the local at the given index. Currently only works for object values.
+ * This value is a copy iff {@link #isVirtual(int)} is true.
+ */
+ Object getLocal(int index);
+
+ /**
+ * Returns whether the local at the given index is a virtual object, and therefore the object
+ * returned by {@link #getLocal(int)} is a copy.
+ */
+ boolean isVirtual(int index);
+
+ /**
+ * Returns true if the stack frame is a compiled stack frame and there are virtual objects
+ * anywhere in the current state of the compiled method. This can return true even if
+ * {@link #isVirtual(int)} return false for all locals.
+ */
+ boolean hasVirtualObjects();
+
+ /**
+ * This method will materialize all virtual objects, deoptimize the stack frame and make sure
+ * that subsequent execution of the deoptimized frame uses the materialized values.
+ */
+ void materializeVirtualObjects(boolean invalidateCode);
+
+ /**
+ * @return the current bytecode index
+ */
+ int getBytecodeIndex();
+
+ /**
+ * @return the current method
+ */
+ ResolvedJavaMethod getMethod();
+
+ /**
+ * Checks if the current method is equal to the given method. This is semantically equivalent to
+ * {@code method.equals(getMethod())}, but can be implemented more efficiently.
+ */
+ boolean isMethod(ResolvedJavaMethod method);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrameVisitor.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.code.stack;
+
+/**
+ * Callback interface for {@link StackIntrospection#iterateFrames}. Implementations of
+ * {@link #visitFrame} return null to indicate that frame iteration should continue and the next
+ * caller frame should be visited; and return any non-null value to indicate that frame iteration
+ * should stop.
+ */
+public interface InspectedFrameVisitor<T> {
+
+ T visitFrame(InspectedFrame frame);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.code.stack;
+
+import jdk.vm.ci.meta.*;
+
+public interface StackIntrospection {
+
+ /**
+ * Accesses the current stack, providing {@link InspectedFrame}s to the visitor that can be used
+ * to inspect the stack frames' contents. Iteration continues as long as
+ * {@link InspectedFrameVisitor#visitFrame}, which is invoked for every {@link InspectedFrame},
+ * returns null. Any non-null result of the visitor indicates that frame iteration should stop.
+ *
+ * @param initialMethods if this is non-{@code null}, then the stack trace will start at these
+ * methods
+ * @param matchingMethods if this is non-{@code null}, then only matching stack frames are
+ * returned
+ * @param initialSkip the number of matching methods to skip (including the initial method)
+ * @param visitor the visitor that is called for every matching method
+ * @return the last result returned by the visitor (which is non-null to indicate that iteration
+ * should stop), or null if the whole stack was iterated.
+ */
+ <T> T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor<T> visitor);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.common;
+
+import java.util.*;
+
+/**
+ * Indicates a condition in JVMCI related code that should never occur during normal operation.
+ */
+public class JVMCIError extends Error {
+
+ private static final long serialVersionUID = 531632331813456233L;
+ private final ArrayList<String> context = new ArrayList<>();
+
+ public static RuntimeException unimplemented() {
+ throw new JVMCIError("unimplemented");
+ }
+
+ public static RuntimeException unimplemented(String msg) {
+ throw new JVMCIError("unimplemented: %s", msg);
+ }
+
+ public static RuntimeException shouldNotReachHere() {
+ throw new JVMCIError("should not reach here");
+ }
+
+ public static RuntimeException shouldNotReachHere(String msg) {
+ throw new JVMCIError("should not reach here: %s", msg);
+ }
+
+ public static RuntimeException shouldNotReachHere(Throwable cause) {
+ throw new JVMCIError(cause);
+ }
+
+ /**
+ * Checks a given condition and throws a {@link JVMCIError} if it is false. Guarantees are
+ * stronger than assertions in that they are always checked. Error messages for guarantee
+ * violations should clearly indicate the nature of the problem as well as a suggested solution
+ * if possible.
+ *
+ * @param condition the condition to check
+ * @param msg the message that will be associated with the error, in
+ * {@link String#format(String, Object...)} syntax
+ * @param args arguments to the format string
+ */
+ public static void guarantee(boolean condition, String msg, Object... args) {
+ if (!condition) {
+ throw new JVMCIError("failed guarantee: " + msg, args);
+ }
+ }
+
+ /**
+ * This constructor creates a {@link JVMCIError} with a given message.
+ *
+ * @param msg the message that will be associated with the error
+ */
+ public JVMCIError(String msg) {
+ super(msg);
+ }
+
+ /**
+ * This constructor creates a {@link JVMCIError} with a message assembled via
+ * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
+ * always generate the same output.
+ *
+ * @param msg the message that will be associated with the error, in String.format syntax
+ * @param args parameters to String.format - parameters that implement {@link Iterable} will be
+ * expanded into a [x, x, ...] representation.
+ */
+ public JVMCIError(String msg, Object... args) {
+ super(format(msg, args));
+ }
+
+ /**
+ * This constructor creates a {@link JVMCIError} for a given causing Throwable instance.
+ *
+ * @param cause the original exception that contains additional information on this error
+ */
+ public JVMCIError(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * This constructor creates a {@link JVMCIError} and adds all the
+ * {@linkplain #addContext(String) context} of another {@link JVMCIError}.
+ *
+ * @param e the original {@link JVMCIError}
+ */
+ public JVMCIError(JVMCIError e) {
+ super(e);
+ context.addAll(e.context);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ str.append(super.toString());
+ for (String s : context) {
+ str.append("\n\tat ").append(s);
+ }
+ return str.toString();
+ }
+
+ private static String format(String msg, Object... args) {
+ if (args != null) {
+ // expand Iterable parameters into a list representation
+ for (int i = 0; i < args.length; i++) {
+ if (args[i] instanceof Iterable<?>) {
+ ArrayList<Object> list = new ArrayList<>();
+ for (Object o : (Iterable<?>) args[i]) {
+ list.add(o);
+ }
+ args[i] = list.toString();
+ }
+ }
+ }
+ return String.format(Locale.ENGLISH, msg, args);
+ }
+
+ public JVMCIError addContext(String newContext) {
+ this.context.add(newContext);
+ return this;
+ }
+
+ public JVMCIError addContext(String name, Object obj) {
+ return addContext(format("%s: %s", name, obj));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/UnsafeUtil.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, 2012, 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.
+ */
+package jdk.vm.ci.common;
+
+import sun.misc.Unsafe;
+
+/**
+ * Utilities for operating on raw memory with {@link Unsafe}.
+ */
+public class UnsafeUtil {
+
+ /**
+ * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'}
+ * terminated C string. The native memory buffer is allocated via
+ * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when
+ * it is no longer needed via {@link Unsafe#freeMemory(long)}.
+ *
+ * @return the native memory pointer of the C string created from {@code s}
+ */
+ public static long createCString(Unsafe unsafe, String s) {
+ return writeCString(unsafe, s, unsafe.allocateMemory(s.length() + 1));
+ }
+
+ /**
+ * Reads a {@code '\0'} terminated C string from native memory and converts it to a
+ * {@link String}.
+ *
+ * @return a Java string
+ */
+ public static String readCString(Unsafe unsafe, long address) {
+ if (address == 0) {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0;; i++) {
+ char c = (char) unsafe.getByte(address + i);
+ if (c == 0) {
+ break;
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'}
+ * terminated C string. The caller is responsible for ensuring the buffer is at least
+ * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer
+ * when it is no longer.
+ *
+ * @return the value of {@code buf}
+ */
+ public static long writeCString(Unsafe unsafe, String s, long buf) {
+ int size = s.length();
+ for (int i = 0; i < size; i++) {
+ unsafe.putByte(buf + i, (byte) s.charAt(i));
+ }
+ unsafe.putByte(buf + size, (byte) '\0');
+ return buf;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.compiler;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.options.*;
+
+public interface Compiler {
+ int INVOCATION_ENTRY_BCI = -1;
+
+ @Option(help = "", type = OptionType.Debug) OptionValue<String> PrintFilter = new OptionValue<>(null);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
+ @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
+
+ /**
+ * Request the compilation of a method by this JVMCI compiler. The compiler should compile the
+ * method to machine code and install it in the code cache if the compilation is successful.
+ *
+ * @param method the method that should be compiled
+ * @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation
+ * request and all other values denote an OSR compilation request
+ * @param jvmciEnv pointer to native {@code JVMCIEnv} object
+ * @param id a unique identifier for this compilation
+ */
+ void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.compiler;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.runtime.*;
+
+/**
+ * Factory for a JVMCI compiler.
+ */
+public interface CompilerFactory {
+
+ /**
+ * Get the name of this compiler. The compiler will be selected when the jvmci.compiler system
+ * property is equal to this name.
+ */
+ String getCompilerName();
+
+ /**
+ * Initialize an {@link Architecture}. The compiler has the opportunity to extend the
+ * {@link Architecture} description with a custom subclass.
+ */
+ Architecture initializeArchitecture(Architecture arch);
+
+ /**
+ * Create a new instance of the {@link Compiler}.
+ */
+ Compiler createCompiler(JVMCIRuntime runtime);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.compiler;
+
+public interface StartupEventListener {
+
+ /**
+ * This method is called before any of the {@link CompilerFactory} methods.
+ */
+ void beforeJVMCIStartup();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.hotspot.amd64;
+
+import static jdk.vm.ci.inittimer.InitTimer.*;
+
+import java.util.*;
+
+import jdk.vm.ci.amd64.*;
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.compiler.*;
+import jdk.vm.ci.hotspot.*;
+import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.service.*;
+
+@ServiceProvider(HotSpotJVMCIBackendFactory.class)
+public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
+
+ protected EnumSet<AMD64.CPUFeature> computeFeatures(HotSpotVMConfig config) {
+ // Configure the feature set using the HotSpot flag settings.
+ EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
+ if ((config.x86CPUFeatures & config.cpu3DNOWPREFETCH) != 0) {
+ features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH);
+ }
+ assert config.useSSE >= 2 : "minimum config for x64";
+ features.add(AMD64.CPUFeature.SSE);
+ features.add(AMD64.CPUFeature.SSE2);
+ if ((config.x86CPUFeatures & config.cpuSSE3) != 0) {
+ features.add(AMD64.CPUFeature.SSE3);
+ }
+ if ((config.x86CPUFeatures & config.cpuSSSE3) != 0) {
+ features.add(AMD64.CPUFeature.SSSE3);
+ }
+ if ((config.x86CPUFeatures & config.cpuSSE4A) != 0) {
+ features.add(AMD64.CPUFeature.SSE4A);
+ }
+ if ((config.x86CPUFeatures & config.cpuSSE41) != 0) {
+ features.add(AMD64.CPUFeature.SSE4_1);
+ }
+ if ((config.x86CPUFeatures & config.cpuSSE42) != 0) {
+ features.add(AMD64.CPUFeature.SSE4_2);
+ }
+ if ((config.x86CPUFeatures & config.cpuPOPCNT) != 0) {
+ features.add(AMD64.CPUFeature.POPCNT);
+ }
+ if ((config.x86CPUFeatures & config.cpuLZCNT) != 0) {
+ features.add(AMD64.CPUFeature.LZCNT);
+ }
+ if ((config.x86CPUFeatures & config.cpuAVX) != 0) {
+ features.add(AMD64.CPUFeature.AVX);
+ }
+ if ((config.x86CPUFeatures & config.cpuAVX2) != 0) {
+ features.add(AMD64.CPUFeature.AVX2);
+ }
+ if ((config.x86CPUFeatures & config.cpuAES) != 0) {
+ features.add(AMD64.CPUFeature.AES);
+ }
+ if ((config.x86CPUFeatures & config.cpuERMS) != 0) {
+ features.add(AMD64.CPUFeature.ERMS);
+ }
+ if ((config.x86CPUFeatures & config.cpuBMI1) != 0) {
+ features.add(AMD64.CPUFeature.BMI1);
+ }
+ return features;
+ }
+
+ protected EnumSet<AMD64.Flag> computeFlags(HotSpotVMConfig config) {
+ EnumSet<AMD64.Flag> flags = EnumSet.noneOf(AMD64.Flag.class);
+ if (config.useCountLeadingZerosInstruction) {
+ flags.add(AMD64.Flag.UseCountLeadingZerosInstruction);
+ }
+ if (config.useCountTrailingZerosInstruction) {
+ flags.add(AMD64.Flag.UseCountTrailingZerosInstruction);
+ }
+ return flags;
+ }
+
+ protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
+ final int stackFrameAlignment = 16;
+ final int implicitNullCheckLimit = 4096;
+ final boolean inlineObjects = true;
+ Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
+ return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+ }
+
+ protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
+ return new HotSpotConstantReflectionProvider(runtime);
+ }
+
+ protected RegisterConfig createRegisterConfig(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target) {
+ return new AMD64HotSpotRegisterConfig(target.arch, runtime.getConfig());
+ }
+
+ protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
+ return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
+ }
+
+ protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntimeProvider runtime) {
+ return new HotSpotMetaAccessProvider(runtime);
+ }
+
+ @Override
+ public String getArchitecture() {
+ return "AMD64";
+ }
+
+ @Override
+ public String toString() {
+ return "JVMCIBackend:" + getArchitecture();
+ }
+
+ @SuppressWarnings("try")
+ public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
+
+ assert host == null;
+ TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
+
+ RegisterConfig regConfig;
+ HotSpotCodeCacheProvider codeCache;
+ ConstantReflectionProvider constantReflection;
+ HotSpotMetaAccessProvider metaAccess;
+ try (InitTimer t = timer("create providers")) {
+ try (InitTimer rt = timer("create MetaAccess provider")) {
+ metaAccess = createMetaAccess(runtime);
+ }
+ try (InitTimer rt = timer("create RegisterConfig")) {
+ regConfig = createRegisterConfig(runtime, target);
+ }
+ try (InitTimer rt = timer("create CodeCache provider")) {
+ codeCache = createCodeCache(runtime, target, regConfig);
+ }
+ try (InitTimer rt = timer("create ConstantReflection provider")) {
+ constantReflection = createConstantReflection(runtime);
+ }
+ }
+ try (InitTimer rt = timer("instantiate backend")) {
+ return createBackend(metaAccess, codeCache, constantReflection);
+ }
+ }
+
+ protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
+ return new JVMCIBackend(metaAccess, codeCache, constantReflection);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot.amd64;
+
+import static jdk.vm.ci.amd64.AMD64.*;
+
+import java.util.*;
+
+import jdk.vm.ci.amd64.*;
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.CallingConvention.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.hotspot.*;
+import jdk.vm.ci.meta.*;
+
+public class AMD64HotSpotRegisterConfig implements RegisterConfig {
+
+ private final Architecture architecture;
+
+ private final Register[] allocatable;
+
+ private final int maxFrameSize;
+
+ /**
+ * The caller saved registers always include all parameter registers.
+ */
+ private final Register[] callerSaved;
+
+ private final boolean allAllocatableAreCallerSaved;
+
+ private final RegisterAttributes[] attributesMap;
+
+ public int getMaximumFrameSize() {
+ return maxFrameSize;
+ }
+
+ @Override
+ public Register[] getAllocatableRegisters() {
+ return allocatable.clone();
+ }
+
+ public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+ ArrayList<Register> list = new ArrayList<>();
+ for (Register reg : registers) {
+ if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
+ list.add(reg);
+ }
+ }
+
+ Register[] ret = list.toArray(new Register[list.size()]);
+ return ret;
+ }
+
+ @Override
+ public RegisterAttributes[] getAttributesMap() {
+ return attributesMap.clone();
+ }
+
+ private final Register[] javaGeneralParameterRegisters;
+ private final Register[] nativeGeneralParameterRegisters;
+ private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
+
+ /*
+ * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
+ * to store the argument registers
+ */
+ private final boolean needsNativeStackHomeSpace;
+
+ private static Register[] initAllocatable(boolean reserveForHeapBase) {
+ Register[] registers = null;
+ // @formatter:off
+ if (reserveForHeapBase) {
+ registers = new Register[] {
+ rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, /*r12,*/ r13, r14, /*r15, */
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+ } else {
+ registers = new Register[] {
+ rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, /*r15, */
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+ }
+ // @formatter:on
+ return registers;
+ }
+
+ public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
+ this(architecture, config, initAllocatable(config.useCompressedOops));
+ assert callerSaved.length >= allocatable.length;
+ }
+
+ public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, Register[] allocatable) {
+ this.architecture = architecture;
+ this.maxFrameSize = config.maxFrameSize;
+
+ if (config.windowsOs) {
+ javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
+ nativeGeneralParameterRegisters = new Register[]{rcx, rdx, r8, r9};
+ this.needsNativeStackHomeSpace = true;
+ } else {
+ javaGeneralParameterRegisters = new Register[]{rsi, rdx, rcx, r8, r9, rdi};
+ nativeGeneralParameterRegisters = new Register[]{rdi, rsi, rdx, rcx, r8, r9};
+ this.needsNativeStackHomeSpace = false;
+ }
+
+ this.allocatable = allocatable.clone();
+ Set<Register> callerSaveSet = new HashSet<>();
+ Collections.addAll(callerSaveSet, allocatable);
+ Collections.addAll(callerSaveSet, xmmParameterRegisters);
+ Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
+ Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
+ callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+
+ allAllocatableAreCallerSaved = true;
+ attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
+ }
+
+ @Override
+ public Register[] getCallerSaveRegisters() {
+ return callerSaved;
+ }
+
+ public Register[] getCalleeSaveRegisters() {
+ return null;
+ }
+
+ @Override
+ public boolean areAllAllocatableRegistersCallerSaved() {
+ return allAllocatableAreCallerSaved;
+ }
+
+ @Override
+ public Register getRegisterForRole(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+ if (type == Type.NativeCall) {
+ return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+ }
+ // On x64, parameter locations are the same whether viewed
+ // from the caller or callee perspective
+ return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+ }
+
+ public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Short:
+ case Char:
+ case Int:
+ case Long:
+ case Object:
+ return type == Type.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
+ case Float:
+ case Double:
+ return xmmParameterRegisters;
+ default:
+ throw JVMCIError.shouldNotReachHere();
+ }
+ }
+
+ private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
+ AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+ int currentGeneral = 0;
+ int currentXMM = 0;
+ int currentStackOffset = type == Type.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.length * target.wordSize : 0;
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+ final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
+
+ switch (kind) {
+ case Byte:
+ case Boolean:
+ case Short:
+ case Char:
+ case Int:
+ case Long:
+ case Object:
+ if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
+ Register register = generalParameterRegisters[currentGeneral++];
+ locations[i] = register.asValue(target.getLIRKind(kind));
+ }
+ break;
+ case Float:
+ case Double:
+ if (!stackOnly && currentXMM < xmmParameterRegisters.length) {
+ Register register = xmmParameterRegisters[currentXMM++];
+ locations[i] = register.asValue(target.getLIRKind(kind));
+ }
+ break;
+ default:
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ if (locations[i] == null) {
+ LIRKind lirKind = target.getLIRKind(kind);
+ locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
+ currentStackOffset += Math.max(target.getSizeInBytes(lirKind.getPlatformKind()), target.wordSize);
+ }
+ }
+
+ JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
+ AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(target.getLIRKind(returnKind.getStackKind()));
+ return new CallingConvention(currentStackOffset, returnLocation, locations);
+ }
+
+ @Override
+ public Register getReturnRegister(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ case Int:
+ case Long:
+ case Object:
+ return rax;
+ case Float:
+ case Double:
+ return xmm0;
+ case Void:
+ case Illegal:
+ return null;
+ default:
+ throw new UnsupportedOperationException("no return register for type " + kind);
+ }
+ }
+
+ @Override
+ public Register getFrameRegister() {
+ return rsp;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.hotspot.sparc;
+
+import static jdk.vm.ci.inittimer.InitTimer.*;
+
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.compiler.*;
+import jdk.vm.ci.hotspot.*;
+import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.service.*;
+import jdk.vm.ci.sparc.*;
+import jdk.vm.ci.sparc.SPARC.CPUFeature;
+
+@ServiceProvider(HotSpotJVMCIBackendFactory.class)
+public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
+
+ protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
+ final int stackFrameAlignment = 16;
+ final int implicitNullCheckLimit = 4096;
+ final boolean inlineObjects = false;
+ Architecture arch = new SPARC(computeFeatures(config));
+ return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+ }
+
+ protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
+ return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
+ }
+
+ protected EnumSet<CPUFeature> computeFeatures(HotSpotVMConfig config) {
+ EnumSet<CPUFeature> features = EnumSet.noneOf(CPUFeature.class);
+ if ((config.sparcFeatures & config.vis1Instructions) != 0) {
+ features.add(CPUFeature.VIS1);
+ }
+ if ((config.sparcFeatures & config.vis2Instructions) != 0) {
+ features.add(CPUFeature.VIS2);
+ }
+ if ((config.sparcFeatures & config.vis3Instructions) != 0) {
+ features.add(CPUFeature.VIS3);
+ }
+ if ((config.sparcFeatures & config.cbcondInstructions) != 0) {
+ features.add(CPUFeature.CBCOND);
+ }
+ if (config.useBlockZeroing) {
+ features.add(CPUFeature.BLOCK_ZEROING);
+ }
+ return features;
+ }
+
+ @Override
+ public String getArchitecture() {
+ return "SPARC";
+ }
+
+ @Override
+ public String toString() {
+ return "JVMCIBackend:" + getArchitecture();
+ }
+
+ @SuppressWarnings("try")
+ public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
+ assert host == null;
+ TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
+
+ HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
+ RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig());
+ HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
+ HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
+ try (InitTimer rt = timer("instantiate backend")) {
+ return createBackend(metaAccess, codeCache, constantReflection);
+ }
+ }
+
+ protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection) {
+ return new JVMCIBackend(metaAccess, codeCache, constantReflection);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+package jdk.vm.ci.hotspot.sparc;
+
+import static jdk.vm.ci.sparc.SPARC.*;
+
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.CallingConvention.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.hotspot.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.sparc.*;
+
+public class SPARCHotSpotRegisterConfig implements RegisterConfig {
+
+ private final Architecture architecture;
+
+ private final Register[] allocatable;
+
+ private final RegisterAttributes[] attributesMap;
+
+ @Override
+ public Register[] getAllocatableRegisters() {
+ return allocatable.clone();
+ }
+
+ public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+ ArrayList<Register> list = new ArrayList<>();
+ for (Register reg : registers) {
+ if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
+ // Special treatment for double precision
+ // TODO: This is wasteful it uses only half of the registers as float.
+ if (kind == JavaKind.Double) {
+ if (reg.getRegisterCategory().equals(FPUd)) {
+ list.add(reg);
+ }
+ } else if (kind == JavaKind.Float) {
+ if (reg.getRegisterCategory().equals(FPUs)) {
+ list.add(reg);
+ }
+ } else {
+ list.add(reg);
+ }
+ }
+ }
+
+ Register[] ret = list.toArray(new Register[list.size()]);
+ return ret;
+ }
+
+ @Override
+ public RegisterAttributes[] getAttributesMap() {
+ return attributesMap.clone();
+ }
+
+ private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
+ private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
+
+ private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
+ private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
+ // @formatter:off
+ private final Register[] callerSaveRegisters =
+ {g1, g2, g3, g4, g5, g6, g7,
+ o0, o1, o2, o3, o4, o5, o7,
+ f0, f1, f2, f3, f4, f5, f6, f7,
+ f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23,
+ f24, f25, f26, f27, f28, f29, f30, f31,
+ d32, d34, d36, d38, d40, d42, d44, d46,
+ d48, d50, d52, d54, d56, d58, d60, d62};
+ // @formatter:on
+
+ /**
+ * Registers saved by the callee. This lists all L and I registers which are saved in the
+ * register window.
+ */
+ private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7};
+
+ private static Register[] initAllocatable(boolean reserveForHeapBase) {
+ Register[] registers = null;
+ if (reserveForHeapBase) {
+ // @formatter:off
+ registers = new Register[]{
+ // TODO this is not complete
+ // o7 cannot be used as register because it is always overwritten on call
+ // and the current register handler would ignore this fact if the called
+ // method still does not modify registers, in fact o7 is modified by the Call instruction
+ // There would be some extra handlin necessary to be able to handle the o7 properly for local usage
+ g1, g4, g5,
+ o0, o1, o2, o3, o4, o5, /*o6,o7,*/
+ l0, l1, l2, l3, l4, l5, l6, l7,
+ i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
+ //f0, f1, f2, f3, f4, f5, f6, f7,
+ f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23,
+ f24, f25, f26, f27, f28, f29, f30, f31,
+ d32, d34, d36, d38, d40, d42, d44, d46,
+ d48, d50, d52, d54, d56, d58, d60, d62
+ };
+ // @formatter:on
+ } else {
+ // @formatter:off
+ registers = new Register[]{
+ // TODO this is not complete
+ g1, g4, g5,
+ o0, o1, o2, o3, o4, o5, /*o6, o7,*/
+ l0, l1, l2, l3, l4, l5, l6, l7,
+ i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
+// f0, f1, f2, f3, f4, f5, f6, f7
+ f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23,
+ f24, f25, f26, f27, f28, f29, f30, f31,
+ d32, d34, d36, d38, d40, d42, d44, d46,
+ d48, d50, d52, d54, d56, d58, d60, d62
+ };
+ // @formatter:on
+ }
+
+ return registers;
+ }
+
+ public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
+ this(target, initAllocatable(config.useCompressedOops));
+ }
+
+ public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
+ this.architecture = target.arch;
+ this.allocatable = allocatable.clone();
+ attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
+ }
+
+ @Override
+ public Register[] getCallerSaveRegisters() {
+ return callerSaveRegisters;
+ }
+
+ public Register[] getCalleeSaveRegisters() {
+ return calleeSaveRegisters;
+ }
+
+ @Override
+ public boolean areAllAllocatableRegistersCallerSaved() {
+ return false;
+ }
+
+ @Override
+ public Register getRegisterForRole(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+ if (type == Type.JavaCall || type == Type.NativeCall) {
+ return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+ }
+ if (type == Type.JavaCallee) {
+ return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+ }
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+ if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) {
+ return fpuParameterRegisters;
+ }
+ assert architecture.canStoreValue(CPU, kind);
+ return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
+ }
+
+ private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
+ AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+ int currentGeneral = 0;
+ int currentFloating = 0;
+ int currentStackOffset = 0;
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+ final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
+
+ switch (kind) {
+ case Byte:
+ case Boolean:
+ case Short:
+ case Char:
+ case Int:
+ case Long:
+ case Object:
+ if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
+ Register register = generalParameterRegisters[currentGeneral++];
+ locations[i] = register.asValue(target.getLIRKind(kind));
+ }
+ break;
+ case Double:
+ if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
+ if (currentFloating % 2 != 0) {
+ // Make register number even to be a double reg
+ currentFloating++;
+ }
+ Register register = fpuDoubleParameterRegisters[currentFloating];
+ currentFloating += 2; // Only every second is a double register
+ locations[i] = register.asValue(target.getLIRKind(kind));
+ }
+ break;
+ case Float:
+ if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
+ Register register = fpuParameterRegisters[currentFloating++];
+ locations[i] = register.asValue(target.getLIRKind(kind));
+ }
+ break;
+ default:
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ if (locations[i] == null) {
+ // Stack slot is always aligned to its size in bytes but minimum wordsize
+ int typeSize = SPARC.spillSlotSize(target, kind);
+ currentStackOffset = roundUp(currentStackOffset, typeSize);
+ int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE;
+ locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out);
+ currentStackOffset += typeSize;
+ }
+ }
+
+ JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
+ AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
+ // Space where callee may spill outgoing parameters o0...o5
+ int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize;
+ return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations);
+ }
+
+ private static int roundUp(int number, int mod) {
+ return ((number + mod - 1) / mod) * mod;
+ }
+
+ @Override
+ public Register getReturnRegister(JavaKind kind) {
+ return getReturnRegister(kind, Type.JavaCallee);
+ }
+
+ private static Register getReturnRegister(JavaKind kind, Type type) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ case Int:
+ case Long:
+ case Object:
+ return type == Type.JavaCallee ? i0 : o0;
+ case Float:
+ return f0;
+ case Double:
+ return d0;
+ case Void:
+ case Illegal:
+ return null;
+ default:
+ throw new UnsupportedOperationException("no return register for type " + kind);
+ }
+ }
+
+ @Override
+ public Register getFrameRegister() {
+ return sp;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.inittimer.InitTimer.timer;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMField;
+import jdk.vm.ci.inittimer.InitTimer;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.SpeculationLog;
+import sun.misc.Unsafe;
+
+/**
+ * Calls from Java into HotSpot. The behavior of all the methods in this class that take a native
+ * pointer as an argument (e.g., {@link #getSymbol(long)}) is undefined if the argument does not
+ * denote a valid native object.
+ */
+public final class CompilerToVM {
+ /**
+ * Initializes the native part of the JVMCI runtime.
+ */
+ private static native void registerNatives();
+
+ static {
+ initialize();
+ }
+
+ @SuppressWarnings("try")
+ private static void initialize() {
+ try (InitTimer t = timer("CompilerToVM.registerNatives")) {
+ registerNatives();
+ }
+ }
+
+ /**
+ * Copies the original bytecode of {@code method} into a new byte array and returns it.
+ *
+ * @return a new byte array containing the original bytecode of {@code method}
+ */
+ native byte[] getBytecode(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Gets the number of entries in {@code method}'s exception handler table or 0 if it has not
+ * exception handler table.
+ */
+ native int getExceptionTableLength(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Gets the address of the first entry in {@code method}'s exception handler table.
+ *
+ * Each entry is a native object described by these fields:
+ *
+ * <ul>
+ * <li>{@link HotSpotVMConfig#exceptionTableElementSize}</li>
+ * <li>{@link HotSpotVMConfig#exceptionTableElementStartPcOffset}</li>
+ * <li>{@link HotSpotVMConfig#exceptionTableElementEndPcOffset}</li>
+ * <li>{@link HotSpotVMConfig#exceptionTableElementHandlerPcOffset}</li>
+ * <li>{@link HotSpotVMConfig#exceptionTableElementCatchTypeIndexOffset}
+ * </ul>
+ *
+ * @return 0 if {@code method} has no exception handlers (i.e.
+ * {@code getExceptionTableLength(method) == 0})
+ */
+ native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Determines if {@code method} can be inlined. A method may not be inlinable for a number of
+ * reasons such as:
+ * <ul>
+ * <li>a CompileOracle directive may prevent inlining or compilation of methods</li>
+ * <li>the method may have a bytecode breakpoint set</li>
+ * <li>the method may have other bytecode features that require special handling by the VM</li>
+ * </ul>
+ */
+ native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Determines if {@code method} should be inlined at any cost. This could be because:
+ * <ul>
+ * <li>a CompileOracle directive may forces inlining of this methods</li>
+ * <li>an annotation forces inlining of this method</li>
+ * </ul>
+ */
+ native boolean shouldInlineMethod(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Used to implement {@link ResolvedJavaType#findUniqueConcreteMethod(ResolvedJavaMethod)}.
+ *
+ * @param method the method on which to base the search
+ * @param actualHolderType the best known type of receiver
+ * @return the method result or 0 is there is no unique concrete method for {@code method}
+ */
+ native HotSpotResolvedJavaMethodImpl findUniqueConcreteMethod(HotSpotResolvedObjectTypeImpl actualHolderType, HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Gets the implementor for the interface class {@code type}.
+ *
+ * @return the implementor if there is a single implementor, 0 if there is no implementor, or
+ * {@code type} itself if there is more than one implementor
+ */
+ native HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type);
+
+ /**
+ * Determines if {@code method} is ignored by security stack walks.
+ */
+ native boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Converts a name to a type.
+ *
+ * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
+ * @param accessingClass the context of resolution (must not be null)
+ * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
+ * either return a {@link ResolvedJavaType} or throw an exception
+ * @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
+ * @throws LinkageError if {@code resolve == true} and the resolution failed
+ */
+ native HotSpotResolvedObjectTypeImpl lookupType(String name, Class<?> accessingClass, boolean resolve);
+
+ /**
+ * Resolves the entry at index {@code cpi} in {@code constantPool} to an object.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote one of the following
+ * entry types: {@code JVM_CONSTANT_MethodHandle}, {@code JVM_CONSTANT_MethodHandleInError},
+ * {@code JVM_CONSTANT_MethodType} and {@code JVM_CONSTANT_MethodTypeInError}.
+ */
+ native Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Resolves the entry at index {@code cpi} in {@code constantPool} to an object, looking in the
+ * constant pool cache first.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote a
+ * {@code JVM_CONSTANT_String} entry.
+ */
+ native Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Gets the {@code JVM_CONSTANT_NameAndType} index from the entry at index {@code cpi} in
+ * {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote an entry containing a
+ * {@code JVM_CONSTANT_NameAndType} index.
+ */
+ native int lookupNameAndTypeRefIndexInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Gets the name of the {@code JVM_CONSTANT_NameAndType} entry referenced by another entry
+ * denoted by {@code which} in {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code which} does not denote a entry that
+ * references a {@code JVM_CONSTANT_NameAndType} entry.
+ */
+ native String lookupNameInPool(HotSpotConstantPool constantPool, int which);
+
+ /**
+ * Gets the signature of the {@code JVM_CONSTANT_NameAndType} entry referenced by another entry
+ * denoted by {@code which} in {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code which} does not denote a entry that
+ * references a {@code JVM_CONSTANT_NameAndType} entry.
+ */
+ native String lookupSignatureInPool(HotSpotConstantPool constantPool, int which);
+
+ /**
+ * Gets the {@code JVM_CONSTANT_Class} index from the entry at index {@code cpi} in
+ * {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote an entry containing a
+ * {@code JVM_CONSTANT_Class} index.
+ */
+ native int lookupKlassRefIndexInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Looks up a class denoted by the {@code JVM_CONSTANT_Class} entry at index {@code cpi} in
+ * {@code constantPool}. This method does not perform any resolution.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote a
+ * {@code JVM_CONSTANT_Class} entry.
+ *
+ * @return the resolved class entry or a String otherwise
+ */
+ native Object lookupKlassInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Looks up a method denoted by the entry at index {@code cpi} in {@code constantPool}. This
+ * method does not perform any resolution.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote an entry representing
+ * a method.
+ *
+ * @param opcode the opcode of the instruction for which the lookup is being performed or
+ * {@code -1}. If non-negative, then resolution checks specific to the bytecode it
+ * denotes are performed if the method is already resolved. Should any of these
+ * checks fail, 0 is returned.
+ * @return the resolved method entry, 0 otherwise
+ */
+ native HotSpotResolvedJavaMethodImpl lookupMethodInPool(HotSpotConstantPool constantPool, int cpi, byte opcode);
+
+ /**
+ * Ensures that the type referenced by the specified {@code JVM_CONSTANT_InvokeDynamic} entry at
+ * index {@code cpi} in {@code constantPool} is loaded and initialized.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote a
+ * {@code JVM_CONSTANT_InvokeDynamic} entry.
+ */
+ native void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Ensures that the type referenced by the entry for a <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">signature
+ * polymorphic</a> method at index {@code cpi} in {@code constantPool} is loaded and
+ * initialized.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote an entry representing
+ * a signature polymorphic method.
+ */
+ native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Gets the resolved type denoted by the entry at index {@code cpi} in {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote an entry representing
+ * a class.
+ *
+ * @throws LinkageError if resolution failed
+ */
+ native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError;
+
+ /**
+ * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry at index {@code cpi} in
+ * {@code constantPool}. The values returned in {@code info} are:
+ *
+ * <pre>
+ * [(int) flags, // only valid if field is resolved
+ * (int) offset] // only valid if field is resolved
+ * </pre>
+ *
+ * The behavior of this method is undefined if {@code cpi} does not denote a
+ * {@code JVM_CONSTANT_Field} entry.
+ *
+ * @param info an array in which the details of the field are returned
+ * @return the type defining the field if resolution is successful, 0 otherwise
+ */
+ native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info);
+
+ /**
+ * Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
+ * directly into {@code constantPool}.
+ *
+ * The behavior of this method is undefined if {@code ccpi} is an invalid constant pool cache
+ * index.
+ */
+ native int constantPoolRemapInstructionOperandFromCache(HotSpotConstantPool constantPool, int cpci);
+
+ /**
+ * Gets the appendix object (if any) associated with the entry at index {@code cpi} in
+ * {@code constantPool}.
+ */
+ native Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
+
+ /**
+ * Installs the result of a compilation into the code cache.
+ *
+ * @param target the target where this code should be installed
+ * @param compiledCode the result of a compilation
+ * @param code the details of the installed CodeBlob are written to this object
+ * @return the outcome of the installation which will be one of
+ * {@link HotSpotVMConfig#codeInstallResultOk},
+ * {@link HotSpotVMConfig#codeInstallResultCacheFull},
+ * {@link HotSpotVMConfig#codeInstallResultCodeTooLarge},
+ * {@link HotSpotVMConfig#codeInstallResultDependenciesFailed} or
+ * {@link HotSpotVMConfig#codeInstallResultDependenciesInvalid}.
+ */
+ public native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
+
+ public native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData);
+
+ /**
+ * Notifies the VM of statistics for a completed compilation.
+ *
+ * @param id the identifier of the compilation
+ * @param method the method compiled
+ * @param osr specifies if the compilation was for on-stack-replacement
+ * @param processedBytecodes the number of bytecodes processed during the compilation, including
+ * the bytecodes of all inlined methods
+ * @param time the amount time spent compiling {@code method}
+ * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
+ * @param installedCode the nmethod installed as a result of the compilation
+ */
+ public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
+ InstalledCode installedCode);
+
+ /**
+ * Resets all compilation statistics.
+ */
+ public native void resetCompilationStatistics();
+
+ /**
+ * Initializes the fields of {@code config}.
+ */
+ native long initializeConfiguration();
+
+ /**
+ * Resolves the implementation of {@code method} for virtual dispatches on objects of dynamic
+ * type {@code exactReceiver}. This resolution process only searches "up" the class hierarchy of
+ * {@code exactReceiver}.
+ *
+ * @param caller the caller or context type used to perform access checks
+ * @return the link-time resolved method (might be abstract) or {@code 0} if it can not be
+ * linked
+ */
+ native HotSpotResolvedJavaMethodImpl resolveMethod(HotSpotResolvedObjectTypeImpl exactReceiver, HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl caller);
+
+ /**
+ * Gets the static initializer of {@code type}.
+ *
+ * @return 0 if {@code type} has no static initializer
+ */
+ native HotSpotResolvedJavaMethodImpl getClassInitializer(HotSpotResolvedObjectTypeImpl type);
+
+ /**
+ * Determines if {@code type} or any of its currently loaded subclasses overrides
+ * {@code Object.finalize()}.
+ */
+ native boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type);
+
+ /**
+ * Gets the method corresponding to {@code holder} and slot number {@code slot} (i.e.
+ * {@link Method#slot} or {@link Constructor#slot}).
+ */
+ native HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(Class<?> holder, int slot);
+
+ /**
+ * Gets the maximum absolute offset of a PC relative call to {@code address} from any position
+ * in the code cache.
+ *
+ * @param address an address that may be called from any code in the code cache
+ * @return -1 if {@code address == 0}
+ */
+ public native long getMaxCallTargetOffset(long address);
+
+ /**
+ * Gets a textual disassembly of {@code codeBlob}.
+ *
+ * @return a non-zero length string containing a disassembly of {@code codeBlob} or null if
+ * {@code codeBlob} could not be disassembled for some reason
+ */
+ // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage
+ public synchronized native String disassembleCodeBlob(long codeBlob);
+
+ /**
+ * Gets a stack trace element for {@code method} at bytecode index {@code bci}.
+ */
+ native StackTraceElement getStackTraceElement(HotSpotResolvedJavaMethodImpl method, int bci);
+
+ /**
+ * Executes some {@code installedCode} with arguments {@code args}.
+ *
+ * @return the result of executing {@code installedCode}
+ * @throws InvalidInstalledCodeException if {@code installedCode} has been invalidated
+ */
+ native Object executeInstalledCode(Object[] args, InstalledCode installedCode) throws InvalidInstalledCodeException;
+
+ /**
+ * Gets the line number table for {@code method}. The line number table is encoded as (bci,
+ * source line number) pairs.
+ *
+ * @return the line number table for {@code method} or null if it doesn't have one
+ */
+ native long[] getLineNumberTable(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Gets the number of entries in the local variable table for {@code method}.
+ *
+ * @return the number of entries in the local variable table for {@code method}
+ */
+ native int getLocalVariableTableLength(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Gets the address of the first entry in the local variable table for {@code method}.
+ *
+ * Each entry is a native object described by these fields:
+ *
+ * <ul>
+ * <li>{@link HotSpotVMConfig#localVariableTableElementSize}</li>
+ * <li>{@link HotSpotVMConfig#localVariableTableElementLengthOffset}</li>
+ * <li>{@link HotSpotVMConfig#localVariableTableElementNameCpIndexOffset}</li>
+ * <li>{@link HotSpotVMConfig#localVariableTableElementDescriptorCpIndexOffset}</li>
+ * <li>{@link HotSpotVMConfig#localVariableTableElementSignatureCpIndexOffset}
+ * <li>{@link HotSpotVMConfig#localVariableTableElementSlotOffset}
+ * <li>{@link HotSpotVMConfig#localVariableTableElementStartBciOffset}
+ * </ul>
+ *
+ * @return 0 if {@code method} does not have a local variable table
+ */
+ native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Reads an object pointer within a VM data structure. That is, any {@link HotSpotVMField} whose
+ * {@link HotSpotVMField#type() type} is {@code "oop"} (e.g.,
+ * {@code ArrayKlass::_component_mirror}, {@code Klass::_java_mirror},
+ * {@code JavaThread::_threadObj}).
+ *
+ * Note that {@link Unsafe#getObject(Object, long)} cannot be used for this since it does a
+ * {@code narrowOop} read if the VM is using compressed oops whereas oops within VM data
+ * structures are (currently) always uncompressed.
+ *
+ * @param address address of an oop field within a VM data structure
+ */
+ native Object readUncompressedOop(long address);
+
+ /**
+ * Determines if {@code method} should not be inlined or compiled.
+ */
+ native void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Invalidates the profiling information for {@code method} and (re)initializes it such that
+ * profiling restarts upon its next invocation.
+ */
+ native void reprofile(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
+ * raised the next time {@code installedCode} is executed.
+ */
+ public native void invalidateInstalledCode(InstalledCode installedCode);
+
+ /**
+ * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
+ */
+ public native long[] collectCounters();
+
+ /**
+ * Determines if {@code metaspaceMethodData} is mature.
+ */
+ native boolean isMature(long metaspaceMethodData);
+
+ /**
+ * Generate a unique id to identify the result of the compile.
+ */
+ native int allocateCompileId(HotSpotResolvedJavaMethodImpl method, int entryBCI);
+
+ /**
+ * Determines if {@code method} has OSR compiled code identified by {@code entryBCI} for
+ * compilation level {@code level}.
+ */
+ native boolean hasCompiledCodeForOSR(HotSpotResolvedJavaMethodImpl method, int entryBCI, int level);
+
+ /**
+ * Gets the value of {@code metaspaceSymbol} as a String.
+ */
+ native String getSymbol(long metaspaceSymbol);
+
+ /**
+ * Looks for the next Java stack frame matching an entry in {@code methods}.
+ *
+ * @param frame the starting point of the search, where {@code null} refers to the topmost frame
+ * @param methods the methods to look for, where {@code null} means that any frame is returned
+ * @return the frame, or {@code null} if the end of the stack was reached during the search
+ */
+ public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethodImpl[] methods, int initialSkip);
+
+ /**
+ * Materializes all virtual objects within {@code stackFrame} updates its locals.
+ *
+ * @param invalidate if {@code true}, the compiled method for the stack frame will be
+ * invalidated.
+ */
+ native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+
+ /**
+ * Gets the v-table index for interface method {@code method} in the receiver {@code type} or
+ * {@link HotSpotVMConfig#invalidVtableIndex} if {@code method} is not in {@code type}'s
+ * v-table.
+ *
+ * @throws InternalError if {@code type} is an interface or {@code method} is not held by an
+ * interface or class represented by {@code type} is not initialized
+ */
+ native int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type, HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Determines if debug info should also be emitted at non-safepoint locations.
+ */
+ public native boolean shouldDebugNonSafepoints();
+
+ /**
+ * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to the
+ * HotSpot's log stream.
+ *
+ * @exception NullPointerException if <code>bytes</code> is <code>null</code>.
+ * @exception IndexOutOfBoundsException if copying would cause access of data outside array
+ * bounds.
+ */
+ public native void writeDebugOutput(byte[] bytes, int offset, int length);
+
+ /**
+ * Flush HotSpot's log stream.
+ */
+ public native void flushDebugOutput();
+
+ /**
+ * Read a value representing a metaspace Method* and return the
+ * {@link HotSpotResolvedJavaMethodImpl} wrapping it. This method does no checking that the
+ * location actually contains a valid Method*. If the {@code base} object is a
+ * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
+ * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
+ * and used as the base. Otherwise the object itself is used as the base.
+ *
+ * @param base an object to read from or null
+ * @param displacement
+ * @return null or the resolved method for this location
+ */
+ native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
+
+ /**
+ * Read a value representing a metaspace ConstantPool* and return the
+ * {@link HotSpotConstantPool} wrapping it. This method does no checking that the location
+ * actually contains a valid ConstantPool*. If the {@code base} object is a
+ * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
+ * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
+ * and used as the base. Otherwise the object itself is used as the base.
+ *
+ * @param base an object to read from or null
+ * @param displacement
+ * @return null or the resolved method for this location
+ */
+ native HotSpotConstantPool getConstantPool(Object base, long displacement);
+
+ /**
+ * Read a value representing a metaspace Klass* and return the
+ * {@link HotSpotResolvedObjectTypeImpl} wrapping it. The method does no checking that the
+ * location actually contains a valid Klass*. If the {@code base} object is a
+ * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
+ * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
+ * and used as the base. Otherwise the object itself is used as the base.
+ *
+ * @param base an object to read from or null
+ * @param displacement
+ * @param compressed true if the location contains a compressed Klass*
+ * @return null or the resolved method for this location
+ */
+ native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.*;
+
+import java.lang.reflect.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.CompilationResult.*;
+import jdk.vm.ci.code.DataSection.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * HotSpot implementation of {@link CodeCacheProvider}.
+ */
+public class HotSpotCodeCacheProvider implements CodeCacheProvider {
+
+ protected final HotSpotJVMCIRuntimeProvider runtime;
+ public final HotSpotVMConfig config;
+ protected final TargetDescription target;
+ protected final RegisterConfig regConfig;
+
+ public HotSpotCodeCacheProvider(HotSpotJVMCIRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) {
+ this.runtime = runtime;
+ this.config = config;
+ this.target = target;
+ this.regConfig = regConfig;
+ }
+
+ @Override
+ public String getMarkName(Mark mark) {
+ int markId = (int) mark.id;
+ Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
+ for (Field f : fields) {
+ if (f.getName().startsWith("MARKID_")) {
+ f.setAccessible(true);
+ try {
+ if (f.getInt(runtime.getConfig()) == markId) {
+ return f.getName();
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+ return CodeCacheProvider.super.getMarkName(mark);
+ }
+
+ /**
+ * Decodes a call target to a mnemonic if possible.
+ */
+ @Override
+ public String getTargetName(Call call) {
+ Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
+ for (Field f : fields) {
+ if (f.getName().endsWith("Stub")) {
+ f.setAccessible(true);
+ try {
+ Object address = f.get(runtime.getConfig());
+ if (address.equals(call.target)) {
+ return f.getName() + ":0x" + Long.toHexString((Long) address);
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+ return CodeCacheProvider.super.getTargetName(call);
+ }
+
+ @Override
+ public RegisterConfig getRegisterConfig() {
+ return regConfig;
+ }
+
+ @Override
+ public int getMinimumOutgoingSize() {
+ return runtime.getConfig().runtimeCallStackSize;
+ }
+
+ public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
+ HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult);
+ return installedCode;
+ }
+
+ private InstalledCode installCode(CompilationResult compResult, HotSpotCompiledNmethod compiledCode, InstalledCode installedCode, SpeculationLog log) {
+ int result = runtime.getCompilerToVM().installCode(target, compiledCode, installedCode, log);
+ if (result != config.codeInstallResultOk) {
+ String msg = compiledCode.getInstallationFailureMessage();
+ String resultDesc = config.getCodeInstallResultDescription(result);
+ if (msg != null) {
+ msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
+ } else {
+ msg = String.format("Code installation failed: %s", resultDesc);
+ }
+ if (result == config.codeInstallResultDependenciesInvalid) {
+ throw new AssertionError(resultDesc + " " + msg);
+ }
+ throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
+ }
+ return logOrDump(installedCode, compResult);
+ }
+
+ public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) {
+ if (compResult.getId() == -1) {
+ compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
+ }
+ HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
+ HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(method, compResult, jvmciEnv);
+ return installCode(compResult, compiledCode, installedCode, method.getSpeculationLog());
+ }
+
+ @Override
+ public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
+ HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
+ if (compResult.getId() == -1) {
+ compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
+ }
+ InstalledCode installedCode = predefinedInstalledCode;
+ if (installedCode == null) {
+ HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
+ installedCode = code;
+ }
+ HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
+ return installCode(compResult, compiledCode, installedCode, log);
+ }
+
+ @Override
+ public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+ HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
+ return installMethod(hotspotMethod, compResult, 0L, true);
+ }
+
+ public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+ HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
+ if (compResult.getId() == -1) {
+ compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
+ }
+ HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
+ HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult);
+ CompilerToVM vm = runtime.getCompilerToVM();
+ int result = vm.installCode(target, compiled, code, null);
+ if (result != runtime.getConfig().codeInstallResultOk) {
+ return null;
+ }
+ return code;
+ }
+
+ public boolean needsDataPatch(JavaConstant constant) {
+ return constant instanceof HotSpotMetaspaceConstant;
+ }
+
+ private Data createSingleDataItem(Constant constant) {
+ int size;
+ DataBuilder builder;
+ if (constant instanceof VMConstant) {
+ VMConstant vmConstant = (VMConstant) constant;
+ boolean compressed;
+ long raw;
+ if (constant instanceof HotSpotObjectConstant) {
+ HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant;
+ compressed = c.isCompressed();
+ raw = 0xDEADDEADDEADDEADL;
+ } else if (constant instanceof HotSpotMetaspaceConstant) {
+ HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant;
+ compressed = meta.isCompressed();
+ raw = meta.rawValue();
+ } else {
+ throw new JVMCIError(String.valueOf(constant));
+ }
+
+ size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
+ if (size == 4) {
+ builder = (buffer, patch) -> {
+ patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
+ buffer.putInt((int) raw);
+ };
+ } else {
+ assert size == 8;
+ builder = (buffer, patch) -> {
+ patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
+ buffer.putLong(raw);
+ };
+ }
+ } else if (JavaConstant.isNull(constant)) {
+ boolean compressed = COMPRESSED_NULL.equals(constant);
+ size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
+ builder = DataBuilder.zero(size);
+ } else if (constant instanceof SerializableConstant) {
+ SerializableConstant s = (SerializableConstant) constant;
+ size = s.getSerializedSize();
+ builder = DataBuilder.serializable(s);
+ } else {
+ throw new JVMCIError(String.valueOf(constant));
+ }
+
+ return new Data(size, size, builder);
+ }
+
+ public Data createDataItem(Constant... constants) {
+ assert constants.length > 0;
+ if (constants.length == 1) {
+ return createSingleDataItem(constants[0]);
+ } else {
+ DataBuilder[] builders = new DataBuilder[constants.length];
+ int size = 0;
+ int alignment = 1;
+ for (int i = 0; i < constants.length; i++) {
+ Data data = createSingleDataItem(constants[i]);
+
+ assert size % data.getAlignment() == 0 : "invalid alignment in packed constants";
+ alignment = DataSection.lcm(alignment, data.getAlignment());
+
+ builders[i] = data.getBuilder();
+ size += data.getSize();
+ }
+ DataBuilder ret = (buffer, patches) -> {
+ for (DataBuilder b : builders) {
+ b.emit(buffer, patches);
+ }
+ };
+ return new Data(alignment, size, ret);
+ }
+ }
+
+ @Override
+ public TargetDescription getTarget() {
+ return target;
+ }
+
+ public String disassemble(InstalledCode code) {
+ if (code.isValid()) {
+ long codeBlob = code.getAddress();
+ return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
+ }
+ return null;
+ }
+
+ public SpeculationLog createSpeculationLog() {
+ return new HotSpotSpeculationLog();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.nio.*;
+import java.util.*;
+import java.util.stream.*;
+import java.util.stream.Stream.Builder;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.CompilationResult.CodeAnnotation;
+import jdk.vm.ci.code.CompilationResult.CodeComment;
+import jdk.vm.ci.code.CompilationResult.DataPatch;
+import jdk.vm.ci.code.CompilationResult.ExceptionHandler;
+import jdk.vm.ci.code.CompilationResult.Infopoint;
+import jdk.vm.ci.code.CompilationResult.JumpTable;
+import jdk.vm.ci.code.CompilationResult.Mark;
+import jdk.vm.ci.code.CompilationResult.Site;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.Assumption;
+
+/**
+ * A {@link CompilationResult} with additional HotSpot-specific information required for installing
+ * the code in HotSpot's code cache.
+ */
+public abstract class HotSpotCompiledCode {
+
+ public final String name;
+ public final Site[] sites;
+ public final ExceptionHandler[] exceptionHandlers;
+ public final Comment[] comments;
+ public final Assumption[] assumptions;
+
+ public final byte[] targetCode;
+ public final int targetCodeSize;
+
+ public final byte[] dataSection;
+ public final int dataSectionAlignment;
+ public final DataPatch[] dataSectionPatches;
+ public final boolean isImmutablePIC;
+
+ public final int totalFrameSize;
+ public final int customStackAreaOffset;
+
+ /**
+ * The list of the methods whose bytecodes were used as input to the compilation. If
+ * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
+ * element of this array is the root method of the compilation.
+ */
+ public final ResolvedJavaMethod[] methods;
+
+ public static class Comment {
+
+ public final String text;
+ public final int pcOffset;
+
+ public Comment(int pcOffset, String text) {
+ this.text = text;
+ this.pcOffset = pcOffset;
+ }
+ }
+
+ public HotSpotCompiledCode(CompilationResult compResult) {
+ name = compResult.getName();
+ sites = getSortedSites(compResult);
+ if (compResult.getExceptionHandlers().isEmpty()) {
+ exceptionHandlers = null;
+ } else {
+ exceptionHandlers = compResult.getExceptionHandlers().toArray(new ExceptionHandler[compResult.getExceptionHandlers().size()]);
+ }
+ List<CodeAnnotation> annotations = compResult.getAnnotations();
+ comments = new Comment[annotations.size()];
+ if (!annotations.isEmpty()) {
+ for (int i = 0; i < comments.length; i++) {
+ CodeAnnotation annotation = annotations.get(i);
+ String text;
+ if (annotation instanceof CodeComment) {
+ CodeComment codeComment = (CodeComment) annotation;
+ text = codeComment.value;
+ } else if (annotation instanceof JumpTable) {
+ JumpTable jumpTable = (JumpTable) annotation;
+ text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]";
+ } else {
+ text = annotation.toString();
+ }
+ comments[i] = new Comment(annotation.position, text);
+ }
+ }
+ assumptions = compResult.getAssumptions();
+ assert validateFrames();
+
+ targetCode = compResult.getTargetCode();
+ targetCodeSize = compResult.getTargetCodeSize();
+
+ DataSection data = compResult.getDataSection();
+ if (!data.isFinalized()) {
+ data.finalizeLayout();
+ }
+ dataSection = new byte[data.getSectionSize()];
+
+ ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
+ Builder<DataPatch> patchBuilder = Stream.builder();
+ data.buildDataSection(buffer, patchBuilder);
+
+ dataSectionAlignment = data.getSectionAlignment();
+ dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]);
+
+ isImmutablePIC = compResult.isImmutablePIC();
+
+ totalFrameSize = compResult.getTotalFrameSize();
+ customStackAreaOffset = compResult.getCustomStackAreaOffset();
+
+ methods = compResult.getMethods();
+ }
+
+ /**
+ * Ensure that all the frames passed into HotSpot are properly formatted with an empty or
+ * illegal slot following double word slots.
+ */
+ private boolean validateFrames() {
+ for (Site site : sites) {
+ if (site instanceof Infopoint) {
+ Infopoint info = (Infopoint) site;
+ if (info.debugInfo != null) {
+ BytecodeFrame frame = info.debugInfo.frame();
+ assert frame == null || frame.validateFormat();
+ }
+ }
+ }
+ return true;
+ }
+
+ static class SiteComparator implements Comparator<Site> {
+
+ public int compare(Site s1, Site s2) {
+ if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+ return s1 instanceof Mark ? -1 : 1;
+ }
+ return s1.pcOffset - s2.pcOffset;
+ }
+ }
+
+ private static Site[] getSortedSites(CompilationResult target) {
+ List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataPatches(), target.getMarks()};
+ int count = 0;
+ for (List<?> list : lists) {
+ count += list.size();
+ }
+ Site[] result = new Site[count];
+ int pos = 0;
+ for (List<?> list : lists) {
+ for (Object elem : list) {
+ result[pos++] = (Site) elem;
+ }
+ }
+ Arrays.sort(result, new SiteComparator());
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.inittimer.*;
+
+/**
+ * {@link HotSpotCompiledCode} destined for installation as an nmethod.
+ */
+public final class HotSpotCompiledNmethod extends HotSpotCompiledCode {
+
+ public final HotSpotResolvedJavaMethod method;
+ public final int entryBCI;
+ public final int id;
+ public final long jvmciEnv;
+ public final boolean hasUnsafeAccess;
+
+ /**
+ * May be set by VM if code installation fails. It will describe in more detail why installation
+ * failed (e.g., exactly which dependency failed).
+ */
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "set by the VM") private String installationFailureMessage;
+
+ public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
+ this(method, compResult, 0L);
+ }
+
+ public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv) {
+ super(compResult);
+ this.method = method;
+ this.entryBCI = compResult.getEntryBCI();
+ this.id = compResult.getId();
+ this.jvmciEnv = jvmciEnv;
+ this.hasUnsafeAccess = compResult.hasUnsafeAccess();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + id + ":" + method.format("%H.%n(%p)%r@") + entryBCI + "]";
+ }
+
+ public String getInstallationFailureMessage() {
+ return installationFailureMessage;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * The compressed representation of the {@link JavaConstant#NULL_POINTER null constant}.
+ */
+public final class HotSpotCompressedNullConstant implements JavaConstant, HotSpotConstant {
+
+ public static final JavaConstant COMPRESSED_NULL = new HotSpotCompressedNullConstant();
+
+ private HotSpotCompressedNullConstant() {
+ }
+
+ public JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ @Override
+ public boolean isNull() {
+ return true;
+ }
+
+ @Override
+ public boolean isCompressed() {
+ return true;
+ }
+
+ @Override
+ public boolean isDefaultForKind() {
+ return true;
+ }
+
+ @Override
+ public Object asBoxedPrimitive() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int asInt() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public boolean asBoolean() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public long asLong() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public float asFloat() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public double asDouble() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public String toString() {
+ return JavaConstant.toString(this);
+ }
+
+ @Override
+ public String toValueString() {
+ return "null";
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof HotSpotCompressedNullConstant;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Marker interface for hotspot specific constants.
+ */
+public interface HotSpotConstant extends Constant {
+
+ boolean isCompressed();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.invoke.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Implementation of {@link ConstantPool} for HotSpot.
+ */
+public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject {
+
+ /**
+ * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
+ */
+ public static class Bytecodes {
+ public static final int LDC = 18; // 0x12
+ public static final int LDC_W = 19; // 0x13
+ public static final int LDC2_W = 20; // 0x14
+ public static final int GETSTATIC = 178; // 0xB2
+ public static final int PUTSTATIC = 179; // 0xB3
+ public static final int GETFIELD = 180; // 0xB4
+ public static final int PUTFIELD = 181; // 0xB5
+ public static final int INVOKEVIRTUAL = 182; // 0xB6
+ public static final int INVOKESPECIAL = 183; // 0xB7
+ public static final int INVOKESTATIC = 184; // 0xB8
+ public static final int INVOKEINTERFACE = 185; // 0xB9
+ public static final int INVOKEDYNAMIC = 186; // 0xBA
+ public static final int NEW = 187; // 0xBB
+ public static final int NEWARRAY = 188; // 0xBC
+ public static final int ANEWARRAY = 189; // 0xBD
+ public static final int CHECKCAST = 192; // 0xC0
+ public static final int INSTANCEOF = 193; // 0xC1
+ public static final int MULTIANEWARRAY = 197; // 0xC5
+
+ static boolean isInvoke(int opcode) {
+ switch (opcode) {
+ case INVOKEVIRTUAL:
+ case INVOKESPECIAL:
+ case INVOKESTATIC:
+ case INVOKEINTERFACE:
+ case INVOKEDYNAMIC:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * See: {@code Rewriter::maybe_rewrite_invokehandle}.
+ */
+ static boolean isInvokeHandleAlias(int opcode) {
+ switch (opcode) {
+ case INVOKEVIRTUAL:
+ case INVOKESPECIAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and
+ * internal ones.
+ */
+ private enum JVM_CONSTANT {
+ // @formatter:off
+ Utf8(config().jvmConstantUtf8),
+ Integer(config().jvmConstantInteger),
+ Long(config().jvmConstantLong),
+ Float(config().jvmConstantFloat),
+ Double(config().jvmConstantDouble),
+ Class(config().jvmConstantClass),
+ UnresolvedClass(config().jvmConstantUnresolvedClass),
+ UnresolvedClassInError(config().jvmConstantUnresolvedClassInError),
+ String(config().jvmConstantString),
+ Fieldref(config().jvmConstantFieldref),
+ MethodRef(config().jvmConstantMethodref),
+ InterfaceMethodref(config().jvmConstantInterfaceMethodref),
+ NameAndType(config().jvmConstantNameAndType),
+ MethodHandle(config().jvmConstantMethodHandle),
+ MethodHandleInError(config().jvmConstantMethodHandleInError),
+ MethodType(config().jvmConstantMethodType),
+ MethodTypeInError(config().jvmConstantMethodTypeInError),
+ InvokeDynamic(config().jvmConstantInvokeDynamic);
+ // @formatter:on
+
+ private final int tag;
+
+ private static final int ExternalMax = config().jvmConstantExternalMax;
+ private static final int InternalMin = config().jvmConstantInternalMin;
+ private static final int InternalMax = config().jvmConstantInternalMax;
+
+ private JVM_CONSTANT(int tag) {
+ this.tag = tag;
+ }
+
+ private static HotSpotVMConfig config() {
+ return runtime().getConfig();
+ }
+
+ /**
+ * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy
+ * initialization.
+ */
+ static class TagValueMap {
+ private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1];
+
+ static {
+ assert InternalMin > ExternalMax;
+ for (JVM_CONSTANT e : values()) {
+ table[indexOf(e.tag)] = e;
+ }
+ }
+
+ private static int indexOf(int tag) {
+ if (tag >= InternalMin) {
+ return tag - InternalMin + ExternalMax + 1;
+ } else {
+ assert tag <= ExternalMax;
+ }
+ return tag;
+ }
+
+ static JVM_CONSTANT get(int tag) {
+ JVM_CONSTANT res = table[indexOf(tag)];
+ if (res != null) {
+ return res;
+ }
+ throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag);
+ }
+ }
+
+ public static JVM_CONSTANT getEnum(int tag) {
+ return TagValueMap.get(tag);
+ }
+ }
+
+ private static class LookupTypeCacheElement {
+ int lastCpi = Integer.MIN_VALUE;
+ JavaType javaType;
+
+ public LookupTypeCacheElement(int lastCpi, JavaType javaType) {
+ super();
+ this.lastCpi = lastCpi;
+ this.javaType = javaType;
+ }
+ }
+
+ /**
+ * Reference to the C++ ConstantPool object.
+ */
+ private final long metaspaceConstantPool;
+ private volatile LookupTypeCacheElement lastLookupType;
+
+ /**
+ * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that
+ * the ConstantPool is kept alive for the duration of this call and the
+ * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+ *
+ * Called from the VM.
+ *
+ * @param metaspaceConstantPool a metaspace ConstantPool object
+ * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool}
+ */
+ @SuppressWarnings("unused")
+ private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
+ return new HotSpotConstantPool(metaspaceConstantPool);
+ }
+
+ private HotSpotConstantPool(long metaspaceConstantPool) {
+ this.metaspaceConstantPool = metaspaceConstantPool;
+ }
+
+ /**
+ * Gets the holder for this constant pool as {@link HotSpotResolvedObjectTypeImpl}.
+ *
+ * @return holder for this constant pool
+ */
+ private HotSpotResolvedObjectType getHolder() {
+ return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().constantPoolHolderOffset, false);
+ }
+
+ /**
+ * Converts a raw index from the bytecodes to a constant pool index by adding a
+ * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}.
+ *
+ * @param rawIndex index from the bytecode
+ * @param opcode bytecode to convert the index for
+ * @return constant pool index
+ */
+ private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
+ int index;
+ if (opcode == Bytecodes.INVOKEDYNAMIC) {
+ index = rawIndex;
+ // See: ConstantPool::is_invokedynamic_index
+ assert index < 0 : "not an invokedynamic constant pool index " + index;
+ } else {
+ assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE ||
+ opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode;
+ index = rawIndex + runtime().getConfig().constantPoolCpCacheIndexTag;
+ }
+ return index;
+ }
+
+ /**
+ * Decode a constant pool cache index to a constant pool index.
+ *
+ * See {@code ConstantPool::decode_cpcache_index}.
+ *
+ * @param index constant pool cache index
+ * @return decoded index
+ */
+ private static int decodeConstantPoolCacheIndex(int index) {
+ if (isInvokedynamicIndex(index)) {
+ return decodeInvokedynamicIndex(index);
+ } else {
+ return index - runtime().getConfig().constantPoolCpCacheIndexTag;
+ }
+ }
+
+ /**
+ * See {@code ConstantPool::is_invokedynamic_index}.
+ */
+ private static boolean isInvokedynamicIndex(int index) {
+ return index < 0;
+ }
+
+ /**
+ * See {@code ConstantPool::decode_invokedynamic_index}.
+ */
+ private static int decodeInvokedynamicIndex(int i) {
+ assert isInvokedynamicIndex(i) : i;
+ return ~i;
+ }
+
+ public long getMetaspaceConstantPool() {
+ return metaspaceConstantPool;
+ }
+
+ public long getMetaspacePointer() {
+ return getMetaspaceConstantPool();
+ }
+
+ /**
+ * Gets the constant pool tag at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return constant pool tag
+ */
+ private JVM_CONSTANT getTagAt(int index) {
+ assertBounds(index);
+ HotSpotVMConfig config = runtime().getConfig();
+ final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset);
+ final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index);
+ if (tag == 0) {
+ return null;
+ }
+ return JVM_CONSTANT.getEnum(tag);
+ }
+
+ /**
+ * Gets the constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return constant pool entry
+ */
+ private long getEntryAt(int index) {
+ assertBounds(index);
+ return UNSAFE.getAddress(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the integer constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return integer constant pool entry at index
+ */
+ private int getIntAt(int index) {
+ assertTag(index, JVM_CONSTANT.Integer);
+ return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the long constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return long constant pool entry
+ */
+ private long getLongAt(int index) {
+ assertTag(index, JVM_CONSTANT.Long);
+ return UNSAFE.getLong(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the float constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return float constant pool entry
+ */
+ private float getFloatAt(int index) {
+ assertTag(index, JVM_CONSTANT.Float);
+ return UNSAFE.getFloat(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the double constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return float constant pool entry
+ */
+ private double getDoubleAt(int index) {
+ assertTag(index, JVM_CONSTANT.Double);
+ return UNSAFE.getDouble(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return {@code JVM_CONSTANT_NameAndType} constant pool entry
+ */
+ private int getNameAndTypeAt(int index) {
+ assertTag(index, JVM_CONSTANT.NameAndType);
+ return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ }
+
+ /**
+ * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index
+ * {@code index}.
+ *
+ * @param index constant pool index
+ * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry
+ */
+ private int getNameAndTypeRefIndexAt(int index) {
+ return runtime().getCompilerToVM().lookupNameAndTypeRefIndexInPool(this, index);
+ }
+
+ /**
+ * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by another
+ * entry denoted by {@code which}.
+ *
+ * @param which constant pool index or constant pool cache index
+ * @return name as {@link String}
+ */
+ private String getNameOf(int which) {
+ return runtime().getCompilerToVM().lookupNameInPool(this, which);
+ }
+
+ /**
+ * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at
+ * index {@code index}.
+ *
+ * @param index constant pool index
+ * @return name reference index
+ */
+ private int getNameRefIndexAt(int index) {
+ final int refIndex = getNameAndTypeAt(index);
+ // name ref index is in the low 16-bits.
+ return refIndex & 0xFFFF;
+ }
+
+ /**
+ * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by
+ * another entry denoted by {@code which}.
+ *
+ * @param which constant pool index or constant pool cache index
+ * @return signature as {@link String}
+ */
+ private String getSignatureOf(int which) {
+ return runtime().getCompilerToVM().lookupSignatureInPool(this, which);
+ }
+
+ /**
+ * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry
+ * at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return signature reference index
+ */
+ private int getSignatureRefIndexAt(int index) {
+ final int refIndex = getNameAndTypeAt(index);
+ // signature ref index is in the high 16-bits.
+ return refIndex >>> 16;
+ }
+
+ /**
+ * Gets the klass reference index constant pool entry at index {@code index}.
+ *
+ * @param index constant pool index
+ * @return klass reference index
+ */
+ private int getKlassRefIndexAt(int index) {
+ return runtime().getCompilerToVM().lookupKlassRefIndexInPool(this, index);
+ }
+
+ /**
+ * Gets the uncached klass reference index constant pool entry at index {@code index}. See:
+ * {@code ConstantPool::uncached_klass_ref_index_at}.
+ *
+ * @param index constant pool index
+ * @return klass reference index
+ */
+ private int getUncachedKlassRefIndexAt(int index, JVM_CONSTANT tag) {
+ int resultIndex;
+ if (tag == JVM_CONSTANT.MethodRef || tag == JVM_CONSTANT.Fieldref || tag == JVM_CONSTANT.InterfaceMethodref) {
+ assertTagIsFieldOrMethod(index);
+ final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+ // klass ref index is in the low 16-bits.
+ resultIndex = refIndex & 0xFFFF;
+ } else {
+ resultIndex = index;
+ }
+
+ // Read the tag only once because it could change between multiple reads.
+ final JVM_CONSTANT klassTag = getTagAt(resultIndex);
+ assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
+
+ return resultIndex;
+ }
+
+ /**
+ * Asserts that the constant pool index {@code index} is in the bounds of the constant pool.
+ *
+ * @param index constant pool index
+ */
+ private void assertBounds(int index) {
+ assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length();
+ }
+
+ /**
+ * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}.
+ *
+ * @param index constant pool index
+ * @param tag expected tag
+ */
+ private void assertTag(int index, JVM_CONSTANT tag) {
+ final JVM_CONSTANT tagAt = getTagAt(index);
+ assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
+ }
+
+ /**
+ * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
+ * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
+ *
+ * @param index constant pool index
+ */
+ private void assertTagIsFieldOrMethod(int index) {
+ final JVM_CONSTANT tagAt = getTagAt(index);
+ assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
+ }
+
+ @Override
+ public int length() {
+ return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolLengthOffset);
+ }
+
+ @Override
+ public Object lookupConstant(int cpi) {
+ assert cpi != 0;
+ final JVM_CONSTANT tag = getTagAt(cpi);
+ switch (tag) {
+ case Integer:
+ return JavaConstant.forInt(getIntAt(cpi));
+ case Long:
+ return JavaConstant.forLong(getLongAt(cpi));
+ case Float:
+ return JavaConstant.forFloat(getFloatAt(cpi));
+ case Double:
+ return JavaConstant.forDouble(getDoubleAt(cpi));
+ case Class:
+ case UnresolvedClass:
+ case UnresolvedClassInError:
+ final int opcode = -1; // opcode is not used
+ return lookupType(cpi, opcode);
+ case String:
+ /*
+ * Normally, we would expect a String here, but anonymous classes can have
+ * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
+ * entries do not have a symbol in the constant pool slot.
+ */
+ Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
+ return HotSpotObjectConstantImpl.forObject(string);
+ case MethodHandle:
+ case MethodHandleInError:
+ case MethodType:
+ case MethodTypeInError:
+ Object obj = runtime().getCompilerToVM().resolveConstantInPool(this, cpi);
+ return HotSpotObjectConstantImpl.forObject(obj);
+ default:
+ throw new JVMCIError("Unknown constant pool tag %s", tag);
+ }
+ }
+
+ @Override
+ public String lookupUtf8(int cpi) {
+ assertTag(cpi, JVM_CONSTANT.Utf8);
+ return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi));
+ }
+
+ @Override
+ public Signature lookupSignature(int cpi) {
+ return new HotSpotSignature(runtime(), lookupUtf8(cpi));
+ }
+
+ @Override
+ public JavaConstant lookupAppendix(int cpi, int opcode) {
+ assert Bytecodes.isInvoke(opcode);
+ final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+ Object appendix = runtime().getCompilerToVM().lookupAppendixInPool(this, index);
+ if (appendix == null) {
+ return null;
+ } else {
+ return HotSpotObjectConstantImpl.forObject(appendix);
+ }
+ }
+
+ /**
+ * Gets a {@link JavaType} corresponding a given resolved or unresolved type.
+ *
+ * @param type either a ResolvedJavaType or a String naming a unresolved type.
+ */
+ private static JavaType getJavaType(final Object type) {
+ if (type instanceof String) {
+ String name = (String) type;
+ return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";");
+ } else {
+ return (JavaType) type;
+ }
+ }
+
+ @Override
+ public JavaMethod lookupMethod(int cpi, int opcode) {
+ final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+ final HotSpotResolvedJavaMethod method = runtime().getCompilerToVM().lookupMethodInPool(this, index, (byte) opcode);
+ if (method != null) {
+ return method;
+ } else {
+ // Get the method's name and signature.
+ String name = getNameOf(index);
+ HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index));
+ if (opcode == Bytecodes.INVOKEDYNAMIC) {
+ HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class);
+ return new HotSpotMethodUnresolved(name, signature, holder);
+ } else {
+ final int klassIndex = getKlassRefIndexAt(index);
+ final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, klassIndex);
+ JavaType holder = getJavaType(type);
+ return new HotSpotMethodUnresolved(name, signature, holder);
+ }
+ }
+ }
+
+ @Override
+ public JavaType lookupType(int cpi, int opcode) {
+ final LookupTypeCacheElement elem = this.lastLookupType;
+ if (elem != null && elem.lastCpi == cpi) {
+ return elem.javaType;
+ } else {
+ final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, cpi);
+ JavaType result = getJavaType(type);
+ if (result instanceof ResolvedJavaType) {
+ this.lastLookupType = new LookupTypeCacheElement(cpi, result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public JavaField lookupField(int cpi, int opcode) {
+ final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+ final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
+ final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
+ String name = lookupUtf8(nameIndex);
+ final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
+ String typeName = lookupUtf8(typeIndex);
+ JavaType type = runtime().lookupType(typeName, getHolder(), false);
+
+ final int holderIndex = getKlassRefIndexAt(index);
+ JavaType holder = lookupType(holderIndex, opcode);
+
+ if (holder instanceof HotSpotResolvedObjectTypeImpl) {
+ long[] info = new long[2];
+ HotSpotResolvedObjectTypeImpl resolvedHolder;
+ try {
+ resolvedHolder = runtime().getCompilerToVM().resolveFieldInPool(this, index, (byte) opcode, info);
+ } catch (Throwable t) {
+ /*
+ * If there was an exception resolving the field we give up and return an unresolved
+ * field.
+ */
+ return new HotSpotUnresolvedField(holder, name, type);
+ }
+ final int flags = (int) info[0];
+ final long offset = info[1];
+ HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags);
+ return result;
+ } else {
+ return new HotSpotUnresolvedField(holder, name, type);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("fallthrough")
+ public void loadReferencedType(int cpi, int opcode) {
+ int index;
+ switch (opcode) {
+ case Bytecodes.CHECKCAST:
+ case Bytecodes.INSTANCEOF:
+ case Bytecodes.NEW:
+ case Bytecodes.ANEWARRAY:
+ case Bytecodes.MULTIANEWARRAY:
+ case Bytecodes.LDC:
+ case Bytecodes.LDC_W:
+ case Bytecodes.LDC2_W:
+ index = cpi;
+ break;
+ case Bytecodes.INVOKEDYNAMIC: {
+ // invokedynamic instructions point to a constant pool cache entry.
+ index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
+ index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+ break;
+ }
+ case Bytecodes.GETSTATIC:
+ case Bytecodes.PUTSTATIC:
+ case Bytecodes.GETFIELD:
+ case Bytecodes.PUTFIELD:
+ case Bytecodes.INVOKEVIRTUAL:
+ case Bytecodes.INVOKESPECIAL:
+ case Bytecodes.INVOKESTATIC:
+ case Bytecodes.INVOKEINTERFACE: {
+ // invoke and field instructions point to a constant pool cache entry.
+ index = rawIndexToConstantPoolIndex(cpi, opcode);
+ index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+ break;
+ }
+ default:
+ throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
+ }
+
+ final JVM_CONSTANT tag = getTagAt(index);
+ if (tag == null) {
+ assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
+ return;
+ }
+ switch (tag) {
+ case MethodRef:
+ case Fieldref:
+ case InterfaceMethodref:
+ case Class:
+ case UnresolvedClass:
+ case UnresolvedClassInError:
+ index = getUncachedKlassRefIndexAt(index, tag);
+ final HotSpotResolvedObjectTypeImpl type = runtime().getCompilerToVM().resolveTypeInPool(this, index);
+ Class<?> klass = type.mirror();
+ if (!klass.isPrimitive() && !klass.isArray()) {
+ UNSAFE.ensureClassInitialized(klass);
+ }
+ switch (tag) {
+ case MethodRef:
+ if (Bytecodes.isInvokeHandleAlias(opcode)) {
+ final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
+ if (isInvokeHandle(methodRefCacheIndex, type)) {
+ runtime().getCompilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
+ }
+ }
+ }
+ break;
+ case InvokeDynamic:
+ if (isInvokedynamicIndex(cpi)) {
+ runtime().getCompilerToVM().resolveInvokeDynamicInPool(this, cpi);
+ }
+ break;
+ default:
+ // nothing
+ break;
+ }
+ }
+
+ private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) {
+ assertTag(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+ return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameOf(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess());
+ }
+
+ @Override
+ public String toString() {
+ HotSpotResolvedObjectType holder = getHolder();
+ return "HotSpotConstantPool<" + holder.toJavaName() + ">";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider.Options.*;
+
+import java.lang.reflect.*;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.options.*;
+
+/**
+ * HotSpot implementation of {@link ConstantReflectionProvider}.
+ */
+public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider, HotSpotProxified {
+
+ static class Options {
+ //@formatter:off
+ @Option(help = "Constant fold final fields with default values.", type = OptionType.Debug)
+ public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
+ //@formatter:on
+ }
+
+ protected final HotSpotJVMCIRuntimeProvider runtime;
+ protected final HotSpotMethodHandleAccessProvider methodHandleAccess;
+ protected final HotSpotMemoryAccessProviderImpl memoryAccess;
+
+ public HotSpotConstantReflectionProvider(HotSpotJVMCIRuntimeProvider runtime) {
+ this.runtime = runtime;
+ this.methodHandleAccess = new HotSpotMethodHandleAccessProvider(this);
+ this.memoryAccess = new HotSpotMemoryAccessProviderImpl(runtime);
+ }
+
+ public MethodHandleAccessProvider getMethodHandleAccess() {
+ return methodHandleAccess;
+ }
+
+ @Override
+ public MemoryAccessProvider getMemoryAccessProvider() {
+ return memoryAccess;
+ }
+
+ @Override
+ public boolean isEmbeddable(Constant constant) {
+ return true;
+ }
+
+ @Override
+ public Boolean constantEquals(Constant x, Constant y) {
+ if (x == y) {
+ return true;
+ } else if (x instanceof HotSpotObjectConstantImpl) {
+ return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object();
+ } else {
+ return x.equals(y);
+ }
+ }
+
+ @Override
+ public Integer readArrayLength(JavaConstant array) {
+ if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
+ return null;
+ }
+
+ Object arrayObject = ((HotSpotObjectConstantImpl) array).object();
+ if (!arrayObject.getClass().isArray()) {
+ return null;
+ }
+ return Array.getLength(arrayObject);
+ }
+
+ public JavaConstant readConstantArrayElement(JavaConstant array, int index) {
+ if (array instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) array).getStableDimension() > 0) {
+ JavaConstant element = readArrayElement(array, index);
+ if (element != null && (((HotSpotObjectConstantImpl) array).isDefaultStable() || !element.isDefaultForKind())) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Try to convert {@code offset} into an an index into {@code array}.
+ *
+ * @return the computed index or -1 if the offset isn't within the array
+ */
+ private int indexForOffset(JavaConstant array, long offset) {
+ if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
+ return -1;
+ }
+ Class<?> componentType = ((HotSpotObjectConstantImpl) array).object().getClass().getComponentType();
+ JavaKind kind = runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(componentType).getJavaKind();
+ int arraybase = runtime.getArrayBaseOffset(kind);
+ int scale = runtime.getArrayIndexScale(kind);
+ if (offset < arraybase) {
+ return -1;
+ }
+ long index = offset - arraybase;
+ if (index % scale != 0) {
+ return -1;
+ }
+ long result = index / scale;
+ if (result >= Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) result;
+ }
+
+ public JavaConstant readConstantArrayElementForOffset(JavaConstant array, long offset) {
+ if (array instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) array).getStableDimension() > 0) {
+ return readConstantArrayElement(array, indexForOffset(array, offset));
+ }
+ return null;
+ }
+
+ @Override
+ public JavaConstant readArrayElement(JavaConstant array, int index) {
+ if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
+ return null;
+ }
+ Object a = ((HotSpotObjectConstantImpl) array).object();
+
+ if (index < 0 || index >= Array.getLength(a)) {
+ return null;
+ }
+
+ if (a instanceof Object[]) {
+ Object element = ((Object[]) a)[index];
+ if (((HotSpotObjectConstantImpl) array).getStableDimension() > 1) {
+ return HotSpotObjectConstantImpl.forStableArray(element, ((HotSpotObjectConstantImpl) array).getStableDimension() - 1, ((HotSpotObjectConstantImpl) array).isDefaultStable());
+ } else {
+ return HotSpotObjectConstantImpl.forObject(element);
+ }
+ } else {
+ return JavaConstant.forBoxedPrimitive(Array.get(a, index));
+ }
+ }
+
+ /**
+ * Check if the constant is a boxed value that is guaranteed to be cached by the platform.
+ * Otherwise the generated code might be the only reference to the boxed value and since object
+ * references from nmethods are weak this can cause GC problems.
+ *
+ * @param source
+ * @return true if the box is cached
+ */
+ private static boolean isBoxCached(JavaConstant source) {
+ switch (source.getJavaKind()) {
+ case Boolean:
+ return true;
+ case Char:
+ return source.asInt() <= 127;
+ case Byte:
+ case Short:
+ case Int:
+ return source.asInt() >= -128 && source.asInt() <= 127;
+ case Long:
+ return source.asLong() >= -128 && source.asLong() <= 127;
+ case Float:
+ case Double:
+ return false;
+ default:
+ throw new IllegalArgumentException("unexpected kind " + source.getJavaKind());
+ }
+ }
+
+ @Override
+ public JavaConstant boxPrimitive(JavaConstant source) {
+ if (!source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
+ return null;
+ }
+ return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive());
+ }
+
+ @Override
+ public JavaConstant unboxPrimitive(JavaConstant source) {
+ if (!source.getJavaKind().isObject()) {
+ return null;
+ }
+ if (source.isNull()) {
+ return null;
+ }
+ return JavaConstant.forBoxedPrimitive(((HotSpotObjectConstantImpl) source).object());
+ }
+
+ public JavaConstant forString(String value) {
+ return HotSpotObjectConstantImpl.forObject(value);
+ }
+
+ @Override
+ public ResolvedJavaType asJavaType(Constant constant) {
+ if (constant instanceof HotSpotObjectConstant) {
+ Object obj = ((HotSpotObjectConstantImpl) constant).object();
+ if (obj instanceof Class) {
+ return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType((Class<?>) obj);
+ }
+ }
+ if (constant instanceof HotSpotMetaspaceConstant) {
+ Object obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
+ if (obj instanceof HotSpotResolvedObjectTypeImpl) {
+ return (ResolvedJavaType) obj;
+ }
+ }
+ return null;
+ }
+
+ private static final String SystemClassName = "Ljava/lang/System;";
+
+ /**
+ * Determines if a static field is constant for the purpose of
+ * {@link #readConstantFieldValue(JavaField, JavaConstant)}.
+ */
+ protected boolean isStaticFieldConstant(HotSpotResolvedJavaField staticField) {
+ if (staticField.isFinal() || staticField.isStable()) {
+ ResolvedJavaType holder = staticField.getDeclaringClass();
+ if (holder.isInitialized() && !holder.getName().equals(SystemClassName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines if a value read from a {@code final} instance field is considered constant. The
+ * implementation in {@link HotSpotConstantReflectionProvider} returns true if {@code value} is
+ * not the {@link JavaConstant#isDefaultForKind default value} for its kind or if
+ * {@link Options#TrustFinalDefaultFields} is true.
+ *
+ * @param value a value read from a {@code final} instance field
+ * @param receiverClass the {@link Object#getClass() class} of object from which the
+ * {@code value} was read
+ */
+ protected boolean isFinalInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
+ return !value.isDefaultForKind() || TrustFinalDefaultFields.getValue();
+ }
+
+ /**
+ * Determines if a value read from a {@link Stable} instance field is considered constant. The
+ * implementation in {@link HotSpotConstantReflectionProvider} returns true if {@code value} is
+ * not the {@link JavaConstant#isDefaultForKind default value} for its kind.
+ *
+ * @param value a value read from a {@link Stable} field
+ * @param receiverClass the {@link Object#getClass() class} of object from which the
+ * {@code value} was read
+ */
+ protected boolean isStableInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
+ return !value.isDefaultForKind();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The {@code value} field in {@link OptionValue} is considered constant if the type of
+ * {@code receiver} is (assignable to) {@link StableOptionValue}.
+ */
+ public JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver) {
+ HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+
+ if (hotspotField.isStatic()) {
+ if (isStaticFieldConstant(hotspotField)) {
+ JavaConstant value = readFieldValue(field, receiver);
+ if (hotspotField.isFinal() || !value.isDefaultForKind()) {
+ return value;
+ }
+ }
+ } else {
+ /*
+ * for non-static final fields, we must assume that they are only initialized if they
+ * have a non-default value.
+ */
+ Object object = receiver.isNull() ? null : ((HotSpotObjectConstantImpl) receiver).object();
+
+ // Canonicalization may attempt to process an unsafe read before
+ // processing a guard (e.g. a null check or a type check) for this read
+ // so we need to check the object being read
+ if (object != null) {
+ if (hotspotField.isFinal()) {
+ if (hotspotField.isInObject(object)) {
+ JavaConstant value = readFieldValue(field, receiver);
+ if (isFinalInstanceFieldValueConstant(value, object.getClass())) {
+ return value;
+ }
+ }
+ } else if (hotspotField.isStable()) {
+ if (hotspotField.isInObject(object)) {
+ JavaConstant value = readFieldValue(field, receiver);
+ if (isStableInstanceFieldValueConstant(value, object.getClass())) {
+ return value;
+ }
+ }
+ } else {
+ Class<?> clazz = object.getClass();
+ if (StableOptionValue.class.isAssignableFrom(clazz)) {
+ if (hotspotField.isInObject(object) && hotspotField.getName().equals("value")) {
+ StableOptionValue<?> option = (StableOptionValue<?>) object;
+ return HotSpotObjectConstantImpl.forObject(option.getValue());
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public JavaConstant readFieldValue(JavaField field, JavaConstant receiver) {
+ HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+ if (!hotspotField.isStable()) {
+ return readNonStableFieldValue(field, receiver);
+ } else {
+ return readStableFieldValue(field, receiver, false);
+ }
+ }
+
+ private JavaConstant readNonStableFieldValue(JavaField field, JavaConstant receiver) {
+ HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+ if (hotspotField.isStatic()) {
+ HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
+ if (holder.isInitialized()) {
+ return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), hotspotField.offset());
+ }
+ } else {
+ if (receiver.isNonNull() && hotspotField.isInObject(((HotSpotObjectConstantImpl) receiver).object())) {
+ return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), receiver, hotspotField.offset());
+ }
+ }
+ return null;
+ }
+
+ public JavaConstant readStableFieldValue(JavaField field, JavaConstant receiver, boolean isDefaultStable) {
+ JavaConstant fieldValue = readNonStableFieldValue(field, receiver);
+ if (fieldValue.isNonNull()) {
+ JavaType declaredType = field.getType();
+ if (declaredType.getComponentType() != null) {
+ int stableDimension = getArrayDimension(declaredType);
+ return HotSpotObjectConstantImpl.forStableArray(((HotSpotObjectConstantImpl) fieldValue).object(), stableDimension, isDefaultStable);
+ }
+ }
+ return fieldValue;
+ }
+
+ private static int getArrayDimension(JavaType type) {
+ int dimensions = 0;
+ JavaType componentType = type;
+ while ((componentType = componentType.getComponentType()) != null) {
+ dimensions++;
+ }
+ return dimensions;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+public class HotSpotForeignCallTarget {
+
+ /**
+ * The entry point address of this call's target.
+ */
+ protected long address;
+
+ public HotSpotForeignCallTarget(long address) {
+ this.address = address;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.inittimer.SuppressFBWarnings;
+import sun.misc.Unsafe;
+
+/**
+ * Implementation of {@link InstalledCode} for HotSpot.
+ */
+public abstract class HotSpotInstalledCode extends InstalledCode {
+
+ /**
+ * Total size of the code blob.
+ */
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
+
+ /**
+ * Start address of the code.
+ */
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
+
+ /**
+ * Size of the code.
+ */
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
+
+ public HotSpotInstalledCode(String name) {
+ super(name);
+ }
+
+ /**
+ * @return the total size of this code blob
+ */
+ public int getSize() {
+ return size;
+ }
+
+ /**
+ * @return a copy of this code blob if it is {@linkplain #isValid() valid}, null otherwise.
+ */
+ public byte[] getBlob() {
+ if (!isValid()) {
+ return null;
+ }
+ byte[] blob = new byte[size];
+ UNSAFE.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
+ return blob;
+ }
+
+ @Override
+ public abstract String toString();
+
+ @Override
+ public long getStart() {
+ return codeStart;
+ }
+
+ @Override
+ public long getCodeSize() {
+ return codeSize;
+ }
+
+ @Override
+ public byte[] getCode() {
+ if (!isValid()) {
+ return null;
+ }
+ byte[] code = new byte[codeSize];
+ UNSAFE.copyMemory(null, codeStart, code, Unsafe.ARRAY_BYTE_BASE_OFFSET, codeSize);
+ return code;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.compiler.*;
+import jdk.vm.ci.runtime.*;
+
+public interface HotSpotJVMCIBackendFactory {
+
+ JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host);
+
+ /**
+ * Gets the CPU architecture of this backend.
+ */
+ String getArchitecture();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.compiler.*;
+import jdk.vm.ci.compiler.Compiler;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.service.*;
+
+final class HotSpotJVMCICompilerConfig {
+
+ private static class DummyCompilerFactory implements CompilerFactory, Compiler {
+
+ public void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+ throw new JVMCIError("no JVMCI compiler selected");
+ }
+
+ public String getCompilerName() {
+ return "<none>";
+ }
+
+ public Architecture initializeArchitecture(Architecture arch) {
+ return arch;
+ }
+
+ public Compiler createCompiler(JVMCIRuntime runtime) {
+ return this;
+ }
+ }
+
+ private static CompilerFactory compilerFactory;
+
+ /**
+ * Selects the system compiler.
+ *
+ * Called from VM. This method has an object return type to allow it to be called with a VM
+ * utility function used to call other static initialization methods.
+ */
+ static Boolean selectCompiler(String compilerName) {
+ assert compilerFactory == null;
+ for (CompilerFactory factory : Services.load(CompilerFactory.class)) {
+ if (factory.getCompilerName().equals(compilerName)) {
+ compilerFactory = factory;
+ return Boolean.TRUE;
+ }
+ }
+
+ throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
+ }
+
+ static CompilerFactory getCompilerFactory() {
+ if (compilerFactory == null) {
+ compilerFactory = new DummyCompilerFactory();
+ }
+ return compilerFactory;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.ref.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * This class manages the set of metadata roots that must be scanned during garbage collection.
+ * Because of class redefinition Method* and ConstantPool* can be freed if they don't appear to be
+ * in use so they must be tracked when there are live references to them from Java.
+ *
+ * The general theory of operation is that all {@link MetaspaceWrapperObject}s are created by
+ * calling into the VM which calls back out to actually create the wrapper instance. During the call
+ * the VM keeps the metadata reference alive through the use of metadata handles. Once the call
+ * completes the wrapper object is registered here and will be scanned during metadata scanning. The
+ * weakness of the reference to the wrapper object allows them to be reclaimed when they are no
+ * longer used.
+ *
+ */
+public class HotSpotJVMCIMetaAccessContext implements JVMCIMetaAccessContext {
+
+ /**
+ * The set of currently live contexts used for tracking of live metadata. Examined from the VM
+ * during garbage collection.
+ */
+ private static WeakReference<?>[] allContexts = new WeakReference<?>[0];
+
+ /**
+ * This is a chunked list of metadata roots. It can be read from VM native code so it's been
+ * marked volatile to ensure the order of updates are respected.
+ */
+ private volatile Object[] metadataRoots;
+
+ private ChunkedList<WeakReference<MetaspaceWrapperObject>> list = new ChunkedList<>();
+
+ /**
+ * The number of weak references freed since the last time the list was shrunk.
+ */
+ private int freed;
+
+ /**
+ * The {@link ReferenceQueue} tracking the weak references created by this context.
+ */
+ private final ReferenceQueue<MetaspaceWrapperObject> queue = new ReferenceQueue<>();
+
+ static synchronized void add(HotSpotJVMCIMetaAccessContext context) {
+ for (int i = 0; i < allContexts.length; i++) {
+ if (allContexts[i] == null || allContexts[i].get() == null) {
+ allContexts[i] = new WeakReference<>(context);
+ return;
+ }
+ }
+ int index = allContexts.length;
+ allContexts = Arrays.copyOf(allContexts, index + 2);
+ allContexts[index] = new WeakReference<>(context);
+ }
+
+ HotSpotJVMCIMetaAccessContext() {
+ add(this);
+ }
+
+ /**
+ * Periodically trim the list of tracked metadata. A new list is created to replace the old to
+ * avoid concurrent scanning issues.
+ */
+ private void clean() {
+ Reference<?> ref = queue.poll();
+ if (ref == null) {
+ return;
+ }
+ while (ref != null) {
+ freed++;
+ ref = queue.poll();
+ }
+ if (freed > list.size() / 2) {
+ ChunkedList<WeakReference<MetaspaceWrapperObject>> newList = new ChunkedList<>();
+ for (WeakReference<MetaspaceWrapperObject> element : list) {
+ /*
+ * The referent could become null anywhere in here but it doesn't matter. It will
+ * get cleaned up next time.
+ */
+ if (element != null && element.get() != null) {
+ newList.add(element);
+ }
+ }
+ list = newList;
+ metadataRoots = list.getHead();
+ freed = 0;
+ }
+ }
+
+ /**
+ * Add a {@link MetaspaceWrapperObject} to tracked by the GC. It's assumed that the caller is
+ * responsible for keeping the reference alive for the duration of the call. Once registration
+ * is complete then the VM will ensure it's kept alive.
+ *
+ * @param metaspaceObject
+ */
+
+ public synchronized void add(MetaspaceWrapperObject metaspaceObject) {
+ clean();
+ list.add(new WeakReference<>(metaspaceObject, queue));
+ if (list.getHead() != metadataRoots) {
+ /*
+ * The list enlarged so update the head.
+ */
+ metadataRoots = list.getHead();
+ }
+ }
+
+ protected ResolvedJavaType createClass(Class<?> javaClass) {
+ if (javaClass.isPrimitive()) {
+ JavaKind kind = JavaKind.fromJavaClass(javaClass);
+ return new HotSpotResolvedPrimitiveType(kind);
+ } else {
+ return new HotSpotResolvedObjectTypeImpl(javaClass, this);
+ }
+ }
+
+ private final Map<Class<?>, WeakReference<ResolvedJavaType>> typeMap = new WeakHashMap<>();
+
+ @Override
+ public synchronized ResolvedJavaType fromClass(Class<?> javaClass) {
+ WeakReference<ResolvedJavaType> typeRef = typeMap.get(javaClass);
+ ResolvedJavaType type = typeRef != null ? typeRef.get() : null;
+ if (type == null) {
+ type = createClass(javaClass);
+ typeMap.put(javaClass, new WeakReference<>(type));
+ }
+ return type;
+ }
+
+ /**
+ * A very simple append only chunked list implementation.
+ */
+ static class ChunkedList<T> implements Iterable<T> {
+ private static final int CHUNK_SIZE = 32;
+
+ private static final int NEXT_CHUNK_INDEX = CHUNK_SIZE - 1;
+
+ private Object[] head;
+ private int index;
+ private int size;
+
+ ChunkedList() {
+ head = new Object[CHUNK_SIZE];
+ index = 0;
+ }
+
+ void add(T element) {
+ if (index == NEXT_CHUNK_INDEX) {
+ Object[] newHead = new Object[CHUNK_SIZE];
+ newHead[index] = head;
+ head = newHead;
+ index = 0;
+ }
+ head[index++] = element;
+ size++;
+ }
+
+ Object[] getHead() {
+ return head;
+ }
+
+ public Iterator<T> iterator() {
+ return new ChunkIterator<>();
+ }
+
+ int size() {
+ return size;
+ }
+
+ class ChunkIterator<V> implements Iterator<V> {
+
+ ChunkIterator() {
+ currentChunk = head;
+ currentIndex = -1;
+ findNext();
+ }
+
+ Object[] currentChunk;
+ int currentIndex;
+ V next;
+
+ @SuppressWarnings("unchecked")
+ V findNext() {
+ V result;
+ do {
+ currentIndex++;
+ if (currentIndex == NEXT_CHUNK_INDEX) {
+ currentChunk = (Object[]) currentChunk[currentIndex];
+ currentIndex = 0;
+ if (currentChunk == null) {
+ return null;
+ }
+ }
+ result = (V) currentChunk[currentIndex];
+ } while (result == null);
+ return result;
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public V next() {
+ V result = next;
+ next = findNext();
+ return result;
+ }
+
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.inittimer.InitTimer.*;
+
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.compiler.*;
+import jdk.vm.ci.compiler.Compiler;
+import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.service.*;
+
+//JaCoCo Exclude
+
+public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified {
+
+ /**
+ * The proper initialization of this class is complex because it's tangled up with the
+ * initialization of the JVMCI and really should only ever be triggered through
+ * {@link JVMCI#getRuntime}. However since {@link #runtime} can also be called directly it
+ * should also trigger proper initialization. To ensure proper ordering, the static initializer
+ * of this class initializes {@link JVMCI} and then access to {@link DelayedInit#instance}
+ * triggers the final initialization of the {@link HotSpotJVMCIRuntime}.
+ */
+ static {
+ JVMCI.initialize();
+ }
+
+ @SuppressWarnings("try")
+ static class DelayedInit {
+ private static final HotSpotJVMCIRuntime instance;
+
+ static {
+ try (InitTimer t0 = timer("HotSpotJVMCIRuntime.<clinit>")) {
+ try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) {
+ for (StartupEventListener l : Services.load(StartupEventListener.class)) {
+ l.beforeJVMCIStartup();
+ }
+ }
+
+ try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
+ instance = new HotSpotJVMCIRuntime();
+ }
+
+ try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) {
+ instance.completeInitialization();
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the singleton {@link HotSpotJVMCIRuntime} object.
+ */
+ public static HotSpotJVMCIRuntime runtime() {
+ assert DelayedInit.instance != null;
+ return DelayedInit.instance;
+ }
+
+ /**
+ * Do deferred initialization.
+ */
+ public void completeInitialization() {
+ compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this);
+ for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
+ vmEventListener.completeInitialization(this);
+ }
+ }
+
+ public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
+ for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
+ if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
+ return factory;
+ }
+ }
+
+ throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
+ }
+
+ /**
+ * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
+ */
+ public static JavaKind getHostWordKind() {
+ return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordKind;
+ }
+
+ protected final CompilerToVM compilerToVm;
+
+ protected final HotSpotVMConfig config;
+ private final JVMCIBackend hostBackend;
+
+ private Compiler compiler;
+ protected final JVMCIMetaAccessContext metaAccessContext;
+
+ private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
+
+ private final Iterable<HotSpotVMEventListener> vmEventListeners;
+
+ @SuppressWarnings("try")
+ private HotSpotJVMCIRuntime() {
+ compilerToVm = new CompilerToVM();
+ try (InitTimer t = timer("HotSpotVMConfig<init>")) {
+ config = new HotSpotVMConfig(compilerToVm);
+ }
+
+ String hostArchitecture = config.getHostArchitectureName();
+
+ HotSpotJVMCIBackendFactory factory;
+ try (InitTimer t = timer("find factory:", hostArchitecture)) {
+ factory = findFactory(hostArchitecture);
+ }
+
+ CompilerFactory compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
+
+ try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
+ hostBackend = registerBackend(factory.createJVMCIBackend(this, compilerFactory, null));
+ }
+
+ vmEventListeners = Services.load(HotSpotVMEventListener.class);
+
+ JVMCIMetaAccessContext context = null;
+ for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
+ context = vmEventListener.createMetaAccessContext(this);
+ if (context != null) {
+ break;
+ }
+ }
+ if (context == null) {
+ context = new HotSpotJVMCIMetaAccessContext();
+ }
+ metaAccessContext = context;
+ }
+
+ private JVMCIBackend registerBackend(JVMCIBackend backend) {
+ Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
+ JVMCIBackend oldValue = backends.put(arch, backend);
+ assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
+ return backend;
+ }
+
+ public ResolvedJavaType fromClass(Class<?> javaClass) {
+ return metaAccessContext.fromClass(javaClass);
+ }
+
+ public HotSpotVMConfig getConfig() {
+ return config;
+ }
+
+ public CompilerToVM getCompilerToVM() {
+ return compilerToVm;
+ }
+
+ public JVMCIMetaAccessContext getMetaAccessContext() {
+ return metaAccessContext;
+ }
+
+ public Compiler getCompiler() {
+ return compiler;
+ }
+
+ public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
+ Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
+ // If the name represents a primitive type we can short-circuit the lookup.
+ if (name.length() == 1) {
+ JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
+ return fromClass(kind.toJavaClass());
+ }
+
+ // Resolve non-primitive types in the VM.
+ HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
+ final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
+
+ if (klass == null) {
+ assert resolve == false;
+ return HotSpotUnresolvedJavaType.create(this, name);
+ }
+ return klass;
+ }
+
+ public JVMCIBackend getHostJVMCIBackend() {
+ return hostBackend;
+ }
+
+ public <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch) {
+ assert arch != Architecture.class;
+ return backends.get(arch);
+ }
+
+ public Map<Class<? extends Architecture>, JVMCIBackend> getBackends() {
+ return Collections.unmodifiableMap(backends);
+ }
+
+ /**
+ * Called from the VM.
+ */
+ @SuppressWarnings({"unused"})
+ private void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+ compiler.compileMethod(method, entryBCI, jvmciEnv, id);
+ }
+
+ /**
+ * Shuts down the runtime.
+ *
+ * Called from the VM.
+ */
+ @SuppressWarnings({"unused"})
+ private void shutdown() throws Exception {
+ for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
+ vmEventListener.notifyShutdown();
+ }
+ }
+
+ /**
+ * Notify on successful install into the CodeCache.
+ *
+ * @param hotSpotCodeCacheProvider
+ * @param installedCode
+ * @param compResult
+ */
+ void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompilationResult compResult) {
+ for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
+ vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compResult);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.compiler.Compiler;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+import sun.misc.*;
+
+//JaCoCo Exclude
+
+/**
+ * Configuration information for the HotSpot JVMCI runtime.
+ */
+public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime {
+
+ HotSpotVMConfig getConfig();
+
+ CompilerToVM getCompilerToVM();
+
+ Compiler getCompiler();
+
+ /**
+ * Converts a name to a Java type. This method attempts to resolve {@code name} to a
+ * {@link ResolvedJavaType}.
+ *
+ * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
+ * @param accessingType the context of resolution which must be non-null
+ * @param resolve specifies whether resolution failure results in an unresolved type being
+ * return or a {@link LinkageError} being thrown
+ * @return a Java type for {@code name} which is guaranteed to be of type
+ * {@link ResolvedJavaType} if {@code resolve == true}
+ * @throws LinkageError if {@code resolve == true} and the resolution failed
+ * @throws NullPointerException if {@code accessingClass} is {@code null}
+ */
+ JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve);
+
+ /**
+ * Gets the JVMCI mirror for a {@link Class} object.
+ *
+ * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+ */
+ ResolvedJavaType fromClass(Class<?> clazz);
+
+ JVMCIMetaAccessContext getMetaAccessContext();
+
+ /**
+ * The offset from the origin of an array to the first element.
+ *
+ * @return the offset in bytes
+ */
+ default int getArrayBaseOffset(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+ case Byte:
+ return Unsafe.ARRAY_BYTE_BASE_OFFSET;
+ case Char:
+ return Unsafe.ARRAY_CHAR_BASE_OFFSET;
+ case Short:
+ return Unsafe.ARRAY_SHORT_BASE_OFFSET;
+ case Int:
+ return Unsafe.ARRAY_INT_BASE_OFFSET;
+ case Long:
+ return Unsafe.ARRAY_LONG_BASE_OFFSET;
+ case Float:
+ return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+ case Double:
+ return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+ case Object:
+ return Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+ default:
+ throw new JVMCIError("%s", kind);
+ }
+ }
+
+ /**
+ * The scale used for the index when accessing elements of an array of this kind.
+ *
+ * @return the scale in order to convert the index into a byte offset
+ */
+ default int getArrayIndexScale(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+ case Byte:
+ return Unsafe.ARRAY_BYTE_INDEX_SCALE;
+ case Char:
+ return Unsafe.ARRAY_CHAR_INDEX_SCALE;
+ case Short:
+ return Unsafe.ARRAY_SHORT_INDEX_SCALE;
+ case Int:
+ return Unsafe.ARRAY_INT_INDEX_SCALE;
+ case Long:
+ return Unsafe.ARRAY_LONG_INDEX_SCALE;
+ case Float:
+ return Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+ case Double:
+ return Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+ case Object:
+ return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+ default:
+ throw new JVMCIError("%s", kind);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Common base class for all HotSpot {@link JavaType} implementations.
+ */
+public abstract class HotSpotJavaType implements JavaType {
+
+ private final String name;
+
+ public HotSpotJavaType(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public final String getName() {
+ return name;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * HotSpot specific extension of {@link MemoryAccessProvider}.
+ */
+public interface HotSpotMemoryAccessProvider extends MemoryAccessProvider {
+
+ JavaConstant readNarrowOopConstant(Constant base, long displacement, CompressEncoding encoding);
+
+ Constant readKlassPointerConstant(Constant base, long displacement);
+
+ Constant readNarrowKlassPointerConstant(Constant base, long displacement, CompressEncoding encoding);
+
+ Constant readMethodPointerConstant(Constant base, long displacement);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+import jdk.vm.ci.meta.PrimitiveConstant;
+
+/**
+ * HotSpot implementation of {@link MemoryAccessProvider}.
+ */
+public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, HotSpotProxified {
+
+ protected final HotSpotJVMCIRuntimeProvider runtime;
+
+ public HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) {
+ this.runtime = runtime;
+ }
+
+ private static Object asObject(Constant base) {
+ if (base instanceof HotSpotObjectConstantImpl) {
+ return ((HotSpotObjectConstantImpl) base).object();
+ } else {
+ return null;
+ }
+ }
+
+ private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
+ if (base instanceof HotSpotMetaspaceConstant) {
+ Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+ if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+ if (displacement == runtime.getConfig().classMirrorOffset) {
+ // Klass::_java_mirror is valid for all Klass* values
+ return true;
+ }
+ } else {
+ throw new JVMCIError("%s", metaspaceObject);
+ }
+ }
+ return false;
+ }
+
+ private static long asRawPointer(Constant base) {
+ if (base instanceof HotSpotMetaspaceConstant) {
+ return ((HotSpotMetaspaceConstant) base).rawValue();
+ } else if (base instanceof PrimitiveConstant) {
+ PrimitiveConstant prim = (PrimitiveConstant) base;
+ if (prim.getJavaKind().isNumericInteger()) {
+ return prim.asLong();
+ }
+ }
+ throw new JVMCIError("%s", base);
+ }
+
+ private static long readRawValue(Constant baseConstant, long displacement, int bits) {
+ Object base = asObject(baseConstant);
+ if (base != null) {
+ switch (bits) {
+ case 8:
+ return UNSAFE.getByte(base, displacement);
+ case 16:
+ return UNSAFE.getShort(base, displacement);
+ case 32:
+ return UNSAFE.getInt(base, displacement);
+ case 64:
+ return UNSAFE.getLong(base, displacement);
+ default:
+ throw new JVMCIError("%d", bits);
+ }
+ } else {
+ long pointer = asRawPointer(baseConstant);
+ switch (bits) {
+ case 8:
+ return UNSAFE.getByte(pointer + displacement);
+ case 16:
+ return UNSAFE.getShort(pointer + displacement);
+ case 32:
+ return UNSAFE.getInt(pointer + displacement);
+ case 64:
+ return UNSAFE.getLong(pointer + displacement);
+ default:
+ throw new JVMCIError("%d", bits);
+ }
+ }
+ }
+
+ private boolean verifyReadRawObject(Object expected, Constant base, long displacement, boolean compressed) {
+ if (compressed == runtime.getConfig().useCompressedOops) {
+ Object obj = asObject(base);
+ if (obj != null) {
+ assert expected == UNSAFE.getObject(obj, displacement) : "readUnsafeOop doesn't agree with unsafe.getObject";
+ }
+ }
+ if (base instanceof HotSpotMetaspaceConstant) {
+ Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+ if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+ if (displacement == runtime.getConfig().classMirrorOffset) {
+ assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
+ }
+ }
+ }
+ return true;
+ }
+
+ private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
+ long displacement = initialDisplacement;
+
+ Object ret;
+ Object base = asObject(baseConstant);
+ if (base == null) {
+ assert !compressed;
+ displacement += asRawPointer(baseConstant);
+ ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
+ } else {
+ assert runtime.getConfig().useCompressedOops == compressed;
+ ret = UNSAFE.getObject(base, displacement);
+ }
+ assert verifyReadRawObject(ret, baseConstant, initialDisplacement, compressed);
+ return ret;
+ }
+
+ @Override
+ public JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) {
+ if (kind == JavaKind.Object) {
+ Object o = readRawObject(baseConstant, displacement, runtime.getConfig().useCompressedOops);
+ return HotSpotObjectConstantImpl.forObject(o);
+ } else {
+ return readPrimitiveConstant(kind, baseConstant, displacement, kind.getByteCount() * 8);
+ }
+ }
+
+ @Override
+ public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
+ try {
+ long rawValue = readRawValue(baseConstant, initialDisplacement, bits);
+ switch (kind) {
+ case Boolean:
+ return JavaConstant.forBoolean(rawValue != 0);
+ case Byte:
+ return JavaConstant.forByte((byte) rawValue);
+ case Char:
+ return JavaConstant.forChar((char) rawValue);
+ case Short:
+ return JavaConstant.forShort((short) rawValue);
+ case Int:
+ return JavaConstant.forInt((int) rawValue);
+ case Long:
+ return JavaConstant.forLong(rawValue);
+ case Float:
+ return JavaConstant.forFloat(Float.intBitsToFloat((int) rawValue));
+ case Double:
+ return JavaConstant.forDouble(Double.longBitsToDouble(rawValue));
+ default:
+ throw new JVMCIError("Unsupported kind: %s", kind);
+ }
+ } catch (NullPointerException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public JavaConstant readObjectConstant(Constant base, long displacement) {
+ if (!isValidObjectFieldDisplacement(base, displacement)) {
+ return null;
+ }
+ return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, false));
+ }
+
+ @Override
+ public JavaConstant readNarrowOopConstant(Constant base, long displacement, CompressEncoding encoding) {
+ assert encoding.equals(runtime.getConfig().getOopEncoding()) : "unexpected oop encoding: " + encoding + " != " + runtime.getConfig().getOopEncoding();
+ return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
+ }
+
+ private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
+ assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
+ Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
+ return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
+ }
+
+ @Override
+ public Constant readKlassPointerConstant(Constant base, long displacement) {
+ HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
+ if (klass == null) {
+ return JavaConstant.NULL_POINTER;
+ }
+ TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget();
+ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, klass.getMetaspaceKlass(), klass, false);
+ }
+
+ @Override
+ public Constant readNarrowKlassPointerConstant(Constant base, long displacement, CompressEncoding encoding) {
+ HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, true);
+ if (klass == null) {
+ return HotSpotCompressedNullConstant.COMPRESSED_NULL;
+ }
+ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(klass.getMetaspaceKlass()), klass, true);
+ }
+
+ @Override
+ public Constant readMethodPointerConstant(Constant base, long displacement) {
+ TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget();
+ assert (base instanceof HotSpotObjectConstantImpl);
+ Object baseObject = ((HotSpotObjectConstantImpl) base).object();
+ HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
+ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, method.getMetaspaceMethod(), method, false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.reflect.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+
+// JaCoCo Exclude
+
+/**
+ * HotSpot implementation of {@link MetaAccessProvider}.
+ */
+public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotProxified {
+
+ protected final HotSpotJVMCIRuntimeProvider runtime;
+
+ public HotSpotMetaAccessProvider(HotSpotJVMCIRuntimeProvider runtime) {
+ this.runtime = runtime;
+ }
+
+ public ResolvedJavaType lookupJavaType(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("Class parameter was null");
+ }
+ return runtime.fromClass(clazz);
+ }
+
+ public HotSpotResolvedObjectType lookupJavaType(JavaConstant constant) {
+ if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) {
+ return null;
+ }
+ return ((HotSpotObjectConstant) constant).getType();
+ }
+
+ public Signature parseMethodDescriptor(String signature) {
+ return new HotSpotSignature(runtime, signature);
+ }
+
+ /**
+ * {@link Field} object of {@link Method#slot}.
+ */
+ private Field reflectionMethodSlot = getReflectionSlotField(Method.class);
+
+ /**
+ * {@link Field} object of {@link Constructor#slot}.
+ */
+ private Field reflectionConstructorSlot = getReflectionSlotField(Constructor.class);
+
+ private static Field getReflectionSlotField(Class<?> reflectionClass) {
+ try {
+ Field field = reflectionClass.getDeclaredField("slot");
+ field.setAccessible(true);
+ return field;
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new JVMCIError(e);
+ }
+ }
+
+ public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) {
+ try {
+ Class<?> holder = reflectionMethod.getDeclaringClass();
+ Field slotField = reflectionMethod instanceof Constructor ? reflectionConstructorSlot : reflectionMethodSlot;
+ final int slot = slotField.getInt(reflectionMethod);
+ return runtime.getCompilerToVM().getResolvedJavaMethodAtSlot(holder, slot);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ throw new JVMCIError(e);
+ }
+ }
+
+ public ResolvedJavaField lookupJavaField(Field reflectionField) {
+ String name = reflectionField.getName();
+ Class<?> fieldHolder = reflectionField.getDeclaringClass();
+ Class<?> fieldType = reflectionField.getType();
+ // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits
+ // are not used (yet).
+ final int modifiers = reflectionField.getModifiers();
+ final long offset = Modifier.isStatic(modifiers) ? UNSAFE.staticFieldOffset(reflectionField) : UNSAFE.objectFieldOffset(reflectionField);
+
+ HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder);
+ JavaType type = runtime.fromClass(fieldType);
+
+ if (offset != -1) {
+ HotSpotResolvedObjectType resolved = holder;
+ return resolved.createField(name, type, offset, modifiers);
+ } else {
+ throw new JVMCIError("unresolved field %s", reflectionField);
+ }
+ }
+
+ private static int intMaskRight(int n) {
+ assert n <= 32;
+ return n == 32 ? -1 : (1 << n) - 1;
+ }
+
+ @Override
+ public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) {
+ HotSpotVMConfig config = runtime.getConfig();
+ int actionValue = convertDeoptAction(action);
+ int reasonValue = convertDeoptReason(reason);
+ int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits);
+ JavaConstant c = JavaConstant.forInt(~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
+ assert c.asInt() < 0;
+ return c;
+ }
+
+ public DeoptimizationReason decodeDeoptReason(JavaConstant constant) {
+ HotSpotVMConfig config = runtime.getConfig();
+ int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits);
+ DeoptimizationReason reason = convertDeoptReason(reasonValue);
+ return reason;
+ }
+
+ public DeoptimizationAction decodeDeoptAction(JavaConstant constant) {
+ HotSpotVMConfig config = runtime.getConfig();
+ int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits);
+ DeoptimizationAction action = convertDeoptAction(actionValue);
+ return action;
+ }
+
+ public int decodeDebugId(JavaConstant constant) {
+ HotSpotVMConfig config = runtime.getConfig();
+ return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits);
+ }
+
+ public int convertDeoptAction(DeoptimizationAction action) {
+ HotSpotVMConfig config = runtime.getConfig();
+ switch (action) {
+ case None:
+ return config.deoptActionNone;
+ case RecompileIfTooManyDeopts:
+ return config.deoptActionMaybeRecompile;
+ case InvalidateReprofile:
+ return config.deoptActionReinterpret;
+ case InvalidateRecompile:
+ return config.deoptActionMakeNotEntrant;
+ case InvalidateStopCompiling:
+ return config.deoptActionMakeNotCompilable;
+ default:
+ throw new JVMCIError("%s", action);
+ }
+ }
+
+ public DeoptimizationAction convertDeoptAction(int action) {
+ HotSpotVMConfig config = runtime.getConfig();
+ if (action == config.deoptActionNone) {
+ return DeoptimizationAction.None;
+ }
+ if (action == config.deoptActionMaybeRecompile) {
+ return DeoptimizationAction.RecompileIfTooManyDeopts;
+ }
+ if (action == config.deoptActionReinterpret) {
+ return DeoptimizationAction.InvalidateReprofile;
+ }
+ if (action == config.deoptActionMakeNotEntrant) {
+ return DeoptimizationAction.InvalidateRecompile;
+ }
+ if (action == config.deoptActionMakeNotCompilable) {
+ return DeoptimizationAction.InvalidateStopCompiling;
+ }
+ throw new JVMCIError("%d", action);
+ }
+
+ public int convertDeoptReason(DeoptimizationReason reason) {
+ HotSpotVMConfig config = runtime.getConfig();
+ switch (reason) {
+ case None:
+ return config.deoptReasonNone;
+ case NullCheckException:
+ return config.deoptReasonNullCheck;
+ case BoundsCheckException:
+ return config.deoptReasonRangeCheck;
+ case ClassCastException:
+ return config.deoptReasonClassCheck;
+ case ArrayStoreException:
+ return config.deoptReasonArrayCheck;
+ case UnreachedCode:
+ return config.deoptReasonUnreached0;
+ case TypeCheckedInliningViolated:
+ return config.deoptReasonTypeCheckInlining;
+ case OptimizedTypeCheckViolated:
+ return config.deoptReasonOptimizedTypeCheck;
+ case NotCompiledExceptionHandler:
+ return config.deoptReasonNotCompiledExceptionHandler;
+ case Unresolved:
+ return config.deoptReasonUnresolved;
+ case JavaSubroutineMismatch:
+ return config.deoptReasonJsrMismatch;
+ case ArithmeticException:
+ return config.deoptReasonDiv0Check;
+ case RuntimeConstraint:
+ return config.deoptReasonConstraint;
+ case LoopLimitCheck:
+ return config.deoptReasonLoopLimitCheck;
+ case Aliasing:
+ return config.deoptReasonAliasing;
+ case TransferToInterpreter:
+ return config.deoptReasonTransferToInterpreter;
+ default:
+ throw new JVMCIError("%s", reason);
+ }
+ }
+
+ public DeoptimizationReason convertDeoptReason(int reason) {
+ HotSpotVMConfig config = runtime.getConfig();
+ if (reason == config.deoptReasonNone) {
+ return DeoptimizationReason.None;
+ }
+ if (reason == config.deoptReasonNullCheck) {
+ return DeoptimizationReason.NullCheckException;
+ }
+ if (reason == config.deoptReasonRangeCheck) {
+ return DeoptimizationReason.BoundsCheckException;
+ }
+ if (reason == config.deoptReasonClassCheck) {
+ return DeoptimizationReason.ClassCastException;
+ }
+ if (reason == config.deoptReasonArrayCheck) {
+ return DeoptimizationReason.ArrayStoreException;
+ }
+ if (reason == config.deoptReasonUnreached0) {
+ return DeoptimizationReason.UnreachedCode;
+ }
+ if (reason == config.deoptReasonTypeCheckInlining) {
+ return DeoptimizationReason.TypeCheckedInliningViolated;
+ }
+ if (reason == config.deoptReasonOptimizedTypeCheck) {
+ return DeoptimizationReason.OptimizedTypeCheckViolated;
+ }
+ if (reason == config.deoptReasonNotCompiledExceptionHandler) {
+ return DeoptimizationReason.NotCompiledExceptionHandler;
+ }
+ if (reason == config.deoptReasonUnresolved) {
+ return DeoptimizationReason.Unresolved;
+ }
+ if (reason == config.deoptReasonJsrMismatch) {
+ return DeoptimizationReason.JavaSubroutineMismatch;
+ }
+ if (reason == config.deoptReasonDiv0Check) {
+ return DeoptimizationReason.ArithmeticException;
+ }
+ if (reason == config.deoptReasonConstraint) {
+ return DeoptimizationReason.RuntimeConstraint;
+ }
+ if (reason == config.deoptReasonLoopLimitCheck) {
+ return DeoptimizationReason.LoopLimitCheck;
+ }
+ if (reason == config.deoptReasonAliasing) {
+ return DeoptimizationReason.Aliasing;
+ }
+ if (reason == config.deoptReasonTransferToInterpreter) {
+ return DeoptimizationReason.TransferToInterpreter;
+ }
+ throw new JVMCIError("%x", reason);
+ }
+
+ @Override
+ public long getMemorySize(JavaConstant constant) {
+ if (constant.getJavaKind() == JavaKind.Object) {
+ HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant);
+
+ if (lookupJavaType == null) {
+ return 0;
+ } else {
+ if (lookupJavaType.isArray()) {
+ // TODO(tw): Add compressed pointer support.
+ int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object());
+ ResolvedJavaType elementType = lookupJavaType.getComponentType();
+ JavaKind elementKind = elementType.getJavaKind();
+ final int headerSize = runtime.getArrayBaseOffset(elementKind);
+ TargetDescription target = runtime.getHostJVMCIBackend().getTarget();
+ int sizeOfElement = target.getSizeInBytes(elementKind);
+ int alignment = target.wordSize;
+ int log2ElementSize = CodeUtil.log2(sizeOfElement);
+ return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
+ }
+ return lookupJavaType.instanceSize();
+ }
+ } else {
+ return constant.getJavaKind().getByteCount();
+ }
+ }
+
+ /**
+ * Computes the size of the memory chunk allocated for an array. This size accounts for the
+ * array header size, body size and any padding after the last element to satisfy object
+ * alignment requirements.
+ *
+ * @param length the number of elements in the array
+ * @param alignment the object alignment requirement
+ * @param headerSize the size of the array header
+ * @param log2ElementSize log2 of the size of an element in the array
+ */
+ public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) {
+ int size = (length << log2ElementSize) + headerSize + (alignment - 1);
+ int mask = ~(alignment - 1);
+ return size & mask;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+public class HotSpotMetaData {
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] pcDescBytes;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] scopesDescBytes;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] relocBytes;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] exceptionBytes;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] oopMaps;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private String[] metadata;
+
+ public byte[] pcDescBytes() {
+ return pcDescBytes != null ? pcDescBytes : new byte[0];
+ }
+
+ public byte[] scopesDescBytes() {
+ return scopesDescBytes != null ? scopesDescBytes : new byte[0];
+ }
+
+ public byte[] relocBytes() {
+ return relocBytes != null ? relocBytes : new byte[0];
+ }
+
+ public byte[] exceptionBytes() {
+ return exceptionBytes != null ? exceptionBytes : new byte[0];
+ }
+
+ public byte[] oopMaps() {
+ return oopMaps != null ? oopMaps : new byte[0];
+ }
+
+ public String[] metadataEntries() {
+ return metadata != null ? metadata : new String[0];
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
+import jdk.vm.ci.meta.*;
+
+public interface HotSpotMetaspaceConstant extends HotSpotConstant, VMConstant {
+
+ Constant compress(CompressEncoding encoding);
+
+ Constant uncompress(CompressEncoding encoding);
+
+ HotSpotResolvedObjectType asResolvedJavaType();
+
+ HotSpotResolvedJavaMethod asResolvedJavaMethod();
+
+ long rawValue();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.*;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
+import jdk.vm.ci.meta.*;
+
+public final class HotSpotMetaspaceConstantImpl extends PrimitiveConstant implements HotSpotMetaspaceConstant, VMConstant, HotSpotProxified {
+
+ static HotSpotMetaspaceConstantImpl forMetaspaceObject(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) {
+ return new HotSpotMetaspaceConstantImpl(kind, primitive, metaspaceObject, compressed);
+ }
+
+ static Object getMetaspaceObject(Constant constant) {
+ return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject;
+ }
+
+ private final Object metaspaceObject;
+ private final boolean compressed;
+
+ private HotSpotMetaspaceConstantImpl(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) {
+ super(kind, primitive);
+ this.metaspaceObject = metaspaceObject;
+ this.compressed = compressed;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ System.identityHashCode(metaspaceObject);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o == this || (o instanceof HotSpotMetaspaceConstantImpl && super.equals(o) && Objects.equals(metaspaceObject, ((HotSpotMetaspaceConstantImpl) o).metaspaceObject));
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "{" + metaspaceObject + (compressed ? ";compressed}" : "}");
+ }
+
+ public boolean isCompressed() {
+ return compressed;
+ }
+
+ public JavaConstant compress(CompressEncoding encoding) {
+ assert !isCompressed();
+ HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(asLong()), metaspaceObject, true);
+ assert res.isCompressed();
+ return res;
+ }
+
+ public JavaConstant uncompress(CompressEncoding encoding) {
+ assert isCompressed();
+ HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Long, encoding.uncompress(asInt()), metaspaceObject, false);
+ assert !res.isCompressed();
+ return res;
+ }
+
+ public HotSpotResolvedObjectType asResolvedJavaType() {
+ if (metaspaceObject instanceof HotSpotResolvedObjectType) {
+ return (HotSpotResolvedObjectType) metaspaceObject;
+ }
+ return null;
+ }
+
+ public HotSpotResolvedJavaMethod asResolvedJavaMethod() {
+ if (metaspaceObject instanceof HotSpotResolvedJavaMethod) {
+ return (HotSpotResolvedJavaMethod) metaspaceObject;
+ }
+ return null;
+ }
+
+ public long rawValue() {
+ return asLong();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.FormattableFlags.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+public abstract class HotSpotMethod implements JavaMethod, Formattable /* , JavaMethodContex */{
+
+ public static String applyFormattingFlagsAndWidth(String s, int flags, int width) {
+ if (flags == 0 && width < 0) {
+ return s;
+ }
+ StringBuilder sb = new StringBuilder(s);
+
+ // apply width and justification
+ int len = sb.length();
+ if (len < width) {
+ for (int i = 0; i < width - len; i++) {
+ if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) {
+ sb.append(' ');
+ } else {
+ sb.insert(0, ' ');
+ }
+ }
+ }
+
+ String res = sb.toString();
+ if ((flags & UPPERCASE) == UPPERCASE) {
+ res = res.toUpperCase();
+ }
+ return res;
+ }
+
+ protected String name;
+
+ /**
+ * Controls whether {@link #toString()} includes the qualified or simple name of the class in
+ * which the method is declared.
+ */
+ public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
+
+ protected HotSpotMethod(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public final String getName() {
+ return name;
+ }
+
+ @Override
+ public final String toString() {
+ char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
+ String suffix = this instanceof ResolvedJavaMethod ? "" : ", unresolved";
+ String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix);
+ return format(fmt);
+ }
+
+ public void formatTo(Formatter formatter, int flags, int width, int precision) {
+ String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString();
+ formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width));
+ }
+
+ public JavaMethod asJavaMethod() {
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,864 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.lang.String.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.util.*;
+
+import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaMethodProfile.*;
+import jdk.vm.ci.meta.JavaTypeProfile.*;
+import sun.misc.*;
+
+/**
+ * Access to a HotSpot MethodData structure (defined in methodData.hpp).
+ */
+public final class HotSpotMethodData {
+
+ private static final HotSpotVMConfig config = runtime().getConfig();
+ private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE);
+ private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN);
+
+ // sorted by tag
+ // @formatter:off
+ private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
+ null,
+ new BitData(),
+ new CounterData(),
+ new JumpData(),
+ new TypeCheckData(),
+ new VirtualCallData(),
+ new RetData(),
+ new BranchData(),
+ new MultiBranchData(),
+ new ArgInfoData(),
+ null, // call_type_data_tag
+ null, // virtual_call_type_data_tag
+ null, // parameters_type_data_tag
+ null, // speculative_trap_data_tag
+ };
+ // @formatter:on
+
+ /**
+ * Reference to the C++ MethodData object.
+ */
+ private final long metaspaceMethodData;
+ @SuppressWarnings("unused") private final HotSpotResolvedJavaMethodImpl method;
+
+ public HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
+ this.metaspaceMethodData = metaspaceMethodData;
+ this.method = method;
+ }
+
+ /**
+ * @return value of the MethodData::_data_size field
+ */
+ private int normalDataSize() {
+ return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
+ }
+
+ /**
+ * Returns the size of the extra data records. This method does the same calculation as
+ * MethodData::extra_data_size().
+ *
+ * @return size of extra data records
+ */
+ private int extraDataSize() {
+ final int extraDataBase = config.methodDataOopDataOffset + normalDataSize();
+ final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + config.methodDataSize);
+ return extraDataLimit - extraDataBase;
+ }
+
+ public boolean hasNormalData() {
+ return normalDataSize() > 0;
+ }
+
+ public boolean hasExtraData() {
+ return extraDataSize() > 0;
+ }
+
+ public int getExtraDataBeginOffset() {
+ return normalDataSize();
+ }
+
+ public boolean isWithin(int position) {
+ return position >= 0 && position < normalDataSize() + extraDataSize();
+ }
+
+ public int getDeoptimizationCount(DeoptimizationReason reason) {
+ HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
+ int reasonIndex = metaAccess.convertDeoptReason(reason);
+ return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
+ }
+
+ public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
+ HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
+ int reasonIndex = metaAccess.convertDeoptReason(reason);
+ return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
+ }
+
+ public HotSpotMethodDataAccessor getNormalData(int position) {
+ if (position >= normalDataSize()) {
+ return null;
+ }
+
+ HotSpotMethodDataAccessor result = getData(position);
+ assert result != null : "NO_DATA tag is not allowed";
+ return result;
+ }
+
+ public HotSpotMethodDataAccessor getExtraData(int position) {
+ if (position >= normalDataSize() + extraDataSize()) {
+ return null;
+ }
+ HotSpotMethodDataAccessor data = getData(position);
+ if (data != null) {
+ return data;
+ }
+ return data;
+ }
+
+ public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
+ if (exceptionPossiblyNotRecorded) {
+ return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
+ } else {
+ return NO_DATA_NO_EXCEPTION_ACCESSOR;
+ }
+ }
+
+ private HotSpotMethodDataAccessor getData(int position) {
+ assert position >= 0 : "out of bounds";
+ final Tag tag = AbstractMethodData.readTag(this, position);
+ HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag.getValue()];
+ assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
+ return accessor;
+ }
+
+ private int readUnsignedByte(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
+ }
+
+ private int readUnsignedShort(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
+ }
+
+ /**
+ * Since the values are stored in cells (platform words) this method uses
+ * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
+ */
+ private long readUnsignedInt(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
+ }
+
+ private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
+ long value = readUnsignedInt(position, offsetInBytes);
+ return truncateLongToInt(value);
+ }
+
+ /**
+ * Since the values are stored in cells (platform words) this method uses
+ * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
+ */
+ private int readInt(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
+ }
+
+ private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return runtime().compilerToVm.getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
+ }
+
+ private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
+ long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+ return runtime().compilerToVm.getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
+ }
+
+ private static int truncateLongToInt(long value) {
+ return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
+ }
+
+ private static int computeFullOffset(int position, int offsetInBytes) {
+ return config.methodDataOopDataOffset + position + offsetInBytes;
+ }
+
+ private static int cellIndexToOffset(int cells) {
+ return config.dataLayoutHeaderSize + cellsToBytes(cells);
+ }
+
+ private static int cellsToBytes(int cells) {
+ return cells * config.dataLayoutCellSize;
+ }
+
+ /**
+ * Returns whether profiling ran long enough that the profile information is mature. Other
+ * informational data will still be valid even if the profile isn't mature.
+ */
+ public boolean isProfileMature() {
+ return runtime().getCompilerToVM().isMature(metaspaceMethodData);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ String nl = String.format("%n");
+ String nlIndent = String.format("%n%38s", "");
+ if (hasNormalData()) {
+ int pos = 0;
+ HotSpotMethodDataAccessor data;
+ while ((data = getNormalData(pos)) != null) {
+ if (pos != 0) {
+ sb.append(nl);
+ }
+ int bci = data.getBCI(this, pos);
+ sb.append(String.format("%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
+ sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
+ pos = pos + data.getSize(this, pos);
+ }
+ }
+
+ if (hasExtraData()) {
+ int pos = getExtraDataBeginOffset();
+ HotSpotMethodDataAccessor data;
+ while ((data = getExtraData(pos)) != null) {
+ if (pos == getExtraDataBeginOffset()) {
+ sb.append(nl).append("--- Extra data:");
+ }
+ int bci = data.getBCI(this, pos);
+ sb.append(String.format("%n%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
+ sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
+ pos = pos + data.getSize(this, pos);
+ }
+
+ }
+ return sb.toString();
+ }
+
+ private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor {
+
+ /**
+ * Corresponds to {@code exception_seen_flag}.
+ */
+ private static final int EXCEPTIONS_MASK = 0x2;
+
+ private final Tag tag;
+ private final int staticSize;
+
+ protected AbstractMethodData(Tag tag, int staticSize) {
+ this.tag = tag;
+ this.staticSize = staticSize;
+ }
+
+ public Tag getTag() {
+ return tag;
+ }
+
+ public static Tag readTag(HotSpotMethodData data, int position) {
+ final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
+ return Tag.getEnum(tag);
+ }
+
+ @Override
+ public int getBCI(HotSpotMethodData data, int position) {
+ return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
+ }
+
+ @Override
+ public int getSize(HotSpotMethodData data, int position) {
+ return staticSize + getDynamicSize(data, position);
+ }
+
+ @Override
+ public TriState getExceptionSeen(HotSpotMethodData data, int position) {
+ return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
+ }
+
+ @Override
+ public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+ return null;
+ }
+
+ @Override
+ public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+ return null;
+ }
+
+ @Override
+ public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+ return -1;
+ }
+
+ @Override
+ public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+ return null;
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ return -1;
+ }
+
+ @Override
+ public TriState getNullSeen(HotSpotMethodData data, int position) {
+ return TriState.UNKNOWN;
+ }
+
+ protected int getFlags(HotSpotMethodData data, int position) {
+ return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
+ }
+
+ /**
+ * @param data
+ * @param position
+ */
+ protected int getDynamicSize(HotSpotMethodData data, int position) {
+ return 0;
+ }
+
+ public abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
+ }
+
+ private static class NoMethodData extends AbstractMethodData {
+
+ private static final int NO_DATA_SIZE = cellIndexToOffset(0);
+
+ private final TriState exceptionSeen;
+
+ protected NoMethodData(TriState exceptionSeen) {
+ super(Tag.No, NO_DATA_SIZE);
+ this.exceptionSeen = exceptionSeen;
+ }
+
+ @Override
+ public int getBCI(HotSpotMethodData data, int position) {
+ return -1;
+ }
+
+ @Override
+ public TriState getExceptionSeen(HotSpotMethodData data, int position) {
+ return exceptionSeen;
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ return sb;
+ }
+ }
+
+ private static class BitData extends AbstractMethodData {
+
+ private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
+ private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01;
+
+ private BitData() {
+ super(Tag.BitData, BIT_DATA_SIZE);
+ }
+
+ protected BitData(Tag tag, int staticSize) {
+ super(tag, staticSize);
+ }
+
+ @Override
+ public TriState getNullSeen(HotSpotMethodData data, int position) {
+ return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ return sb.append(format("exception_seen(%s)", getExceptionSeen(data, pos)));
+ }
+ }
+
+ private static class CounterData extends BitData {
+
+ private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
+ private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0);
+
+ public CounterData() {
+ super(Tag.CounterData, COUNTER_DATA_SIZE);
+ }
+
+ protected CounterData(Tag tag, int staticSize) {
+ super(tag, staticSize);
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ return getCounterValue(data, position);
+ }
+
+ protected int getCounterValue(HotSpotMethodData data, int position) {
+ return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ return sb.append(format("count(%d) null_seen(%s) exception_seen(%s)", getCounterValue(data, pos), getNullSeen(data, pos), getExceptionSeen(data, pos)));
+ }
+ }
+
+ private static class JumpData extends AbstractMethodData {
+
+ private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
+ protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0);
+ protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1);
+
+ public JumpData() {
+ super(Tag.JumpData, JUMP_DATA_SIZE);
+ }
+
+ protected JumpData(Tag tag, int staticSize) {
+ super(tag, staticSize);
+ }
+
+ @Override
+ public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+ return getExecutionCount(data, position) != 0 ? 1 : 0;
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
+ }
+
+ public int getTakenDisplacement(HotSpotMethodData data, int position) {
+ return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET);
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ return sb.append(format("taken(%d) displacement(%d)", getExecutionCount(data, pos), getTakenDisplacement(data, pos)));
+ }
+ }
+
+ static class RawItemProfile<T> {
+ final int entries;
+ final T[] items;
+ final long[] counts;
+ final long totalCount;
+
+ public RawItemProfile(int entries, T[] items, long[] counts, long totalCount) {
+ this.entries = entries;
+ this.items = items;
+ this.counts = counts;
+ this.totalCount = totalCount;
+ }
+ }
+
+ private abstract static class AbstractTypeData extends CounterData {
+
+ protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2);
+
+ protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1);
+ protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2);
+ protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3);
+
+ protected AbstractTypeData(Tag tag, int staticSize) {
+ super(tag, staticSize);
+ }
+
+ @Override
+ public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+ return createTypeProfile(getNullSeen(data, position), getRawTypeProfile(data, position));
+ }
+
+ private RawItemProfile<ResolvedJavaType> getRawTypeProfile(HotSpotMethodData data, int position) {
+ int typeProfileWidth = config.typeProfileWidth;
+
+ ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth];
+ long[] counts = new long[typeProfileWidth];
+ long totalCount = 0;
+ int entries = 0;
+
+ outer: for (int i = 0; i < typeProfileWidth; i++) {
+ HotSpotResolvedObjectTypeImpl receiverKlass = data.readKlass(position, getTypeOffset(i));
+ if (receiverKlass != null) {
+ HotSpotResolvedObjectTypeImpl klass = receiverKlass;
+ long count = data.readUnsignedInt(position, getTypeCountOffset(i));
+ /*
+ * Because of races in the profile collection machinery it's possible for a
+ * class to appear multiple times so merge them to make the profile look
+ * rational.
+ */
+ for (int j = 0; j < entries; j++) {
+ if (types[j].equals(klass)) {
+ totalCount += count;
+ counts[j] += count;
+ continue outer;
+ }
+ }
+ types[entries] = klass;
+ totalCount += count;
+ counts[entries] = count;
+ entries++;
+ }
+ }
+
+ totalCount += getTypesNotRecordedExecutionCount(data, position);
+ return new RawItemProfile<>(entries, types, counts, totalCount);
+ }
+
+ protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
+
+ private static JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
+ if (profile.entries <= 0 || profile.totalCount <= 0) {
+ return null;
+ }
+
+ ProfiledType[] ptypes = new ProfiledType[profile.entries];
+ double totalProbability = 0.0;
+ for (int i = 0; i < profile.entries; i++) {
+ double p = profile.counts[i];
+ p = p / profile.totalCount;
+ totalProbability += p;
+ ptypes[i] = new ProfiledType(profile.items[i], p);
+ }
+
+ Arrays.sort(ptypes);
+
+ double notRecordedTypeProbability = profile.entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+ assert notRecordedTypeProbability == 0 || profile.entries == config.typeProfileWidth;
+ return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
+ }
+
+ private static int getTypeOffset(int row) {
+ return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE;
+ }
+
+ protected static int getTypeCountOffset(int row) {
+ return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ RawItemProfile<ResolvedJavaType> profile = getRawTypeProfile(data, pos);
+ TriState nullSeen = getNullSeen(data, pos);
+ TriState exceptionSeen = getExceptionSeen(data, pos);
+ sb.append(format("count(%d) null_seen(%s) exception_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, exceptionSeen,
+ getTypesNotRecordedExecutionCount(data, pos), profile.entries));
+ for (int i = 0; i < profile.entries; i++) {
+ long count = profile.counts[i];
+ sb.append(format("%n %s (%d, %4.2f)", profile.items[i].toJavaName(), count, (double) count / profile.totalCount));
+ }
+ return sb;
+ }
+ }
+
+ private static class TypeCheckData extends AbstractTypeData {
+
+ private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+
+ public TypeCheckData() {
+ super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ return -1;
+ }
+
+ @Override
+ protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+ return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+ }
+ }
+
+ private static class VirtualCallData extends AbstractTypeData {
+
+ private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
+ private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+ private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+
+ public VirtualCallData() {
+ super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ final int typeProfileWidth = config.typeProfileWidth;
+
+ long total = 0;
+ for (int i = 0; i < typeProfileWidth; i++) {
+ total += data.readUnsignedInt(position, getTypeCountOffset(i));
+ }
+
+ total += getCounterValue(data, position);
+ return truncateLongToInt(total);
+ }
+
+ @Override
+ protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+ return getCounterValue(data, position);
+ }
+
+ private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+ return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+ }
+
+ @Override
+ public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+ return createMethodProfile(getRawMethodProfile(data, position));
+ }
+
+ private static RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
+ int profileWidth = config.methodProfileWidth;
+
+ ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth];
+ long[] counts = new long[profileWidth];
+ long totalCount = 0;
+ int entries = 0;
+
+ for (int i = 0; i < profileWidth; i++) {
+ HotSpotResolvedJavaMethod method = data.readMethod(position, getMethodOffset(i));
+ if (method != null) {
+ methods[entries] = method;
+ long count = data.readUnsignedInt(position, getMethodCountOffset(i));
+ totalCount += count;
+ counts[entries] = count;
+
+ entries++;
+ }
+ }
+
+ totalCount += getMethodsNotRecordedExecutionCount(data, position);
+ return new RawItemProfile<>(entries, methods, counts, totalCount);
+ }
+
+ private static JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
+ if (profile.entries <= 0 || profile.totalCount <= 0) {
+ return null;
+ }
+
+ ProfiledMethod[] pmethods = new ProfiledMethod[profile.entries];
+ double totalProbability = 0.0;
+ for (int i = 0; i < profile.entries; i++) {
+ double p = profile.counts[i];
+ p = p / profile.totalCount;
+ totalProbability += p;
+ pmethods[i] = new ProfiledMethod(profile.items[i], p);
+ }
+
+ Arrays.sort(pmethods);
+
+ double notRecordedMethodProbability = profile.entries < config.methodProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+ assert notRecordedMethodProbability == 0 || profile.entries == config.methodProfileWidth;
+ return new JavaMethodProfile(notRecordedMethodProbability, pmethods);
+ }
+
+ private static int getMethodOffset(int row) {
+ return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
+ }
+
+ private static int getMethodCountOffset(int row) {
+ return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ RawItemProfile<ResolvedJavaMethod> profile = getRawMethodProfile(data, pos);
+ super.appendTo(sb.append(format("exception_seen(%s) ", getExceptionSeen(data, pos))), data, pos).append(format("%nmethod_entries(%d)", profile.entries));
+ for (int i = 0; i < profile.entries; i++) {
+ long count = profile.counts[i];
+ sb.append(format("%n %s (%d, %4.2f)", profile.items[i].format("%H.%n(%p)"), count, (double) count / profile.totalCount));
+ }
+ return sb;
+ }
+ }
+
+ private static class RetData extends CounterData {
+
+ private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
+ private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
+
+ public RetData() {
+ super(Tag.RetData, RET_DATA_SIZE);
+ }
+ }
+
+ private static class BranchData extends JumpData {
+
+ private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
+ private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2);
+
+ public BranchData() {
+ super(Tag.BranchData, BRANCH_DATA_SIZE);
+ }
+
+ @Override
+ public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+ long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
+ long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+ long total = takenCount + notTakenCount;
+
+ return total <= 0 ? -1 : takenCount / (double) total;
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+ return truncateLongToInt(count);
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
+ long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
+ double takenProbability = getBranchTakenProbability(data, pos);
+ return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
+ }
+ }
+
+ private static class ArrayData extends AbstractMethodData {
+
+ private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0);
+ protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1);
+
+ public ArrayData(Tag tag, int staticSize) {
+ super(tag, staticSize);
+ }
+
+ @Override
+ protected int getDynamicSize(HotSpotMethodData data, int position) {
+ return cellsToBytes(getLength(data, position));
+ }
+
+ protected static int getLength(HotSpotMethodData data, int position) {
+ return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ return sb.append(format("length(%d)", getLength(data, pos)));
+ }
+ }
+
+ private static class MultiBranchData extends ArrayData {
+
+ private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
+ private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2;
+ private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
+ private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
+ private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
+
+ public MultiBranchData() {
+ super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
+ }
+
+ @Override
+ public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+ int arrayLength = getLength(data, position);
+ assert arrayLength > 0 : "switch must have at least the default case";
+ assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+
+ int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+ long totalCount = 0;
+ double[] result = new double[length];
+
+ // default case is first in HotSpot but last for the compiler
+ long count = readCount(data, position, 0);
+ totalCount += count;
+ result[length - 1] = count;
+
+ for (int i = 1; i < length; i++) {
+ count = readCount(data, position, i);
+ totalCount += count;
+ result[i - 1] = count;
+ }
+
+ if (totalCount <= 0) {
+ return null;
+ } else {
+ for (int i = 0; i < length; i++) {
+ result[i] = result[i] / totalCount;
+ }
+ return result;
+ }
+ }
+
+ private static long readCount(HotSpotMethodData data, int position, int i) {
+ int offset;
+ long count;
+ offset = getCountOffset(i);
+ count = data.readUnsignedInt(position, offset);
+ return count;
+ }
+
+ @Override
+ public int getExecutionCount(HotSpotMethodData data, int position) {
+ int arrayLength = getLength(data, position);
+ assert arrayLength > 0 : "switch must have at least the default case";
+ assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+
+ int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+ long totalCount = 0;
+ for (int i = 0; i < length; i++) {
+ int offset = getCountOffset(i);
+ totalCount += data.readUnsignedInt(position, offset);
+ }
+
+ return truncateLongToInt(totalCount);
+ }
+
+ private static int getCountOffset(int index) {
+ return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+ }
+
+ private static int getDisplacementOffset(int index) {
+ return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+ }
+
+ @Override
+ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+ int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+ sb.append(format("entries(%d)", entries));
+ for (int i = 0; i < entries; i++) {
+ sb.append(format("%n %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
+ }
+ return sb;
+ }
+ }
+
+ private static class ArgInfoData extends ArrayData {
+
+ private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
+
+ public ArgInfoData() {
+ super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
+ }
+ }
+
+ public void setCompiledIRSize(int size) {
+ UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
+ }
+
+ public int getCompiledIRSize() {
+ return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Interface for accessor objects that encapsulate the logic for accessing the different kinds of
+ * data in a HotSpot methodDataOop. This interface is similar to the interface {@link ProfilingInfo}
+ * , but most methods require a MethodDataObject and the exact position within the methodData.
+ */
+public interface HotSpotMethodDataAccessor {
+
+ /**
+ * {@code DataLayout} tag values.
+ */
+ enum Tag {
+ No(config().dataLayoutNoTag),
+ BitData(config().dataLayoutBitDataTag),
+ CounterData(config().dataLayoutCounterDataTag),
+ JumpData(config().dataLayoutJumpDataTag),
+ ReceiverTypeData(config().dataLayoutReceiverTypeDataTag),
+ VirtualCallData(config().dataLayoutVirtualCallDataTag),
+ RetData(config().dataLayoutRetDataTag),
+ BranchData(config().dataLayoutBranchDataTag),
+ MultiBranchData(config().dataLayoutMultiBranchDataTag),
+ ArgInfoData(config().dataLayoutArgInfoDataTag),
+ CallTypeData(config().dataLayoutCallTypeDataTag),
+ VirtualCallTypeData(config().dataLayoutVirtualCallTypeDataTag),
+ ParametersTypeData(config().dataLayoutParametersTypeDataTag),
+ SpeculativeTrapData(config().dataLayoutSpeculativeTrapDataTag);
+
+ private final int value;
+
+ private Tag(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ private static HotSpotVMConfig config() {
+ return runtime().getConfig();
+ }
+
+ public static Tag getEnum(int value) {
+ Tag result = values()[value];
+ assert value == result.value;
+ return result;
+ }
+ }
+
+ /**
+ * Returns the {@link Tag} stored in the LayoutData header.
+ *
+ * @return tag stored in the LayoutData header
+ */
+ Tag getTag();
+
+ /**
+ * Returns the BCI stored in the LayoutData header.
+ *
+ * @return An integer ≥ 0 and ≤ Short.MAX_VALUE, or -1 if not supported.
+ */
+ int getBCI(HotSpotMethodData data, int position);
+
+ /**
+ * Computes the size for the specific data at the given position.
+ *
+ * @return An integer > 0.
+ */
+ int getSize(HotSpotMethodData data, int position);
+
+ JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position);
+
+ JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position);
+
+ double getBranchTakenProbability(HotSpotMethodData data, int position);
+
+ double[] getSwitchProbabilities(HotSpotMethodData data, int position);
+
+ TriState getExceptionSeen(HotSpotMethodData data, int position);
+
+ TriState getNullSeen(HotSpotMethodData data, int position);
+
+ int getExecutionCount(HotSpotMethodData data, int position);
+
+ StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+
+public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider, HotSpotProxified {
+
+ private final ConstantReflectionProvider constantReflection;
+
+ public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
+ this.constantReflection = constantReflection;
+ }
+
+ /**
+ * Lazy initialization to break class initialization cycle. Field and method lookup is only
+ * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+ */
+ static class LazyInitialization {
+ static final ResolvedJavaField methodHandleFormField;
+ static final ResolvedJavaField lambdaFormVmentryField;
+ static final ResolvedJavaMethod lambdaFormCompileToBytecodeMethod;
+ static final HotSpotResolvedJavaField memberNameVmtargetField;
+
+ /**
+ * Search for an instance field with the given name in a class.
+ *
+ * @param className name of the class to search in
+ * @param fieldName name of the field to be searched
+ * @return resolved java field
+ * @throws ClassNotFoundException
+ */
+ private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException {
+ Class<?> clazz = Class.forName(className);
+ ResolvedJavaType type = runtime().fromClass(clazz);
+ ResolvedJavaField[] fields = type.getInstanceFields(false);
+ for (ResolvedJavaField field : fields) {
+ if (field.getName().equals(fieldName)) {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ private static ResolvedJavaMethod findMethodInClass(String className, String methodName) throws ClassNotFoundException {
+ Class<?> clazz = Class.forName(className);
+ HotSpotResolvedObjectTypeImpl type = fromObjectClass(clazz);
+ ResolvedJavaMethod result = null;
+ for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+ if (method.getName().equals(methodName)) {
+ assert result == null : "more than one method found: " + className + "." + methodName;
+ result = method;
+ }
+ }
+ assert result != null : "method not found: " + className + "." + methodName;
+ return result;
+ }
+
+ static {
+ try {
+ methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form");
+ lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry");
+ lambdaFormCompileToBytecodeMethod = findMethodInClass("java.lang.invoke.LambdaForm", "compileToBytecode");
+ memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass("java.lang.invoke.MemberName", "vmtarget");
+ } catch (Throwable ex) {
+ throw new JVMCIError(ex);
+ }
+ }
+ }
+
+ @Override
+ public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
+ int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
+ if (intrinsicId != 0) {
+ return getMethodHandleIntrinsic(intrinsicId);
+ }
+ return null;
+ }
+
+ public static IntrinsicMethod getMethodHandleIntrinsic(int intrinsicId) {
+ HotSpotVMConfig config = runtime().getConfig();
+ if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+ return IntrinsicMethod.INVOKE_BASIC;
+ } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+ return IntrinsicMethod.LINK_TO_INTERFACE;
+ } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+ return IntrinsicMethod.LINK_TO_SPECIAL;
+ } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+ return IntrinsicMethod.LINK_TO_STATIC;
+ } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+ return IntrinsicMethod.LINK_TO_VIRTUAL;
+ }
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration) {
+ if (methodHandle.isNull()) {
+ return null;
+ }
+
+ /* Load non-public field: LambdaForm MethodHandle.form */
+ JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+ if (lambdaForm.isNull()) {
+ return null;
+ }
+
+ JavaConstant memberName;
+ if (forceBytecodeGeneration) {
+ /* Invoke non-public method: MemberName LambdaForm.compileToBytecode() */
+ memberName = LazyInitialization.lambdaFormCompileToBytecodeMethod.invoke(lambdaForm, new JavaConstant[0]);
+ } else {
+ /* Load non-public field: MemberName LambdaForm.vmentry */
+ memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+ }
+ return getTargetMethod(memberName);
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
+ return getTargetMethod(memberName);
+ }
+
+ /**
+ * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName.
+ */
+ private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
+ if (memberName.isNull()) {
+ return null;
+ }
+
+ Object object = ((HotSpotObjectConstantImpl) memberName).object();
+ /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */
+ return runtime().compilerToVm.getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Implementation of {@link JavaMethod} for unresolved HotSpot methods.
+ */
+public final class HotSpotMethodUnresolved extends HotSpotMethod {
+
+ private final Signature signature;
+ protected JavaType holder;
+
+ public HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) {
+ super(name);
+ this.holder = holder;
+ this.signature = signature;
+ }
+
+ @Override
+ public Signature getSignature() {
+ return signature;
+ }
+
+ @Override
+ public JavaType getDeclaringClass() {
+ return holder;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || !(obj instanceof HotSpotMethodUnresolved)) {
+ return false;
+ }
+ HotSpotMethodUnresolved that = (HotSpotMethodUnresolved) obj;
+ return this.name.equals(that.name) && this.signature.equals(that.signature) && this.holder.equals(that.holder);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a
+ * weak reference to an instance of this class. This is necessary to keep the nmethod from being
+ * unloaded while the associated {@link HotSpotNmethod} instance is alive.
+ * <p>
+ * Note that there is no (current) way for the reference from an nmethod to a {@link HotSpotNmethod}
+ * instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as
+ * strong GC roots.
+ */
+public class HotSpotNmethod extends HotSpotInstalledCode {
+
+ /**
+ * This (indirect) Method* reference is safe since class redefinition preserves all methods
+ * associated with nmethods in the code cache.
+ */
+ private final HotSpotResolvedJavaMethod method;
+
+ private final boolean isDefault;
+ private final boolean isExternal;
+
+ public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
+ this(method, name, isDefault, false);
+ }
+
+ public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) {
+ super(name);
+ this.method = method;
+ this.isDefault = isDefault;
+ this.isExternal = isExternal;
+ }
+
+ public boolean isDefault() {
+ return isDefault;
+ }
+
+ public boolean isExternal() {
+ return isExternal;
+ }
+
+ public ResolvedJavaMethod getMethod() {
+ return method;
+ }
+
+ @Override
+ public void invalidate() {
+ runtime().getCompilerToVM().invalidateInstalledCode(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
+ }
+
+ protected boolean checkThreeObjectArgs() {
+ assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
+ assert method.getSignature().getParameterKind(0) == JavaKind.Object;
+ assert method.getSignature().getParameterKind(1) == JavaKind.Object;
+ assert !method.isStatic() || method.getSignature().getParameterKind(2) == JavaKind.Object;
+ return true;
+ }
+
+ private boolean checkArgs(Object... args) {
+ JavaType[] sig = method.toParameterTypes();
+ assert args.length == sig.length : method.format("%H.%n(%p): expected ") + sig.length + " args, got " + args.length;
+ for (int i = 0; i < sig.length; i++) {
+ Object arg = args[i];
+ if (arg == null) {
+ assert sig[i].getJavaKind() == JavaKind.Object : method.format("%H.%n(%p): expected arg ") + i + " to be Object, not " + sig[i];
+ } else if (sig[i].getJavaKind() != JavaKind.Object) {
+ assert sig[i].getJavaKind().toBoxedJavaClass() == arg.getClass() : method.format("%H.%n(%p): expected arg ") + i + " to be " + sig[i] + ", not " + arg.getClass();
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+ assert checkArgs(args);
+ assert !isExternal();
+ return runtime().getCompilerToVM().executeInstalledCode(args, this);
+ }
+
+ @Override
+ public long getStart() {
+ return isValid() ? super.getStart() : 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.invoke.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a constant non-{@code null} object reference, within the compiler and across the
+ * compiler/runtime interface.
+ */
+public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VMConstant {
+
+ JavaConstant compress();
+
+ JavaConstant uncompress();
+
+ /**
+ * Gets the resolved Java type of the object represented by this constant.
+ */
+ HotSpotResolvedObjectType getType();
+
+ /**
+ * Gets the result of {@link Class#getClassLoader()} for the {@link Class} object represented by
+ * this constant.
+ *
+ * @return {@code null} if this constant does not represent a {@link Class} object
+ */
+ JavaConstant getClassLoader();
+
+ /**
+ * Gets the {@linkplain System#identityHashCode(Object) identity} has code for the object
+ * represented by this constant.
+ */
+ int getIdentityHashCode();
+
+ /**
+ * Gets the result of {@link Class#getComponentType()} for the {@link Class} object represented
+ * by this constant.
+ *
+ * @return {@code null} if this constant does not represent a {@link Class} object
+ */
+ JavaConstant getComponentType();
+
+ /**
+ * Gets the result of {@link Class#getSuperclass()} for the {@link Class} object represented by
+ * this constant.
+ *
+ * @return {@code null} if this constant does not represent a {@link Class} object
+ */
+ JavaConstant getSuperclass();
+
+ /**
+ * Gets the result of {@link CallSite#getTarget()} for the {@link CallSite} object represented
+ * by this constant.
+ *
+ * @param assumptions used to register an assumption that the {@link CallSite}'s target does not
+ * change
+ * @return {@code null} if this constant does not represent a {@link CallSite} object
+ */
+ JavaConstant getCallSiteTarget(Assumptions assumptions);
+
+ /**
+ * Determines if this constant represents an {@linkplain String#intern() interned} string.
+ */
+ boolean isInternedString();
+
+ /**
+ * Gets the object represented by this constant represents if it is of a given type.
+ *
+ * @param type the expected type of the object represented by this constant. If the object is
+ * required to be of this type, then wrap the call to this method in
+ * {@link Objects#requireNonNull(Object)}.
+ * @return the object value represented by this constant if it is an
+ * {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+ * {@code null}
+ */
+ <T> T asObject(Class<T> type);
+
+ /**
+ * Gets the object represented by this constant represents if it is of a given type.
+ *
+ * @param type the expected type of the object represented by this constant. If the object is
+ * required to be of this type, then wrap the call to this method in
+ * {@link Objects#requireNonNull(Object)}.
+ * @return the object value represented by this constant if it is an
+ * {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+ * {@code null}
+ */
+ Object asObject(ResolvedJavaType type);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+
+import java.lang.invoke.*;
+
+import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a constant non-{@code null} object reference, within the compiler and across the
+ * compiler/runtime interface.
+ */
+public final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified {
+
+ public static JavaConstant forObject(Object object) {
+ return forObject(object, false);
+ }
+
+ static JavaConstant forObject(Object object, boolean compressed) {
+ if (object == null) {
+ return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
+ } else {
+ return new HotSpotObjectConstantImpl(object, compressed);
+ }
+ }
+
+ static JavaConstant forStableArray(Object object, int stableDimension, boolean isDefaultStable) {
+ if (object == null) {
+ return JavaConstant.NULL_POINTER;
+ } else {
+ assert object.getClass().isArray();
+ return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
+ }
+ }
+
+ public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
+ if (kind == JavaKind.Object) {
+ return HotSpotObjectConstantImpl.forObject(value);
+ } else {
+ return JavaConstant.forBoxedPrimitive(value);
+ }
+ }
+
+ static Object asBoxedValue(Constant constant) {
+ if (JavaConstant.isNull(constant)) {
+ return null;
+ } else if (constant instanceof HotSpotObjectConstantImpl) {
+ return ((HotSpotObjectConstantImpl) constant).object;
+ } else {
+ return ((JavaConstant) constant).asBoxedPrimitive();
+ }
+ }
+
+ private final Object object;
+ private final boolean compressed;
+ private final byte stableDimension;
+ private final boolean isDefaultStable;
+
+ private HotSpotObjectConstantImpl(Object object, boolean compressed, int stableDimension, boolean isDefaultStable) {
+ this.object = object;
+ this.compressed = compressed;
+ this.stableDimension = (byte) stableDimension;
+ this.isDefaultStable = isDefaultStable;
+ assert object != null;
+ assert stableDimension == 0 || (object != null && object.getClass().isArray());
+ assert stableDimension >= 0 && stableDimension <= 255;
+ assert !isDefaultStable || stableDimension > 0;
+ }
+
+ private HotSpotObjectConstantImpl(Object object, boolean compressed) {
+ this(object, compressed, 0, false);
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ /**
+ * Package-private accessor for the object represented by this constant.
+ */
+ Object object() {
+ return object;
+ }
+
+ /**
+ * Determines if the object represented by this constant is {@link Object#equals(Object) equal}
+ * to a given object.
+ */
+ public boolean isEqualTo(Object obj) {
+ return object.equals(obj);
+ }
+
+ /**
+ * Gets the class of the object represented by this constant.
+ */
+ public Class<?> getObjectClass() {
+ return object.getClass();
+ }
+
+ public boolean isCompressed() {
+ return compressed;
+ }
+
+ public JavaConstant compress() {
+ assert !compressed;
+ return new HotSpotObjectConstantImpl(object, true, stableDimension, isDefaultStable);
+ }
+
+ public JavaConstant uncompress() {
+ assert compressed;
+ return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
+ }
+
+ public HotSpotResolvedObjectType getType() {
+ return fromObjectClass(object.getClass());
+ }
+
+ public JavaConstant getClassLoader() {
+ if (object instanceof Class) {
+ /*
+ * This is an intrinsic for getClassLoader0, which occurs after any security checks. We
+ * can't call that directly so just call getClassLoader.
+ */
+ return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getClassLoader());
+ }
+ return null;
+ }
+
+ public int getIdentityHashCode() {
+ return System.identityHashCode(object);
+ }
+
+ public JavaConstant getComponentType() {
+ if (object instanceof Class) {
+ return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getComponentType());
+ }
+ return null;
+ }
+
+ public JavaConstant getSuperclass() {
+ if (object instanceof Class) {
+ return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getSuperclass());
+ }
+ return null;
+ }
+
+ public JavaConstant getCallSiteTarget(Assumptions assumptions) {
+ if (object instanceof CallSite) {
+ CallSite callSite = (CallSite) object;
+ MethodHandle target = callSite.getTarget();
+ if (!(callSite instanceof ConstantCallSite)) {
+ if (assumptions == null) {
+ return null;
+ }
+ assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
+ }
+ return HotSpotObjectConstantImpl.forObject(target);
+ }
+ return null;
+ }
+
+ @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
+ public boolean isInternedString() {
+ if (object instanceof String) {
+ String s = (String) object;
+ return s.intern() == s;
+ }
+ return false;
+ }
+
+ public <T> T asObject(Class<T> type) {
+ if (type.isInstance(object)) {
+ return type.cast(object);
+ }
+ return null;
+ }
+
+ public Object asObject(ResolvedJavaType type) {
+ if (type.isInstance(this)) {
+ return object;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isNull() {
+ return false;
+ }
+
+ @Override
+ public boolean isDefaultForKind() {
+ return false;
+ }
+
+ @Override
+ public Object asBoxedPrimitive() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int asInt() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public boolean asBoolean() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public long asLong() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public float asFloat() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public double asDouble() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(object);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ } else if (o instanceof HotSpotObjectConstantImpl) {
+ HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
+ return object == other.object && compressed == other.compressed && stableDimension == other.stableDimension && isDefaultStable == other.isDefaultStable;
+ }
+ return false;
+ }
+
+ @Override
+ public String toValueString() {
+ if (object instanceof String) {
+ return "\"" + (String) object + "\"";
+ } else {
+ return JavaKind.Object.format(object);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
+ }
+
+ /**
+ * Number of stable dimensions if this constant is a stable array.
+ */
+ public int getStableDimension() {
+ return stableDimension & 0xff;
+ }
+
+ /**
+ * Returns {@code true} if this is a stable array constant and its elements should be considered
+ * as stable regardless of whether they are default values.
+ */
+ public boolean isDefaultStable() {
+ return isDefaultStable;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+public class HotSpotOopMap {
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int offset;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int count;
+ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] data;
+
+ public byte[] data() {
+ return data;
+ }
+
+ public int count() {
+ return count;
+ }
+
+ public int offset() {
+ return offset;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+public final class HotSpotProfilingInfo implements ProfilingInfo, HotSpotProxified {
+
+ // private static final DebugMetric metricInsufficentSpace =
+ // Debug.metric("InsufficientSpaceForProfilingData");
+
+ private final HotSpotMethodData methodData;
+ private final HotSpotResolvedJavaMethod method;
+
+ private boolean isMature;
+ private int position;
+ private int hintPosition;
+ private int hintBCI;
+ private HotSpotMethodDataAccessor dataAccessor;
+
+ private boolean includeNormal;
+ private boolean includeOSR;
+
+ public HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
+ this.methodData = methodData;
+ this.method = method;
+ this.includeNormal = includeNormal;
+ this.includeOSR = includeOSR;
+ this.isMature = methodData.isProfileMature();
+ hintPosition = 0;
+ hintBCI = -1;
+ }
+
+ @Override
+ public int getCodeSize() {
+ return method.getCodeSize();
+ }
+
+ @Override
+ public JavaTypeProfile getTypeProfile(int bci) {
+ if (!isMature) {
+ return null;
+ }
+ findBCI(bci, false);
+ return dataAccessor.getTypeProfile(methodData, position);
+ }
+
+ @Override
+ public JavaMethodProfile getMethodProfile(int bci) {
+ if (!isMature) {
+ return null;
+ }
+ findBCI(bci, false);
+ return dataAccessor.getMethodProfile(methodData, position);
+ }
+
+ @Override
+ public double getBranchTakenProbability(int bci) {
+ if (!isMature) {
+ return -1;
+ }
+ findBCI(bci, false);
+ return dataAccessor.getBranchTakenProbability(methodData, position);
+ }
+
+ @Override
+ public double[] getSwitchProbabilities(int bci) {
+ if (!isMature) {
+ return null;
+ }
+ findBCI(bci, false);
+ return dataAccessor.getSwitchProbabilities(methodData, position);
+ }
+
+ @Override
+ public TriState getExceptionSeen(int bci) {
+ findBCI(bci, true);
+ return dataAccessor.getExceptionSeen(methodData, position);
+ }
+
+ @Override
+ public TriState getNullSeen(int bci) {
+ findBCI(bci, false);
+ return dataAccessor.getNullSeen(methodData, position);
+ }
+
+ @Override
+ public int getExecutionCount(int bci) {
+ if (!isMature) {
+ return -1;
+ }
+ findBCI(bci, false);
+ return dataAccessor.getExecutionCount(methodData, position);
+ }
+
+ @Override
+ public int getDeoptimizationCount(DeoptimizationReason reason) {
+ int count = 0;
+ if (includeNormal) {
+ count += methodData.getDeoptimizationCount(reason);
+ }
+ if (includeOSR) {
+ count += methodData.getOSRDeoptimizationCount(reason);
+ }
+ return count;
+ }
+
+ private void findBCI(int targetBCI, boolean searchExtraData) {
+ assert targetBCI >= 0 : "invalid BCI";
+
+ if (methodData.hasNormalData()) {
+ int currentPosition = targetBCI < hintBCI ? 0 : hintPosition;
+ HotSpotMethodDataAccessor currentAccessor;
+ while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) {
+ int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+ if (currentBCI == targetBCI) {
+ normalDataFound(currentAccessor, currentPosition, currentBCI);
+ return;
+ } else if (currentBCI > targetBCI) {
+ break;
+ }
+ currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
+ }
+ }
+
+ boolean exceptionPossiblyNotRecorded = false;
+ if (searchExtraData && methodData.hasExtraData()) {
+ int currentPosition = methodData.getExtraDataBeginOffset();
+ HotSpotMethodDataAccessor currentAccessor;
+ while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) {
+ int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+ if (currentBCI == targetBCI) {
+ extraDataFound(currentAccessor, currentPosition);
+ return;
+ }
+ currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
+ }
+
+ if (!methodData.isWithin(currentPosition)) {
+ exceptionPossiblyNotRecorded = true;
+ // metricInsufficentSpace.increment();
+ }
+ }
+
+ noDataFound(exceptionPossiblyNotRecorded);
+ }
+
+ private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) {
+ setCurrentData(data, pos);
+ this.hintPosition = position;
+ this.hintBCI = bci;
+ }
+
+ private void extraDataFound(HotSpotMethodDataAccessor data, int pos) {
+ setCurrentData(data, pos);
+ }
+
+ private void noDataFound(boolean exceptionPossiblyNotRecorded) {
+ HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded);
+ setCurrentData(accessor, -1);
+ }
+
+ private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) {
+ this.dataAccessor = dataAccessor;
+ this.position = position;
+ }
+
+ @Override
+ public boolean isMature() {
+ return isMature;
+ }
+
+ public void ignoreMature() {
+ isMature = true;
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotProfilingInfo<" + this.toString(null, "; ") + ">";
+ }
+
+ @Override
+ public void setMature() {
+ isMature = true;
+ }
+
+ /**
+ * {@code MethodData::_jvmci_ir_size} (currently) supports at most one JVMCI compiler IR type
+ * which will be determined by the first JVMCI compiler that calls
+ * {@link #setCompilerIRSize(Class, int)}.
+ */
+ private static volatile Class<?> supportedCompilerIRType;
+
+ @Override
+ public boolean setCompilerIRSize(Class<?> irType, int size) {
+ if (supportedCompilerIRType == null) {
+ synchronized (HotSpotProfilingInfo.class) {
+ if (supportedCompilerIRType == null) {
+ supportedCompilerIRType = irType;
+ }
+ }
+ }
+ if (supportedCompilerIRType != irType) {
+ return false;
+ }
+ methodData.setCompiledIRSize(size);
+ return true;
+ }
+
+ @Override
+ public int getCompilerIRSize(Class<?> irType) {
+ if (irType == supportedCompilerIRType) {
+ return methodData.getCompiledIRSize();
+ }
+ return -1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProxified.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Marker interface for classes whose values are proxied during replay compilation capture.
+ */
+public interface HotSpotProxified {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+
+public final class HotSpotReferenceMap extends ReferenceMap {
+
+ final Location[] objects;
+ final Location[] derivedBase;
+ final int[] sizeInBytes;
+ final int maxRegisterSize;
+
+ public HotSpotReferenceMap(Location[] objects, Location[] derivedBase, int[] sizeInBytes, int maxRegisterSize) {
+ this.objects = objects;
+ this.derivedBase = derivedBase;
+ this.sizeInBytes = sizeInBytes;
+ this.maxRegisterSize = maxRegisterSize;
+ }
+
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HotSpotReferenceMap) {
+ HotSpotReferenceMap that = (HotSpotReferenceMap) obj;
+ if (Arrays.equals(objects, that.objects)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return Arrays.toString(objects);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a field in a HotSpot type.
+ */
+public interface HotSpotResolvedJavaField extends ResolvedJavaField {
+
+ /**
+ * Determines if a given object contains this field.
+ *
+ * @return true iff this is a non-static field and its declaring class is assignable from
+ * {@code object}'s class
+ */
+ boolean isInObject(Object object);
+
+ int offset();
+
+ /**
+ * Checks if this field has the {@link Stable} annotation.
+ *
+ * @return true if field has {@link Stable} annotation, false otherwise
+ */
+ boolean isStable();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl.Options.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.options.*;
+
+/**
+ * Represents a field in a HotSpot type.
+ */
+public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified {
+
+ static class Options {
+ //@formatter:off
+ @Option(help = "Mark well-known stable fields as such.", type = OptionType.Debug)
+ public static final OptionValue<Boolean> ImplicitStableValues = new OptionValue<>(true);
+ //@formatter:on
+ }
+
+ private final HotSpotResolvedObjectTypeImpl holder;
+ private final String name;
+ private JavaType type;
+ private final int offset;
+
+ /**
+ * This value contains all flags as stored in the VM including internal ones.
+ */
+ private final int modifiers;
+ private final LocationIdentity locationIdentity = new FieldLocationIdentity(this);
+
+ public static class FieldLocationIdentity extends LocationIdentity {
+ HotSpotResolvedJavaField inner;
+
+ public FieldLocationIdentity(HotSpotResolvedJavaFieldImpl inner) {
+ this.inner = inner;
+ }
+
+ @Override
+ public boolean isImmutable() {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof FieldLocationIdentity) {
+ FieldLocationIdentity fieldLocationIdentity = (FieldLocationIdentity) obj;
+ return inner.equals(fieldLocationIdentity.inner);
+
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return inner.getName();
+ }
+ }
+
+ public HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) {
+ this.holder = holder;
+ this.name = name;
+ this.type = type;
+ assert offset != -1;
+ assert offset == (int) offset : "offset larger than int";
+ this.offset = (int) offset;
+ this.modifiers = modifiers;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HotSpotResolvedJavaField) {
+ HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj;
+ if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
+ return false;
+ } else if (this.holder.equals(that.holder)) {
+ assert this.name.equals(that.name) && this.type.equals(that.type);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public int getModifiers() {
+ return modifiers & ModifiersProvider.jvmFieldModifiers();
+ }
+
+ @Override
+ public boolean isInternal() {
+ return (modifiers & runtime().getConfig().jvmAccFieldInternal) != 0;
+ }
+
+ /**
+ * Determines if a given object contains this field.
+ *
+ * @return true iff this is a non-static field and its declaring class is assignable from
+ * {@code object}'s class
+ */
+ public boolean isInObject(Object object) {
+ if (isStatic()) {
+ return false;
+ }
+ return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass()));
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getDeclaringClass() {
+ return holder;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public JavaType getType() {
+ // Pull field into local variable to prevent a race causing
+ // a ClassCastException below
+ JavaType currentType = type;
+ if (currentType instanceof HotSpotUnresolvedJavaType) {
+ // Don't allow unresolved types to hang around forever
+ HotSpotUnresolvedJavaType unresolvedType = (HotSpotUnresolvedJavaType) currentType;
+ ResolvedJavaType resolved = unresolvedType.reresolve(holder);
+ if (resolved != null) {
+ type = resolved;
+ }
+ }
+ return type;
+ }
+
+ public int offset() {
+ return offset;
+ }
+
+ @Override
+ public String toString() {
+ return format("HotSpotField<%H.%n %t:") + offset + ">";
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ return (runtime().getConfig().syntheticFlag & modifiers) != 0;
+ }
+
+ /**
+ * Checks if this field has the {@link Stable} annotation.
+ *
+ * @return true if field has {@link Stable} annotation, false otherwise
+ */
+ public boolean isStable() {
+ if ((runtime().getConfig().jvmAccFieldStable & modifiers) != 0) {
+ return true;
+ }
+ assert getAnnotation(Stable.class) == null;
+ if (ImplicitStableValues.getValue() && isImplicitStableField()) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ Field javaField = toJava();
+ if (javaField != null) {
+ return javaField.getAnnotations();
+ }
+ return new Annotation[0];
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ Field javaField = toJava();
+ if (javaField != null) {
+ return javaField.getAnnotation(annotationClass);
+ }
+ return null;
+ }
+
+ private Field toJavaCache;
+
+ private Field toJava() {
+ if (toJavaCache != null) {
+ return toJavaCache;
+ }
+
+ if (isInternal()) {
+ return null;
+ }
+ try {
+ return toJavaCache = holder.mirror().getDeclaredField(name);
+ } catch (NoSuchFieldException | NoClassDefFoundError e) {
+ return null;
+ }
+ }
+
+ private boolean isArray() {
+ JavaType fieldType = getType();
+ return fieldType instanceof ResolvedJavaType && ((ResolvedJavaType) fieldType).isArray();
+ }
+
+ private boolean isImplicitStableField() {
+ if (isSynthetic()) {
+ if (isSyntheticImplicitStableField()) {
+ return true;
+ }
+ } else if (isWellKnownImplicitStableField()) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSyntheticImplicitStableField() {
+ assert this.isSynthetic();
+ if (isStatic() && isArray()) {
+ if (isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) {
+ // generated int[] field for EnumClass::values()
+ return true;
+ } else if (name.startsWith("$SwitchMap$") || name.startsWith("$SWITCH_TABLE$")) {
+ // javac and ecj generate a static field in an inner class for a switch on an enum
+ // named $SwitchMap$p$k$g$EnumClass and $SWITCH_TABLE$p$k$g$EnumClass, respectively
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isWellKnownImplicitStableField() {
+ return WellKnownImplicitStableField.test(this);
+ }
+
+ static class WellKnownImplicitStableField {
+ /**
+ * @return {@code true} if the field is a well-known stable field.
+ */
+ public static boolean test(HotSpotResolvedJavaField field) {
+ return field.equals(STRING_VALUE_FIELD);
+ }
+
+ private static final ResolvedJavaField STRING_VALUE_FIELD;
+ static {
+ try {
+ MetaAccessProvider metaAccess = runtime().getHostJVMCIBackend().getMetaAccess();
+ STRING_VALUE_FIELD = metaAccess.lookupJavaField(String.class.getDeclaredField("value"));
+ } catch (SecurityException | NoSuchFieldException e) {
+ throw new JVMCIError(e);
+ }
+ }
+ }
+
+ public LocationIdentity getLocationIdentity() {
+ return locationIdentity;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.reflect.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Implementation of {@link JavaMethod} for resolved HotSpot methods.
+ */
+public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
+
+ /**
+ * Returns true if this method has a {@code CallerSensitive} annotation.
+ *
+ * @return true if CallerSensitive annotation present, false otherwise
+ */
+ boolean isCallerSensitive();
+
+ HotSpotResolvedObjectType getDeclaringClass();
+
+ /**
+ * Returns true if this method has a {@code ForceInline} annotation.
+ *
+ * @return true if ForceInline annotation present, false otherwise
+ */
+ boolean isForceInline();
+
+ /**
+ * Returns true if this method has a {@code DontInline} annotation.
+ *
+ * @return true if DontInline annotation present, false otherwise
+ */
+ boolean isDontInline();
+
+ /**
+ * Manually adds a DontInline annotation to this method.
+ */
+ void setNotInlineable();
+
+ /**
+ * Returns true if this method is one of the special methods that is ignored by security stack
+ * walks.
+ *
+ * @return true if special method ignored by security stack walks, false otherwise
+ */
+ boolean ignoredBySecurityStackWalk();
+
+ ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver);
+
+ /**
+ * Returns whether this method has compiled code.
+ *
+ * @return true if this method has compiled code, false otherwise
+ */
+ boolean hasCompiledCode();
+
+ /**
+ * @param level
+ * @return true if the currently installed code was generated at {@code level}.
+ */
+ boolean hasCompiledCodeAtLevel(int level);
+
+ default boolean isDefault() {
+ if (isConstructor()) {
+ return false;
+ }
+ // Copied from java.lang.Method.isDefault()
+ int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
+ return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
+ }
+
+ /**
+ * Returns the offset of this method into the v-table. The method must have a v-table entry as
+ * indicated by {@link #isInVirtualMethodTable(ResolvedJavaType)}, otherwise an exception is
+ * thrown.
+ *
+ * @return the offset of this method into the v-table
+ */
+ int vtableEntryOffset(ResolvedJavaType resolved);
+
+ int intrinsicId();
+
+ /**
+ * Allocates a compile id for this method by asking the VM for one.
+ *
+ * @param entryBCI entry bci
+ * @return compile id
+ */
+ int allocateCompileId(int entryBCI);
+
+ boolean hasCodeAtLevel(int entryBCI, int level);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.Options.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.options.*;
+
+/**
+ * Implementation of {@link JavaMethod} for resolved HotSpot methods.
+ */
+public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MetaspaceWrapperObject {
+
+ public static class Options {
+ // @formatter:off
+ @Option(help = "", type = OptionType.Debug)
+ public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+ // @formatter:on
+ }
+
+ /**
+ * Reference to metaspace Method object.
+ */
+ private final long metaspaceMethod;
+
+ private final HotSpotResolvedObjectTypeImpl holder;
+ private final HotSpotConstantPool constantPool;
+ private final HotSpotSignature signature;
+ private HotSpotMethodData methodData;
+ private byte[] code;
+ private Member toJavaCache;
+
+ /**
+ * Gets the holder of a HotSpot metaspace method native object.
+ *
+ * @param metaspaceMethod a metaspace Method object
+ * @return the {@link ResolvedJavaType} corresponding to the holder of the
+ * {@code metaspaceMethod}
+ */
+ private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) {
+ HotSpotVMConfig config = runtime().getConfig();
+ final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset);
+ final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset);
+ return runtime().getCompilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
+ }
+
+ /**
+ * Gets the JVMCI mirror from a HotSpot method. The VM is responsible for ensuring that the
+ * Method* is kept alive for the duration of this call and the
+ * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+ *
+ * Called from the VM.
+ *
+ * @param metaspaceMethod a metaspace Method object
+ * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
+ */
+ @SuppressWarnings("unused")
+ private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) {
+ HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceMethod);
+ return holder.createMethod(metaspaceMethod);
+ }
+
+ HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
+ // It would be too much work to get the method name here so we fill it in later.
+ super(null);
+ this.metaspaceMethod = metaspaceMethod;
+ this.holder = holder;
+
+ HotSpotVMConfig config = runtime().getConfig();
+ final long constMethod = getConstMethod();
+
+ /*
+ * Get the constant pool from the metaspace method. Some methods (e.g. intrinsics for
+ * signature-polymorphic method handle methods) have their own constant pool instead of the
+ * one from their holder.
+ */
+ final long metaspaceConstantPool = UNSAFE.getAddress(constMethod + config.constMethodConstantsOffset);
+ if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) {
+ this.constantPool = holder.getConstantPool();
+ } else {
+ this.constantPool = runtime().getCompilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset);
+ }
+
+ final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset);
+ this.name = constantPool.lookupUtf8(nameIndex);
+
+ final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
+ this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
+ }
+
+ /**
+ * Returns a pointer to this method's constant method data structure (
+ * {@code Method::_constMethod}). This pointer isn't wrapped since it should be safe to use it
+ * within the context of this HotSpotResolvedJavaMethodImpl since the Method* and ConstMethod*
+ * are kept alive as a pair.
+ *
+ * @return pointer to this method's ConstMethod
+ */
+ private long getConstMethod() {
+ assert metaspaceMethod != 0;
+ return UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodConstMethodOffset);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HotSpotResolvedJavaMethodImpl) {
+ HotSpotResolvedJavaMethodImpl that = (HotSpotResolvedJavaMethodImpl) obj;
+ return that.metaspaceMethod == metaspaceMethod;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) metaspaceMethod;
+ }
+
+ /**
+ * Returns this method's flags ({@code Method::_flags}).
+ *
+ * @return flags of this method
+ */
+ private int getFlags() {
+ return UNSAFE.getByte(metaspaceMethod + runtime().getConfig().methodFlagsOffset);
+ }
+
+ /**
+ * Returns this method's constant method flags ({@code ConstMethod::_flags}).
+ *
+ * @return flags of this method's ConstMethod
+ */
+ private int getConstMethodFlags() {
+ return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodFlagsOffset);
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getDeclaringClass() {
+ return holder;
+ }
+
+ /**
+ * Gets the address of the C++ Method object for this method.
+ */
+ public JavaConstant getMetaspaceMethodConstant() {
+ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this, false);
+ }
+
+ public long getMetaspaceMethod() {
+ return metaspaceMethod;
+ }
+
+ public long getMetaspacePointer() {
+ return getMetaspaceMethod();
+ }
+
+ @Override
+ public JavaConstant getEncoding() {
+ return getMetaspaceMethodConstant();
+ }
+
+ /**
+ * Gets the complete set of modifiers for this method which includes the JVM specification
+ * modifiers as well as the HotSpot internal modifiers.
+ */
+ public int getAllModifiers() {
+ return UNSAFE.getInt(metaspaceMethod + runtime().getConfig().methodAccessFlagsOffset);
+ }
+
+ @Override
+ public int getModifiers() {
+ return getAllModifiers() & ModifiersProvider.jvmMethodModifiers();
+ }
+
+ @Override
+ public boolean canBeStaticallyBound() {
+ return (isFinal() || isPrivate() || isStatic() || holder.isLeaf()) && isConcrete();
+ }
+
+ @Override
+ public byte[] getCode() {
+ if (getCodeSize() == 0) {
+ return null;
+ }
+ if (code == null && holder.isLinked()) {
+ code = runtime().getCompilerToVM().getBytecode(this);
+ assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length;
+ }
+ return code;
+ }
+
+ @Override
+ public int getCodeSize() {
+ return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodCodeSizeOffset);
+ }
+
+ @Override
+ public ExceptionHandler[] getExceptionHandlers() {
+ final boolean hasExceptionTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasExceptionTable) != 0;
+ if (!hasExceptionTable) {
+ return new ExceptionHandler[0];
+ }
+
+ HotSpotVMConfig config = runtime().getConfig();
+ final int exceptionTableLength = runtime().getCompilerToVM().getExceptionTableLength(this);
+ ExceptionHandler[] handlers = new ExceptionHandler[exceptionTableLength];
+ long exceptionTableElement = runtime().getCompilerToVM().getExceptionTableStart(this);
+
+ for (int i = 0; i < exceptionTableLength; i++) {
+ final int startPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementStartPcOffset);
+ final int endPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementEndPcOffset);
+ final int handlerPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementHandlerPcOffset);
+ int catchTypeIndex = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementCatchTypeIndexOffset);
+
+ JavaType catchType;
+ if (catchTypeIndex == 0) {
+ catchType = null;
+ } else {
+ final int opcode = -1; // opcode is not used
+ catchType = constantPool.lookupType(catchTypeIndex, opcode);
+
+ // Check for Throwable which catches everything.
+ if (catchType instanceof HotSpotResolvedObjectTypeImpl) {
+ HotSpotResolvedObjectTypeImpl resolvedType = (HotSpotResolvedObjectTypeImpl) catchType;
+ if (resolvedType.mirror() == Throwable.class) {
+ catchTypeIndex = 0;
+ catchType = null;
+ }
+ }
+ }
+ handlers[i] = new ExceptionHandler(startPc, endPc, handlerPc, catchTypeIndex, catchType);
+
+ // Go to the next ExceptionTableElement
+ exceptionTableElement += config.exceptionTableElementSize;
+ }
+
+ return handlers;
+ }
+
+ /**
+ * Returns true if this method has a {@code CallerSensitive} annotation.
+ *
+ * @return true if CallerSensitive annotation present, false otherwise
+ */
+ public boolean isCallerSensitive() {
+ return (getFlags() & runtime().getConfig().methodFlagsCallerSensitive) != 0;
+ }
+
+ /**
+ * Returns true if this method has a {@code ForceInline} annotation.
+ *
+ * @return true if ForceInline annotation present, false otherwise
+ */
+ public boolean isForceInline() {
+ return (getFlags() & runtime().getConfig().methodFlagsForceInline) != 0;
+ }
+
+ /**
+ * Returns true if this method has a {@code DontInline} annotation.
+ *
+ * @return true if DontInline annotation present, false otherwise
+ */
+ public boolean isDontInline() {
+ return (getFlags() & runtime().getConfig().methodFlagsDontInline) != 0;
+ }
+
+ /**
+ * Manually adds a DontInline annotation to this method.
+ */
+ public void setNotInlineable() {
+ runtime().getCompilerToVM().doNotInlineOrCompile(this);
+ }
+
+ /**
+ * Returns true if this method is one of the special methods that is ignored by security stack
+ * walks.
+ *
+ * @return true if special method ignored by security stack walks, false otherwise
+ */
+ public boolean ignoredBySecurityStackWalk() {
+ return runtime().getCompilerToVM().methodIsIgnoredBySecurityStackWalk(this);
+ }
+
+ @Override
+ public boolean isClassInitializer() {
+ return "<clinit>".equals(name) && isStatic();
+ }
+
+ @Override
+ public boolean isConstructor() {
+ return "<init>".equals(name) && !isStatic();
+ }
+
+ @Override
+ public int getMaxLocals() {
+ if (isAbstract() || isNative()) {
+ return 0;
+ }
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getChar(getConstMethod() + config.methodMaxLocalsOffset);
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ if (isAbstract() || isNative()) {
+ return 0;
+ }
+ HotSpotVMConfig config = runtime().getConfig();
+ return config.extraStackEntries + UNSAFE.getChar(getConstMethod() + config.constMethodMaxStackOffset);
+ }
+
+ @Override
+ public StackTraceElement asStackTraceElement(int bci) {
+ if (bci < 0 || bci >= getCodeSize()) {
+ // HotSpot code can only construct stack trace elements for valid bcis
+ StackTraceElement ste = runtime().getCompilerToVM().getStackTraceElement(this, 0);
+ return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1);
+ }
+ return runtime().getCompilerToVM().getStackTraceElement(this, bci);
+ }
+
+ public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) {
+ if (receiver.isInterface()) {
+ // Cannot trust interfaces. Because of:
+ // interface I { void foo(); }
+ // class A { public void foo() {} }
+ // class B extends A implements I { }
+ // class C extends B { public void foo() { } }
+ // class D extends B { }
+ // Would lead to identify C.foo() as the unique concrete method for I.foo() without
+ // seeing A.foo().
+ return null;
+ }
+ return runtime().getCompilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this);
+ }
+
+ @Override
+ public HotSpotSignature getSignature() {
+ return signature;
+ }
+
+ /**
+ * Gets the value of {@code Method::_code}.
+ *
+ * @return the value of {@code Method::_code}
+ */
+ private long getCompiledCode() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset);
+ }
+
+ /**
+ * Returns whether this method has compiled code.
+ *
+ * @return true if this method has compiled code, false otherwise
+ */
+ public boolean hasCompiledCode() {
+ return getCompiledCode() != 0L;
+ }
+
+ /**
+ * @param level
+ * @return true if the currently installed code was generated at {@code level}.
+ */
+ public boolean hasCompiledCodeAtLevel(int level) {
+ long compiledCode = getCompiledCode();
+ if (compiledCode != 0) {
+ return UNSAFE.getInt(compiledCode + runtime().getConfig().nmethodCompLevelOffset) == level;
+ }
+ return false;
+ }
+
+ private static final String TraceMethodDataFilter = System.getProperty("jvmci.traceMethodDataFilter");
+
+ @Override
+ public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
+ ProfilingInfo info;
+
+ if (UseProfilingInformation.getValue() && methodData == null) {
+ long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodDataOffset);
+ if (metaspaceMethodData != 0) {
+ methodData = new HotSpotMethodData(metaspaceMethodData, this);
+ if (TraceMethodDataFilter != null && this.format("%H.%n").contains(TraceMethodDataFilter)) {
+ System.out.println("Raw method data for " + this.format("%H.%n(%p)") + ":");
+ System.out.println(methodData.toString());
+ }
+ }
+ }
+
+ if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) {
+ // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in
+ // case of a deoptimization.
+ info = DefaultProfilingInfo.get(TriState.FALSE);
+ } else {
+ info = new HotSpotProfilingInfo(methodData, this, includeNormal, includeOSR);
+ }
+ return info;
+ }
+
+ @Override
+ public void reprofile() {
+ runtime().getCompilerToVM().reprofile(this);
+ }
+
+ @Override
+ public ConstantPool getConstantPool() {
+ return constantPool;
+ }
+
+ @Override
+ public Annotation[][] getParameterAnnotations() {
+ if (isConstructor()) {
+ Constructor<?> javaConstructor = toJavaConstructor();
+ return javaConstructor == null ? null : javaConstructor.getParameterAnnotations();
+ }
+ Method javaMethod = toJava();
+ return javaMethod == null ? null : javaMethod.getParameterAnnotations();
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ if (isConstructor()) {
+ Constructor<?> javaConstructor = toJavaConstructor();
+ return javaConstructor == null ? new Annotation[0] : javaConstructor.getAnnotations();
+ }
+ Method javaMethod = toJava();
+ return javaMethod == null ? new Annotation[0] : javaMethod.getAnnotations();
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ if (isConstructor()) {
+ Constructor<?> javaConstructor = toJavaConstructor();
+ return javaConstructor == null ? null : javaConstructor.getAnnotation(annotationClass);
+ }
+ Method javaMethod = toJava();
+ return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
+ }
+
+ public boolean isDefault() {
+ if (isConstructor()) {
+ return false;
+ }
+ // Copied from java.lang.Method.isDefault()
+ int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
+ return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
+ }
+
+ @Override
+ public Type[] getGenericParameterTypes() {
+ if (isConstructor()) {
+ Constructor<?> javaConstructor = toJavaConstructor();
+ return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes();
+ }
+ Method javaMethod = toJava();
+ return javaMethod == null ? null : javaMethod.getGenericParameterTypes();
+ }
+
+ public Class<?>[] signatureToTypes() {
+ Signature sig = getSignature();
+ int count = sig.getParameterCount(false);
+ Class<?>[] result = new Class<?>[count];
+ for (int i = 0; i < result.length; ++i) {
+ JavaType parameterType = sig.getParameterType(i, holder);
+ HotSpotResolvedJavaType resolvedParameterType = (HotSpotResolvedJavaType) parameterType.resolve(holder);
+ result[i] = resolvedParameterType.mirror();
+ }
+ return result;
+ }
+
+ private Method toJava() {
+ if (toJavaCache != null) {
+ return (Method) toJavaCache;
+ }
+ try {
+ Method result = holder.mirror().getDeclaredMethod(name, signatureToTypes());
+ toJavaCache = result;
+ return result;
+ } catch (NoSuchMethodException | NoClassDefFoundError e) {
+ return null;
+ }
+ }
+
+ private Constructor<?> toJavaConstructor() {
+ if (toJavaCache != null) {
+ return (Constructor<?>) toJavaCache;
+ }
+ try {
+ Constructor<?> result = holder.mirror().getDeclaredConstructor(signatureToTypes());
+ toJavaCache = result;
+ return result;
+ } catch (NoSuchMethodException | NoClassDefFoundError e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean canBeInlined() {
+ if (isDontInline()) {
+ return false;
+ }
+ return runtime().getCompilerToVM().canInlineMethod(this);
+ }
+
+ @Override
+ public boolean shouldBeInlined() {
+ if (isForceInline()) {
+ return true;
+ }
+ return runtime().getCompilerToVM().shouldInlineMethod(this);
+ }
+
+ @Override
+ public LineNumberTable getLineNumberTable() {
+ final boolean hasLineNumberTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLineNumberTable) != 0;
+ if (!hasLineNumberTable) {
+ return null;
+ }
+
+ long[] values = runtime().getCompilerToVM().getLineNumberTable(this);
+ if (values == null || values.length == 0) {
+ // Empty table so treat is as non-existent
+ return null;
+ }
+ assert values.length % 2 == 0;
+ int[] bci = new int[values.length / 2];
+ int[] line = new int[values.length / 2];
+
+ for (int i = 0; i < values.length / 2; i++) {
+ bci[i] = (int) values[i * 2];
+ line[i] = (int) values[i * 2 + 1];
+ }
+
+ return new LineNumberTableImpl(line, bci);
+ }
+
+ @Override
+ public LocalVariableTable getLocalVariableTable() {
+ final boolean hasLocalVariableTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLocalVariableTable) != 0;
+ if (!hasLocalVariableTable) {
+ return null;
+ }
+
+ HotSpotVMConfig config = runtime().getConfig();
+ long localVariableTableElement = runtime().getCompilerToVM().getLocalVariableTableStart(this);
+ final int localVariableTableLength = runtime().getCompilerToVM().getLocalVariableTableLength(this);
+ Local[] locals = new Local[localVariableTableLength];
+
+ for (int i = 0; i < localVariableTableLength; i++) {
+ final int startBci = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementStartBciOffset);
+ final int endBci = startBci + UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementLengthOffset);
+ final int nameCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementNameCpIndexOffset);
+ final int typeCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementDescriptorCpIndexOffset);
+ final int slot = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementSlotOffset);
+
+ String localName = getConstantPool().lookupUtf8(nameCpIndex);
+ String localType = getConstantPool().lookupUtf8(typeCpIndex);
+
+ locals[i] = new LocalImpl(localName, runtime().lookupType(localType, holder, false), startBci, endBci, slot);
+
+ // Go to the next LocalVariableTableElement
+ localVariableTableElement += config.localVariableTableElementSize;
+ }
+
+ return new LocalVariableTableImpl(locals);
+ }
+
+ /**
+ * Returns the offset of this method into the v-table. The method must have a v-table entry as
+ * indicated by {@link #isInVirtualMethodTable(ResolvedJavaType)}, otherwise an exception is
+ * thrown.
+ *
+ * @return the offset of this method into the v-table
+ */
+ public int vtableEntryOffset(ResolvedJavaType resolved) {
+ if (!isInVirtualMethodTable(resolved)) {
+ throw new JVMCIError("%s does not have a vtable entry in type %s", this, resolved);
+ }
+ HotSpotVMConfig config = runtime().getConfig();
+ final int vtableIndex = getVtableIndex((HotSpotResolvedObjectTypeImpl) resolved);
+ return config.instanceKlassVtableStartOffset() + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
+ }
+
+ @Override
+ public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
+ if (resolved instanceof HotSpotResolvedObjectTypeImpl) {
+ HotSpotResolvedObjectTypeImpl hotspotResolved = (HotSpotResolvedObjectTypeImpl) resolved;
+ int vtableIndex = getVtableIndex(hotspotResolved);
+ return vtableIndex >= 0 && vtableIndex < hotspotResolved.getVtableLength();
+ }
+ return false;
+ }
+
+ private int getVtableIndex(HotSpotResolvedObjectTypeImpl resolved) {
+ if (!holder.isLinked()) {
+ return runtime().getConfig().invalidVtableIndex;
+ }
+ if (holder.isInterface()) {
+ if (resolved.isInterface()) {
+ return runtime().getConfig().invalidVtableIndex;
+ }
+ return getVtableIndexForInterfaceMethod(resolved);
+ }
+ return getVtableIndex();
+ }
+
+ /**
+ * Returns this method's virtual table index.
+ *
+ * @return virtual table index
+ */
+ private int getVtableIndex() {
+ assert!holder.isInterface();
+ HotSpotVMConfig config = runtime().getConfig();
+ int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+ assert result >= config.nonvirtualVtableIndex : "must be linked";
+ return result;
+ }
+
+ private int getVtableIndexForInterfaceMethod(ResolvedJavaType resolved) {
+ HotSpotResolvedObjectTypeImpl hotspotType = (HotSpotResolvedObjectTypeImpl) resolved;
+ return runtime().getCompilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
+ }
+
+ /**
+ * The {@link SpeculationLog} for methods compiled by JVMCI hang off this per-declaring-type
+ * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
+ * never moves and b) we never read from it.
+ * <p>
+ * One implication is that we will preserve {@link SpeculationLog}s for methods that have been
+ * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot
+ * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
+ * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
+ */
+ private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<Map<Long, SpeculationLog>>() {
+ @Override
+ protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
+ return new HashMap<>(4);
+ }
+ };
+
+ public SpeculationLog getSpeculationLog() {
+ Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror());
+ synchronized (map) {
+ SpeculationLog log = map.get(this.metaspaceMethod);
+ if (log == null) {
+ log = new HotSpotSpeculationLog();
+ map.put(metaspaceMethod, log);
+ }
+ return log;
+ }
+ }
+
+ public int intrinsicId() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset);
+ }
+
+ @Override
+ public JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments) {
+ assert!isConstructor();
+ Method javaMethod = toJava();
+ javaMethod.setAccessible(true);
+
+ Object[] objArguments = new Object[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ objArguments[i] = HotSpotObjectConstantImpl.asBoxedValue(arguments[i]);
+ }
+ Object objReceiver = receiver != null && !receiver.isNull() ? ((HotSpotObjectConstantImpl) receiver).object() : null;
+
+ try {
+ Object objResult = javaMethod.invoke(objReceiver, objArguments);
+ return javaMethod.getReturnType() == void.class ? null : HotSpotObjectConstantImpl.forBoxedValue(getSignature().getReturnKind(), objResult);
+
+ } catch (IllegalAccessException | InvocationTargetException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ /**
+ * Allocates a compile id for this method by asking the VM for one.
+ *
+ * @param entryBCI entry bci
+ * @return compile id
+ */
+ public int allocateCompileId(int entryBCI) {
+ return runtime().getCompilerToVM().allocateCompileId(this, entryBCI);
+ }
+
+ public boolean hasCodeAtLevel(int entryBCI, int level) {
+ if (entryBCI == runtime().getConfig().invocationEntryBci) {
+ return hasCompiledCodeAtLevel(level);
+ }
+ return runtime().getCompilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2013, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
+
+ public HotSpotResolvedJavaType(String name) {
+ super(name);
+ }
+
+ public abstract Class<?> mirror();
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (!(obj instanceof HotSpotResolvedJavaType)) {
+ return false;
+ }
+ HotSpotResolvedJavaType that = (HotSpotResolvedJavaType) obj;
+ return this.mirror().equals(that.mirror());
+ }
+
+ @Override
+ public final int hashCode() {
+ return getName().hashCode();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.*;
+
+/**
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ */
+public interface HotSpotResolvedObjectType extends ResolvedJavaType {
+
+ HotSpotResolvedObjectType getArrayClass();
+
+ ResolvedJavaType getComponentType();
+
+ AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
+
+ HotSpotResolvedObjectType getSuperclass();
+
+ HotSpotResolvedObjectType[] getInterfaces();
+
+ HotSpotResolvedObjectType getSupertype();
+
+ HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType);
+
+ HotSpotResolvedObjectType asExactType();
+
+ default boolean isPrimitive() {
+ return false;
+ }
+
+ default JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ ConstantPool getConstantPool();
+
+ /**
+ * Gets the instance size of this type. If an instance of this type cannot be fast path
+ * allocated, then the returned value is negative (its absolute value gives the size). Must not
+ * be called if this is an array or interface type.
+ */
+ int instanceSize();
+
+ int getVtableLength();
+
+ @Override
+ AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
+
+ /**
+ * Performs a fast-path check that this type is resolved in the context of a given accessing
+ * class. A negative result does not mean this type is not resolved with respect to
+ * {@code accessingClass}. That can only be determined by
+ * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
+ * re-resolving} the type.
+ */
+ boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass);
+
+ /**
+ * Gets the metaspace Klass boxed in a {@link JavaConstant}.
+ */
+ Constant klass();
+
+ boolean isPrimaryType();
+
+ int superCheckOffset();
+
+ long prototypeMarkWord();
+
+ int layoutHelper();
+
+ HotSpotResolvedObjectType getEnclosingType();
+
+ ResolvedJavaMethod getClassInitializer();
+
+ ResolvedJavaField createField(String name, JavaType type, long offset, int modifiers);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,889 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.Objects.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.nio.*;
+import java.util.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.*;
+
+/**
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ */
+public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject {
+
+ /**
+ * The Java class this type represents.
+ */
+ private final Class<?> javaClass;
+ private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
+ private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCache;
+ private HotSpotResolvedJavaField[] instanceFields;
+ private HotSpotResolvedObjectTypeImpl[] interfaces;
+ private HotSpotConstantPool constantPool;
+ final HotSpotJVMCIMetaAccessContext context;
+ private HotSpotResolvedObjectType arrayOfType;
+
+ /**
+ * Gets the JVMCI mirror for a {@link Class} object.
+ *
+ * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
+ */
+ public static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
+ return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
+ }
+
+ /**
+ * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
+ * underlying Klass*, it is used instead of the raw Klass*.
+ *
+ * Called from the VM.
+ *
+ * @param javaClass a {@link Class} object
+ * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+ */
+ @SuppressWarnings("unused")
+ private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
+ return fromObjectClass(javaClass);
+ }
+
+ /**
+ * Creates the JVMCI mirror for a {@link Class} object.
+ *
+ * <p>
+ * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
+ * {@link Class} type. Use {@link #fromObjectClass(Class)} or {@link #fromMetaspace(Class)}
+ * instead.
+ * </p>
+ *
+ * @param javaClass the Class to create the mirror for
+ * @param context
+ */
+ HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
+ super(getSignatureName(javaClass));
+ this.javaClass = javaClass;
+ this.context = context;
+ assert getName().charAt(0) != '[' || isArray() : getName();
+ }
+
+ /**
+ * Returns the name of this type as it would appear in a signature.
+ */
+ private static String getSignatureName(Class<?> javaClass) {
+ if (javaClass.isArray()) {
+ return javaClass.getName().replace('.', '/');
+ }
+ return "L" + javaClass.getName().replace('.', '/') + ";";
+ }
+
+ /**
+ * Gets the metaspace Klass for this type.
+ */
+ public long getMetaspaceKlass() {
+ if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
+ return UNSAFE.getLong(javaClass, (long) runtime().getConfig().klassOffset);
+ }
+ return UNSAFE.getInt(javaClass, (long) runtime().getConfig().klassOffset) & 0xFFFFFFFFL;
+ }
+
+ public long getMetaspacePointer() {
+ return getMetaspaceKlass();
+ }
+
+ @Override
+ public int getModifiers() {
+ if (isArray()) {
+ return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
+ } else {
+ return getAccessFlags() & ModifiersProvider.jvmClassModifiers();
+ }
+ }
+
+ public int getAccessFlags() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
+ }
+
+ @Override
+ public HotSpotResolvedObjectType getArrayClass() {
+ if (arrayOfType == null) {
+ arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
+ }
+ return arrayOfType;
+ }
+
+ @Override
+ public ResolvedJavaType getComponentType() {
+ Class<?> javaComponentType = mirror().getComponentType();
+ return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
+ }
+
+ @Override
+ public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+ HotSpotVMConfig config = runtime().getConfig();
+ if (isArray()) {
+ return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null;
+ } else if (isInterface()) {
+ HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
+ /*
+ * If the implementor field contains itself that indicates that the interface has more
+ * than one implementors (see: InstanceKlass::add_implementor).
+ */
+ if (implementor == null || implementor.equals(this)) {
+ return null;
+ }
+
+ assert !implementor.isInterface();
+ if (implementor.isAbstract() || !implementor.isLeafClass()) {
+ AssumptionResult<ResolvedJavaType> leafConcreteSubtype = implementor.findLeafConcreteSubtype();
+ if (leafConcreteSubtype != null) {
+ assert !leafConcreteSubtype.getResult().equals(implementor);
+ AssumptionResult<ResolvedJavaType> newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor));
+ // Accumulate leaf assumptions and return the combined result.
+ newResult.add(leafConcreteSubtype);
+ return newResult;
+ }
+ return null;
+ }
+
+ return new AssumptionResult<>(implementor, new LeafType(implementor), new ConcreteSubtype(this, implementor));
+ } else {
+ HotSpotResolvedObjectTypeImpl type = this;
+ while (type.isAbstract()) {
+ HotSpotResolvedObjectTypeImpl subklass = type.getSubklass();
+ if (subklass == null || UNSAFE.getAddress(subklass.getMetaspaceKlass() + config.nextSiblingOffset) != 0) {
+ return null;
+ }
+ type = subklass;
+ }
+ if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
+ return null;
+ }
+ if (this.isAbstract()) {
+ return new AssumptionResult<>(type, new LeafType(type), new ConcreteSubtype(this, type));
+ } else {
+ assert this.equals(type);
+ return new AssumptionResult<>(type, new LeafType(type));
+ }
+ }
+ }
+
+ /**
+ * Returns if type {@code type} is a leaf class. This is the case if the
+ * {@code Klass::_subklass} field of the underlying class is zero.
+ *
+ * @return true if the type is a leaf class
+ */
+ private boolean isLeafClass() {
+ return getSubklass() == null;
+ }
+
+ /**
+ * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
+ * type {@code type}.
+ *
+ * @return value of the subklass field as metaspace klass pointer
+ */
+ private HotSpotResolvedObjectTypeImpl getSubklass() {
+ return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().subklassOffset, false);
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getSuperclass() {
+ Class<?> javaSuperclass = mirror().getSuperclass();
+ return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
+ if (interfaces == null) {
+ Class<?>[] javaInterfaces = mirror().getInterfaces();
+ HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
+ for (int i = 0; i < javaInterfaces.length; i++) {
+ result[i] = fromObjectClass(javaInterfaces[i]);
+ }
+ interfaces = result;
+ }
+ return interfaces;
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
+ if (!isInterface()) {
+ throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
+ }
+ return runtime().getCompilerToVM().getImplementor(this);
+ }
+
+ public HotSpotResolvedObjectTypeImpl getSupertype() {
+ if (isArray()) {
+ ResolvedJavaType componentType = getComponentType();
+ if (mirror() == Object[].class || componentType.isPrimitive()) {
+ return fromObjectClass(Object.class);
+ }
+ return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
+ }
+ if (isInterface()) {
+ return fromObjectClass(Object.class);
+ }
+ return getSuperclass();
+ }
+
+ @Override
+ public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
+ if (otherType.isPrimitive()) {
+ return null;
+ } else {
+ HotSpotResolvedObjectTypeImpl t1 = this;
+ HotSpotResolvedObjectTypeImpl t2 = (HotSpotResolvedObjectTypeImpl) otherType;
+ while (true) {
+ if (t1.isAssignableFrom(t2)) {
+ return t1;
+ }
+ if (t2.isAssignableFrom(t1)) {
+ return t2;
+ }
+ t1 = t1.getSupertype();
+ t2 = t2.getSupertype();
+ }
+ }
+ }
+
+ @Override
+ public HotSpotResolvedObjectType asExactType() {
+ return isLeaf() ? this : null;
+ }
+
+ @Override
+ public JavaConstant getJavaClass() {
+ return HotSpotObjectConstantImpl.forObject(mirror());
+ }
+
+ @Override
+ public JavaConstant getObjectHub() {
+ return klass();
+ }
+
+ @Override
+ public AssumptionResult<Boolean> hasFinalizableSubclass() {
+ assert !isArray();
+ if (!runtime().getCompilerToVM().hasFinalizableSubclass(this)) {
+ return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
+ }
+ return new AssumptionResult<>(true);
+ }
+
+ @Override
+ public boolean hasFinalizer() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return (getAccessFlags() & config.klassHasFinalizerFlag) != 0;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ @Override
+ public boolean isArray() {
+ return mirror().isArray();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isArray() ? true : getInitState() == runtime().getConfig().instanceKlassStateFullyInitialized;
+ }
+
+ @Override
+ public boolean isLinked() {
+ return isArray() ? true : getInitState() >= runtime().getConfig().instanceKlassStateLinked;
+ }
+
+ /**
+ * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
+ * klass.
+ *
+ * @return state field value of this type
+ */
+ private int getInitState() {
+ assert !isArray() : "_init_state only exists in InstanceKlass";
+ return UNSAFE.getByte(getMetaspaceKlass() + runtime().getConfig().instanceKlassInitStateOffset) & 0xFF;
+ }
+
+ @Override
+ public void initialize() {
+ if (!isInitialized()) {
+ UNSAFE.ensureClassInitialized(mirror());
+ assert isInitialized();
+ }
+ }
+
+ @Override
+ public boolean isInstance(JavaConstant obj) {
+ if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
+ return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isInstanceClass() {
+ return !isArray() && !isInterface();
+ }
+
+ @Override
+ public boolean isInterface() {
+ return mirror().isInterface();
+ }
+
+ @Override
+ public boolean isAssignableFrom(ResolvedJavaType other) {
+ assert other != null;
+ if (other instanceof HotSpotResolvedObjectTypeImpl) {
+ HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
+ return mirror().isAssignableFrom(otherType.mirror());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isJavaLangObject() {
+ return javaClass.equals(Object.class);
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+ ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType);
+ if (resolvedMethod == null || resolvedMethod.isAbstract()) {
+ return null;
+ }
+ return resolvedMethod;
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+ assert !callerType.isArray();
+ if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) {
+ return method;
+ }
+ if (!method.getDeclaringClass().isAssignableFrom(this)) {
+ return null;
+ }
+ HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method;
+ HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType;
+ return runtime().getCompilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
+ }
+
+ public HotSpotConstantPool getConstantPool() {
+ if (constantPool == null) {
+ constantPool = runtime().getCompilerToVM().getConstantPool(this, runtime().getConfig().instanceKlassConstantsOffset);
+ }
+ return constantPool;
+ }
+
+ /**
+ * Gets the instance size of this type. If an instance of this type cannot be fast path
+ * allocated, then the returned value is negative (its absolute value gives the size). Must not
+ * be called if this is an array or interface type.
+ */
+ public int instanceSize() {
+ assert !isArray();
+ assert !isInterface();
+
+ HotSpotVMConfig config = runtime().getConfig();
+ final int layoutHelper = layoutHelper();
+ assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
+
+ // See: Klass::layout_helper_size_in_bytes
+ int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
+
+ // See: Klass::layout_helper_needs_slow_path
+ boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
+
+ return needsSlowPath ? -size : size;
+ }
+
+ public int layoutHelper() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+ }
+
+ synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
+ HotSpotResolvedJavaMethodImpl method = null;
+ if (methodCache == null) {
+ methodCache = new HashMap<>(8);
+ } else {
+ method = methodCache.get(metaspaceMethod);
+ }
+ if (method == null) {
+ method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+ methodCache.put(metaspaceMethod, method);
+ context.add(method);
+ }
+ return method;
+ }
+
+ public int getVtableLength() {
+ HotSpotVMConfig config = runtime().getConfig();
+ if (isInterface() || isArray()) {
+ /* Everything has the core vtable of java.lang.Object */
+ return config.baseVtableLength();
+ }
+ int result = UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
+ assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize;
+ return result;
+ }
+
+ public synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
+ HotSpotResolvedJavaField result = null;
+
+ final int flags = rawFlags & ModifiersProvider.jvmFieldModifiers();
+
+ final long id = offset + ((long) flags << 32);
+
+ // Must cache the fields, because the local load elimination only works if the
+ // objects from two field lookups are identical.
+ if (fieldCache == null) {
+ fieldCache = new HashMap<>(8);
+ } else {
+ result = fieldCache.get(id);
+ }
+
+ if (result == null) {
+ result = new HotSpotResolvedJavaFieldImpl(this, fieldName, type, offset, rawFlags);
+ fieldCache.put(id, result);
+ } else {
+ assert result.getName().equals(fieldName);
+ // assert result.getType().equals(type);
+ assert result.offset() == offset;
+ assert result.getModifiers() == flags;
+ }
+
+ return result;
+ }
+
+ @Override
+ public AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
+ HotSpotResolvedJavaMethod hmethod = (HotSpotResolvedJavaMethod) method;
+ HotSpotResolvedObjectType declaredHolder = hmethod.getDeclaringClass();
+ /*
+ * Sometimes the receiver type in the graph hasn't stabilized to a subtype of declared
+ * holder, usually because of phis, so make sure that the type is related to the declared
+ * type before using it for lookup. Unlinked types should also be ignored because we can't
+ * resolve the proper method to invoke. Generally unlinked types in invokes should result in
+ * a deopt instead since they can't really be used if they aren't linked yet.
+ */
+ if (!declaredHolder.isAssignableFrom(this) || this.isArray() || this.equals(declaredHolder) || !isLinked() || isInterface()) {
+ ResolvedJavaMethod result = hmethod.uniqueConcreteMethod(declaredHolder);
+ if (result != null) {
+ return new AssumptionResult<>(result, new ConcreteMethod(method, declaredHolder, result));
+ }
+ return null;
+ }
+ /*
+ * The holder may be a subtype of the declaredHolder so make sure to resolve the method to
+ * the correct method for the subtype.
+ */
+ HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this);
+ if (resolvedMethod == null) {
+ // The type isn't known to implement the method.
+ return null;
+ }
+
+ ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
+ if (result != null) {
+ return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
+ }
+ return null;
+ }
+
+ /**
+ * This class represents the field information for one field contained in the fields array of an
+ * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
+ */
+ private class FieldInfo {
+ /**
+ * Native pointer into the array of Java shorts.
+ */
+ private final long metaspaceData;
+
+ /**
+ * Creates a field info for the field in the fields array at index {@code index}.
+ *
+ * @param index index to the fields array
+ */
+ public FieldInfo(int index) {
+ HotSpotVMConfig config = runtime().getConfig();
+ // Get Klass::_fields
+ final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
+ assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
+ metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index;
+ }
+
+ private int getAccessFlags() {
+ return readFieldSlot(runtime().getConfig().fieldInfoAccessFlagsOffset);
+ }
+
+ private int getNameIndex() {
+ return readFieldSlot(runtime().getConfig().fieldInfoNameIndexOffset);
+ }
+
+ private int getSignatureIndex() {
+ return readFieldSlot(runtime().getConfig().fieldInfoSignatureIndexOffset);
+ }
+
+ public int getOffset() {
+ HotSpotVMConfig config = runtime().getConfig();
+ final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
+ final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
+ final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
+ return offset;
+ }
+
+ /**
+ * Helper method to read an entry (slot) from the field array. Currently field info is laid
+ * on top an array of Java shorts.
+ */
+ private int readFieldSlot(int index) {
+ return UNSAFE.getChar(metaspaceData + Short.BYTES * index);
+ }
+
+ /**
+ * Returns the name of this field as a {@link String}. If the field is an internal field the
+ * name index is pointing into the vmSymbols table.
+ */
+ public String getName() {
+ final int nameIndex = getNameIndex();
+ return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
+ }
+
+ /**
+ * Returns the signature of this field as {@link String}. If the field is an internal field
+ * the signature index is pointing into the vmSymbols table.
+ */
+ public String getSignature() {
+ final int signatureIndex = getSignatureIndex();
+ return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
+ }
+
+ public JavaType getType() {
+ String signature = getSignature();
+ return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false);
+ }
+
+ private boolean isInternal() {
+ return (getAccessFlags() & runtime().getConfig().jvmAccFieldInternal) != 0;
+ }
+
+ public boolean isStatic() {
+ return Modifier.isStatic(getAccessFlags());
+ }
+
+ public boolean hasGenericSignature() {
+ return (getAccessFlags() & runtime().getConfig().jvmAccFieldHasGenericSignature) != 0;
+ }
+ }
+
+ private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
+ @Override
+ public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
+ return o1.offset() - o2.offset();
+ }
+ }
+
+ @Override
+ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
+ if (instanceFields == null) {
+ if (isArray() || isInterface()) {
+ instanceFields = new HotSpotResolvedJavaField[0];
+ } else {
+ final int fieldCount = getFieldCount();
+ ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
+
+ for (int i = 0; i < fieldCount; i++) {
+ FieldInfo field = new FieldInfo(i);
+
+ // We are only interested in instance fields.
+ if (!field.isStatic()) {
+ HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
+ fieldsArray.add(resolvedJavaField);
+ }
+ }
+
+ fieldsArray.sort(new OffsetComparator());
+
+ HotSpotResolvedJavaField[] myFields = fieldsArray.toArray(new HotSpotResolvedJavaField[0]);
+
+ if (mirror() != Object.class) {
+ HotSpotResolvedJavaField[] superFields = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true);
+ HotSpotResolvedJavaField[] fields = Arrays.copyOf(superFields, superFields.length + myFields.length);
+ System.arraycopy(myFields, 0, fields, superFields.length, myFields.length);
+ instanceFields = fields;
+ } else {
+ assert myFields.length == 0 : "java.lang.Object has fields!";
+ instanceFields = myFields;
+ }
+
+ }
+ }
+ if (!includeSuperclasses) {
+ int myFieldsStart = 0;
+ while (myFieldsStart < instanceFields.length && !instanceFields[myFieldsStart].getDeclaringClass().equals(this)) {
+ myFieldsStart++;
+ }
+ if (myFieldsStart == 0) {
+ return instanceFields;
+ }
+ if (myFieldsStart == instanceFields.length) {
+ return new HotSpotResolvedJavaField[0];
+ }
+ return Arrays.copyOfRange(instanceFields, myFieldsStart, instanceFields.length);
+ }
+ return instanceFields;
+ }
+
+ @Override
+ public ResolvedJavaField[] getStaticFields() {
+ if (isArray()) {
+ return new HotSpotResolvedJavaField[0];
+ } else {
+ final int fieldCount = getFieldCount();
+ ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
+
+ for (int i = 0; i < fieldCount; i++) {
+ FieldInfo field = new FieldInfo(i);
+
+ // We are only interested in static fields.
+ if (field.isStatic()) {
+ HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
+ fieldsArray.add(resolvedJavaField);
+ }
+ }
+
+ fieldsArray.sort(new OffsetComparator());
+ return fieldsArray.toArray(new HotSpotResolvedJavaField[fieldsArray.size()]);
+ }
+ }
+
+ /**
+ * Returns the actual field count of this class's internal {@code InstanceKlass::_fields} array
+ * by walking the array and discounting the generic signature slots at the end of the array.
+ *
+ * <p>
+ * See {@code FieldStreamBase::init_generic_signature_start_slot}
+ */
+ private int getFieldCount() {
+ HotSpotVMConfig config = runtime().getConfig();
+ final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
+ int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
+ int fieldCount = 0;
+
+ for (int i = 0, index = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
+ FieldInfo field = new FieldInfo(index);
+ if (field.hasGenericSignature()) {
+ metaspaceFieldsLength--;
+ }
+ fieldCount++;
+ }
+ return fieldCount;
+ }
+
+ @Override
+ public Class<?> mirror() {
+ return javaClass;
+ }
+
+ @Override
+ public String getSourceFileName() {
+ HotSpotVMConfig config = runtime().getConfig();
+ final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
+ if (sourceFileNameIndex == 0) {
+ return null;
+ }
+ return getConstantPool().lookupUtf8(sourceFileNameIndex);
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return mirror().getAnnotations();
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return mirror().getAnnotation(annotationClass);
+ }
+
+ /**
+ * Performs a fast-path check that this type is resolved in the context of a given accessing
+ * class. A negative result does not mean this type is not resolved with respect to
+ * {@code accessingClass}. That can only be determined by
+ * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
+ * re-resolving} the type.
+ */
+ public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
+ assert accessingClass != null;
+ ResolvedJavaType elementType = getElementalType();
+ if (elementType.isPrimitive()) {
+ // Primitive type resolution is context free.
+ return true;
+ }
+ if (elementType.getName().startsWith("Ljava/")) {
+ // Classes in a java.* package can only be defined by the
+ // boot class loader. This is enforced by ClassLoader.preDefineClass()
+ assert mirror().getClassLoader() == null;
+ return true;
+ }
+ ClassLoader thisCl = mirror().getClassLoader();
+ ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
+ return thisCl == accessingClassCl;
+ }
+
+ @Override
+ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+ if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
+ return this;
+ }
+ HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
+ return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
+ }
+
+ /**
+ * Gets the metaspace Klass boxed in a {@link JavaConstant}.
+ */
+ public JavaConstant klass() {
+ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(runtime().getHostJVMCIBackend().getTarget().wordKind, getMetaspaceKlass(), this, false);
+ }
+
+ public boolean isPrimaryType() {
+ return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset();
+ }
+
+ public int superCheckOffset() {
+ HotSpotVMConfig config = runtime().getConfig();
+ return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset);
+ }
+
+ public long prototypeMarkWord() {
+ HotSpotVMConfig config = runtime().getConfig();
+ if (isArray()) {
+ return config.arrayPrototypeMarkWord();
+ } else {
+ return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
+ }
+ }
+
+ @Override
+ public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
+ ResolvedJavaField[] declaredFields = getInstanceFields(true);
+ for (ResolvedJavaField field : declaredFields) {
+ HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
+ long resolvedFieldOffset = resolvedField.offset();
+ // @formatter:off
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
+ expectedEntryKind.isPrimitive() &&
+ !expectedEntryKind.equals(JavaKind.Void) &&
+ resolvedField.getJavaKind().isPrimitive()) {
+ resolvedFieldOffset +=
+ resolvedField.getJavaKind().getByteCount() -
+ Math.min(resolvedField.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
+ }
+ if (resolvedFieldOffset == offset) {
+ return field;
+ }
+ // @formatter:on
+ }
+ return null;
+ }
+
+ @Override
+ public URL getClassFilePath() {
+ Class<?> cls = mirror();
+ return cls.getResource(MetaUtil.getSimpleName(cls, true).replace('.', '$') + ".class");
+ }
+
+ @Override
+ public boolean isLocal() {
+ return mirror().isLocalClass();
+ }
+
+ @Override
+ public boolean isMember() {
+ return mirror().isMemberClass();
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getEnclosingType() {
+ final Class<?> encl = mirror().getEnclosingClass();
+ return encl == null ? null : fromObjectClass(encl);
+ }
+
+ @Override
+ public ResolvedJavaMethod[] getDeclaredConstructors() {
+ Constructor<?>[] constructors = mirror().getDeclaredConstructors();
+ ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
+ for (int i = 0; i < constructors.length; i++) {
+ result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
+ assert result[i].isConstructor();
+ }
+ return result;
+ }
+
+ @Override
+ public ResolvedJavaMethod[] getDeclaredMethods() {
+ Method[] methods = mirror().getDeclaredMethods();
+ ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
+ for (int i = 0; i < methods.length; i++) {
+ result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
+ assert !result[i].isConstructor();
+ }
+ return result;
+ }
+
+ public ResolvedJavaMethod getClassInitializer() {
+ return runtime().getCompilerToVM().getClassInitializer(this);
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotType<" + getName() + ", resolved>";
+ }
+
+ @Override
+ public boolean isTrustedInterfaceType() {
+ return TrustedInterface.class.isAssignableFrom(mirror());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.Objects.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.net.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+
+/**
+ * Implementation of {@link JavaType} for primitive HotSpot types.
+ */
+public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType implements HotSpotProxified {
+
+ private final JavaKind kind;
+
+ /**
+ * Creates the JVMCI mirror for a primitive {@link JavaKind}.
+ *
+ * <p>
+ * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
+ * {@link Class} type. Use {@link HotSpotJVMCIRuntimeProvider#fromClass(Class)} instead.
+ * </p>
+ *
+ * @param kind the Kind to create the mirror for
+ */
+ public HotSpotResolvedPrimitiveType(JavaKind kind) {
+ super(String.valueOf(Character.toUpperCase(kind.getTypeChar())));
+ this.kind = kind;
+ assert mirror().isPrimitive() : mirror() + " not a primitive type";
+ }
+
+ @Override
+ public int getModifiers() {
+ return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
+ }
+
+ @Override
+ public HotSpotResolvedObjectTypeImpl getArrayClass() {
+ if (kind == JavaKind.Void) {
+ return null;
+ }
+ Class<?> javaArrayMirror = Array.newInstance(mirror(), 0).getClass();
+ return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaArrayMirror);
+ }
+
+ public ResolvedJavaType getElementalType() {
+ return this;
+ }
+
+ @Override
+ public ResolvedJavaType getComponentType() {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaType asExactType() {
+ return this;
+ }
+
+ @Override
+ public ResolvedJavaType getSuperclass() {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaType[] getInterfaces() {
+ return new ResolvedJavaType[0];
+ }
+
+ @Override
+ public ResolvedJavaType getSingleImplementor() {
+ throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
+ }
+
+ @Override
+ public ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType) {
+ return null;
+ }
+
+ @Override
+ public JavaConstant getObjectHub() {
+ throw JVMCIError.unimplemented();
+ }
+
+ @Override
+ public JavaConstant getJavaClass() {
+ throw JVMCIError.unimplemented();
+ }
+
+ @Override
+ public AssumptionResult<Boolean> hasFinalizableSubclass() {
+ return new AssumptionResult<>(false);
+ }
+
+ @Override
+ public boolean hasFinalizer() {
+ return false;
+ }
+
+ @Override
+ public boolean isArray() {
+ return false;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return true;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return true;
+ }
+
+ public boolean isLinked() {
+ return true;
+ }
+
+ @Override
+ public boolean isInstance(JavaConstant obj) {
+ return false;
+ }
+
+ @Override
+ public boolean isInstanceClass() {
+ return false;
+ }
+
+ @Override
+ public boolean isInterface() {
+ return false;
+ }
+
+ @Override
+ public boolean isAssignableFrom(ResolvedJavaType other) {
+ assert other != null;
+ return other.equals(this);
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return kind;
+ }
+
+ @Override
+ public boolean isJavaLangObject() {
+ return false;
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotResolvedPrimitiveType<" + kind + ">";
+ }
+
+ @Override
+ public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+ return new AssumptionResult<>(this);
+ }
+
+ @Override
+ public AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
+ return new ResolvedJavaField[0];
+ }
+
+ @Override
+ public ResolvedJavaField[] getStaticFields() {
+ return new ResolvedJavaField[0];
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return new Annotation[0];
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+ requireNonNull(accessingClass);
+ return this;
+ }
+
+ @Override
+ public void initialize() {
+ }
+
+ @Override
+ public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedType) {
+ return null;
+ }
+
+ @Override
+ public String getSourceFileName() {
+ throw JVMCIError.unimplemented();
+ }
+
+ @Override
+ public Class<?> mirror() {
+ return kind.toJavaClass();
+ }
+
+ @Override
+ public URL getClassFilePath() {
+ return null;
+ }
+
+ @Override
+ public boolean isLocal() {
+ return false;
+ }
+
+ @Override
+ public boolean isMember() {
+ return false;
+ }
+
+ @Override
+ public ResolvedJavaType getEnclosingType() {
+ return null;
+ }
+
+ @Override
+ public ResolvedJavaMethod[] getDeclaredConstructors() {
+ return new ResolvedJavaMethod[0];
+ }
+
+ @Override
+ public ResolvedJavaMethod[] getDeclaredMethods() {
+ return new ResolvedJavaMethod[0];
+ }
+
+ @Override
+ public ResolvedJavaMethod getClassInitializer() {
+ return null;
+ }
+
+ @Override
+ public boolean isTrustedInterfaceType() {
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+public final class HotSpotSentinelConstant extends Value implements JavaConstant, VMConstant {
+
+ public HotSpotSentinelConstant(JavaKind kind) {
+ super(LIRKind.reference(kind));
+ }
+
+ public JavaKind getJavaKind() {
+ return (JavaKind) getLIRKind().getPlatformKind();
+ }
+
+ @Override
+ public boolean isNull() {
+ return true;
+ }
+
+ @Override
+ public boolean isDefaultForKind() {
+ return true;
+ }
+
+ @Override
+ public Object asBoxedPrimitive() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int asInt() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public boolean asBoolean() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public long asLong() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public float asFloat() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public double asDouble() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public String toString() {
+ return JavaConstant.toString(this);
+ }
+
+ @Override
+ public String toValueString() {
+ return "sentinel";
+ }
+
+ @Override
+ public int hashCode() {
+ return 13;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof HotSpotSentinelConstant;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a method signature.
+ */
+public class HotSpotSignature implements Signature {
+
+ private final List<String> parameters = new ArrayList<>();
+ private final String returnType;
+ private final String originalString;
+ private ResolvedJavaType[] parameterTypes;
+ private ResolvedJavaType returnTypeCache;
+ private final HotSpotJVMCIRuntimeProvider runtime;
+
+ public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, String signature) {
+ this.runtime = runtime;
+ assert signature.length() > 0;
+ this.originalString = signature;
+
+ if (signature.charAt(0) == '(') {
+ int cur = 1;
+ while (cur < signature.length() && signature.charAt(cur) != ')') {
+ int nextCur = parseSignature(signature, cur);
+ parameters.add(signature.substring(cur, nextCur));
+ cur = nextCur;
+ }
+
+ cur++;
+ int nextCur = parseSignature(signature, cur);
+ returnType = signature.substring(cur, nextCur);
+ assert nextCur == signature.length();
+ } else {
+ returnType = null;
+ }
+ }
+
+ public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) {
+ this.runtime = runtime;
+ this.parameterTypes = parameterTypes.clone();
+ this.returnTypeCache = returnType;
+ this.returnType = returnType.getName();
+ StringBuilder sb = new StringBuilder("(");
+ for (JavaType type : parameterTypes) {
+ parameters.add(type.getName());
+ sb.append(type.getName());
+ }
+ sb.append(")").append(returnType.getName());
+ this.originalString = sb.toString();
+ assert new HotSpotSignature(runtime, originalString).equals(this);
+ }
+
+ private static int parseSignature(String signature, int start) {
+ int cur = start;
+ char first;
+ do {
+ first = signature.charAt(cur++);
+ } while (first == '[');
+
+ switch (first) {
+ case 'L':
+ while (signature.charAt(cur) != ';') {
+ cur++;
+ }
+ cur++;
+ break;
+ case 'V':
+ case 'I':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'J':
+ case 'S':
+ case 'Z':
+ break;
+ default:
+ throw new JVMCIError("Invalid character at index %d in signature: %s", cur, signature);
+ }
+ return cur;
+ }
+
+ @Override
+ public int getParameterCount(boolean withReceiver) {
+ return parameters.size() + (withReceiver ? 1 : 0);
+ }
+
+ @Override
+ public JavaKind getParameterKind(int index) {
+ return JavaKind.fromTypeString(parameters.get(index));
+ }
+
+ private static boolean checkValidCache(ResolvedJavaType type, ResolvedJavaType accessingClass) {
+ assert accessingClass != null;
+ if (type == null) {
+ return false;
+ } else if (type instanceof HotSpotResolvedObjectTypeImpl) {
+ return ((HotSpotResolvedObjectTypeImpl) type).isDefinitelyResolvedWithRespectTo(accessingClass);
+ }
+ return true;
+ }
+
+ private static JavaType getUnresolvedOrPrimitiveType(HotSpotJVMCIRuntimeProvider runtime, String name) {
+ if (name.length() == 1) {
+ JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
+ return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(kind.toJavaClass());
+ }
+ return new HotSpotUnresolvedJavaType(name, runtime);
+ }
+
+ @Override
+ public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
+ if (accessingClass == null) {
+ // Caller doesn't care about resolution context so return an unresolved
+ // or primitive type (primitive type resolution is context free)
+ return getUnresolvedOrPrimitiveType(runtime, parameters.get(index));
+ }
+ if (parameterTypes == null) {
+ parameterTypes = new ResolvedJavaType[parameters.size()];
+ }
+
+ ResolvedJavaType type = parameterTypes[index];
+ if (!checkValidCache(type, accessingClass)) {
+ JavaType result = runtime.lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false);
+ if (result instanceof ResolvedJavaType) {
+ type = (ResolvedJavaType) result;
+ parameterTypes[index] = type;
+ } else {
+ return result;
+ }
+ }
+ return type;
+ }
+
+ @Override
+ public String toMethodDescriptor() {
+ assert originalString.equals(Signature.super.toMethodDescriptor());
+ return originalString;
+ }
+
+ @Override
+ public JavaKind getReturnKind() {
+ return JavaKind.fromTypeString(returnType);
+ }
+
+ @Override
+ public JavaType getReturnType(ResolvedJavaType accessingClass) {
+ if (accessingClass == null) {
+ // Caller doesn't care about resolution context so return an unresolved
+ // or primitive type (primitive type resolution is context free)
+ return getUnresolvedOrPrimitiveType(runtime, returnType);
+ }
+ if (!checkValidCache(returnTypeCache, accessingClass)) {
+ JavaType result = runtime.lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false);
+ if (result instanceof ResolvedJavaType) {
+ returnTypeCache = (ResolvedJavaType) result;
+ } else {
+ return result;
+ }
+ }
+ return returnTypeCache;
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotSignature<" + originalString + ">";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof HotSpotSignature) {
+ HotSpotSignature other = (HotSpotSignature) obj;
+ if (other.originalString.equals(originalString)) {
+ assert other.parameters.equals(parameters);
+ assert other.returnType.equals(returnType);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return originalString.hashCode();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+public class HotSpotSpeculationLog extends SpeculationLog {
+
+ @Override
+ public JavaConstant speculate(Object reason) {
+ addSpeculation(reason);
+ return HotSpotObjectConstantImpl.forObject(reason);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.*;
+
+import jdk.vm.ci.code.stack.*;
+import jdk.vm.ci.meta.*;
+
+public class HotSpotStackFrameReference implements InspectedFrame {
+
+ private CompilerToVM compilerToVM;
+
+ // information used to find the stack frame
+ private long stackPointer;
+ private int frameNumber;
+
+ // information about the stack frame's contents
+ private int bci;
+ private HotSpotResolvedJavaMethod method;
+ private Object[] locals;
+ private boolean[] localIsVirtual;
+
+ public long getStackPointer() {
+ return stackPointer;
+ }
+
+ public int getFrameNumber() {
+ return frameNumber;
+ }
+
+ @Override
+ public Object getLocal(int index) {
+ return locals[index];
+ }
+
+ @Override
+ public boolean isVirtual(int index) {
+ return localIsVirtual == null ? false : localIsVirtual[index];
+ }
+
+ @Override
+ public void materializeVirtualObjects(boolean invalidateCode) {
+ compilerToVM.materializeVirtualObjects(this, invalidateCode);
+ }
+
+ @Override
+ public int getBytecodeIndex() {
+ return bci;
+ }
+
+ @Override
+ public ResolvedJavaMethod getMethod() {
+ return method;
+ }
+
+ @Override
+ public boolean isMethod(ResolvedJavaMethod otherMethod) {
+ return method.equals(otherMethod);
+ }
+
+ @Override
+ public boolean hasVirtualObjects() {
+ return localIsVirtual != null;
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotStackFrameReference [stackPointer=" + stackPointer + ", frameNumber=" + frameNumber + ", bci=" + bci + ", method=" + getMethod() + ", locals=" + Arrays.toString(locals) +
+ ", localIsVirtual=" + Arrays.toString(localIsVirtual) + "]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2009, 2011, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * A implementation of {@link JavaField} for an unresolved field.
+ */
+public class HotSpotUnresolvedField implements JavaField {
+
+ private final String name;
+ private final JavaType holder;
+ private final JavaType type;
+
+ public HotSpotUnresolvedField(JavaType holder, String name, JavaType type) {
+ this.name = name;
+ this.type = type;
+ this.holder = holder;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public JavaType getType() {
+ return type;
+ }
+
+ public JavaType getDeclaringClass() {
+ return holder;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || !(obj instanceof HotSpotUnresolvedField)) {
+ return false;
+ }
+ HotSpotUnresolvedField that = (HotSpotUnresolvedField) obj;
+ return this.holder.equals(that.holder) && this.name.equals(that.name) && this.type.equals(that.type);
+ }
+
+ /**
+ * Converts this compiler interface field to a string.
+ */
+ @Override
+ public String toString() {
+ return format("HotSpotField<%H.%n %t, unresolved>");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Implementation of {@link JavaType} for unresolved HotSpot classes.
+ */
+public class HotSpotUnresolvedJavaType extends HotSpotJavaType {
+
+ private final HotSpotJVMCIRuntimeProvider runtime;
+
+ public HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) {
+ super(name);
+ assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name;
+ this.runtime = runtime;
+ }
+
+ /**
+ * Creates an unresolved type for a valid {@link JavaType#getName() type name}.
+ */
+ public static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) {
+ return new HotSpotUnresolvedJavaType(name, runtime);
+ }
+
+ @Override
+ public JavaType getComponentType() {
+ assert getName().charAt(0) == '[' : "no array class" + getName();
+ return new HotSpotUnresolvedJavaType(getName().substring(1), runtime);
+ }
+
+ @Override
+ public JavaType getArrayClass() {
+ return new HotSpotUnresolvedJavaType('[' + getName(), runtime);
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || !(obj instanceof HotSpotUnresolvedJavaType)) {
+ return false;
+ }
+ HotSpotUnresolvedJavaType that = (HotSpotUnresolvedJavaType) obj;
+ return this.getName().equals(that.getName());
+ }
+
+ @Override
+ public String toString() {
+ return "HotSpotType<" + getName() + ", unresolved>";
+ }
+
+ @Override
+ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+ return (ResolvedJavaType) runtime.lookupType(getName(), (HotSpotResolvedObjectType) accessingClass, true);
+ }
+
+ /**
+ * Try to find a loaded version of this class.
+ *
+ * @param accessingClass
+ * @return the resolved class or null.
+ */
+ ResolvedJavaType reresolve(HotSpotResolvedObjectType accessingClass) {
+ JavaType type = runtime.lookupType(getName(), accessingClass, false);
+ if (type instanceof ResolvedJavaType) {
+ return (ResolvedJavaType) type;
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1773 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.common.UnsafeUtil.readCString;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import sun.misc.*;
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.hotspotvmconfig.*;
+
+//JaCoCo Exclude
+
+/**
+ * Used to access native configuration details.
+ *
+ * All non-static, public fields in this class are so that they can be compiled as constants.
+ */
+public class HotSpotVMConfig {
+
+ /**
+ * Maximum allowed size of allocated area for a frame.
+ */
+ public final int maxFrameSize = 16 * 1024;
+
+ public HotSpotVMConfig(CompilerToVM compilerToVm) {
+ // Get raw pointer to the array that contains all gHotSpotVM values.
+ final long gHotSpotVMData = compilerToVm.initializeConfiguration();
+ assert gHotSpotVMData != 0;
+
+ // Make FindBugs happy.
+ gHotSpotVMStructs = 0;
+ gHotSpotVMTypes = 0;
+ gHotSpotVMIntConstants = 0;
+ gHotSpotVMLongConstants = 0;
+ gHotSpotVMAddresses = 0;
+
+ // Initialize the gHotSpotVM fields.
+ for (Field f : HotSpotVMConfig.class.getDeclaredFields()) {
+ if (f.isAnnotationPresent(HotSpotVMData.class)) {
+ HotSpotVMData annotation = f.getAnnotation(HotSpotVMData.class);
+ final int index = annotation.index();
+ final long value = UNSAFE.getAddress(gHotSpotVMData + Unsafe.ADDRESS_SIZE * index);
+ try {
+ f.setLong(this, value);
+ } catch (IllegalAccessException e) {
+ throw new JVMCIError("index " + index, e);
+ }
+ }
+ }
+
+ // Quick sanity check.
+ assert gHotSpotVMStructs != 0;
+ assert gHotSpotVMTypes != 0;
+ assert gHotSpotVMIntConstants != 0;
+ assert gHotSpotVMLongConstants != 0;
+ assert gHotSpotVMAddresses != 0;
+
+ initialize();
+
+ oopEncoding = new CompressEncoding(narrowOopBase, narrowOopShift, logMinObjAlignment());
+ klassEncoding = new CompressEncoding(narrowKlassBase, narrowKlassShift, logKlassAlignment);
+
+ final long barrierSetAddress = UNSAFE.getAddress(universeCollectedHeap + collectedHeapBarrierSetOffset);
+ final int kind = UNSAFE.getInt(barrierSetAddress + barrierSetFakeRttiOffset + fakeRttiConcreteTagOffset);
+ if ((kind == barrierSetCardTableModRef) || (kind == barrierSetCardTableExtension) || (kind == barrierSetG1SATBCT) || (kind == barrierSetG1SATBCTLogging)) {
+ final long base = UNSAFE.getAddress(barrierSetAddress + cardTableModRefBSByteMapBaseOffset);
+ assert base != 0 : "unexpected byte_map_base: " + base;
+ cardtableStartAddress = base;
+ cardtableShift = cardTableModRefBSCardShift;
+ } else if (kind == barrierSetCardTableForRS) {
+ throw JVMCIError.unimplemented();
+ } else if (kind == barrierSetModRef) {
+ // No post barriers
+ cardtableStartAddress = 0;
+ cardtableShift = 0;
+ } else {
+ cardtableStartAddress = -1;
+ cardtableShift = -1;
+ }
+
+ // Now handle all HotSpotVMManual fields.
+ inlineCacheMissStub = inlineCacheMissBlob + UNSAFE.getInt(inlineCacheMissBlob + codeBlobCodeOffsetOffset);
+ handleWrongMethodStub = wrongMethodBlob + UNSAFE.getInt(wrongMethodBlob + codeBlobCodeOffsetOffset);
+ handleDeoptStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUnpackOffsetOffset);
+ uncommonTrapStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUncommonTrapOffsetOffset);
+
+ assert check();
+ assert HotSpotVMConfigVerifier.check();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+
+ /**
+ * Initialize fields by reading their values from vmStructs.
+ */
+ private void initialize() {
+ // Fill the VM fields hash map.
+ HashMap<String, VMFields.Field> vmFields = new HashMap<>();
+ for (VMFields.Field e : new VMFields(gHotSpotVMStructs)) {
+ vmFields.put(e.getName(), e);
+ }
+
+ // Fill the VM types hash map.
+ HashMap<String, VMTypes.Type> vmTypes = new HashMap<>();
+ for (VMTypes.Type e : new VMTypes(gHotSpotVMTypes)) {
+ vmTypes.put(e.getTypeName(), e);
+ }
+
+ // Fill the VM constants hash map.
+ HashMap<String, AbstractConstant> vmConstants = new HashMap<>();
+ for (AbstractConstant e : new VMIntConstants(gHotSpotVMIntConstants)) {
+ vmConstants.put(e.getName(), e);
+ }
+ for (AbstractConstant e : new VMAddresses(gHotSpotVMLongConstants)) {
+ vmConstants.put(e.getName(), e);
+ }
+
+ // Fill the VM addresses hash map.
+ HashMap<String, VMAddresses.Address> vmAddresses = new HashMap<>();
+ for (VMAddresses.Address e : new VMAddresses(gHotSpotVMAddresses)) {
+ vmAddresses.put(e.getName(), e);
+ }
+
+ // Fill the flags hash map.
+ HashMap<String, Flags.Flag> flags = new HashMap<>();
+ for (Flags.Flag e : new Flags(vmFields, vmTypes)) {
+ flags.put(e.getName(), e);
+ }
+
+ String osName = getHostOSName();
+ String osArch = getHostArchitectureName();
+
+ for (Field f : HotSpotVMConfig.class.getDeclaredFields()) {
+ if (f.isAnnotationPresent(HotSpotVMField.class)) {
+ HotSpotVMField annotation = f.getAnnotation(HotSpotVMField.class);
+ String name = annotation.name();
+ String type = annotation.type();
+ VMFields.Field entry = vmFields.get(name);
+ if (entry == null) {
+ if (!isRequired(osArch, annotation.archs())) {
+ continue;
+ }
+ throw new JVMCIError(f.getName() + ": expected VM field not found: " + name);
+ }
+
+ // Make sure the native type is still the type we expect.
+ if (!type.isEmpty()) {
+ if (!type.equals(entry.getTypeString())) {
+ throw new JVMCIError(f.getName() + ": compiler expects type " + type + " but VM field " + name + " is of type " + entry.getTypeString());
+ }
+ }
+
+ switch (annotation.get()) {
+ case OFFSET:
+ setField(f, entry.getOffset());
+ break;
+ case ADDRESS:
+ setField(f, entry.getAddress());
+ break;
+ case VALUE:
+ setField(f, entry.getValue());
+ break;
+ default:
+ throw new JVMCIError(f.getName() + ": unknown kind: " + annotation.get());
+ }
+ } else if (f.isAnnotationPresent(HotSpotVMType.class)) {
+ HotSpotVMType annotation = f.getAnnotation(HotSpotVMType.class);
+ String name = annotation.name();
+ VMTypes.Type entry = vmTypes.get(name);
+ if (entry == null) {
+ throw new JVMCIError(f.getName() + ": expected VM type not found: " + name);
+ }
+ switch (annotation.get()) {
+ case SIZE:
+ setField(f, entry.getSize());
+ break;
+ default:
+ throw new JVMCIError(f.getName() + ": unknown kind: " + annotation.get());
+ }
+ } else if (f.isAnnotationPresent(HotSpotVMConstant.class)) {
+ HotSpotVMConstant annotation = f.getAnnotation(HotSpotVMConstant.class);
+ String name = annotation.name();
+ AbstractConstant entry = vmConstants.get(name);
+ if (entry == null) {
+ if (!isRequired(osArch, annotation.archs())) {
+ continue;
+ }
+ throw new JVMCIError(f.getName() + ": expected VM constant not found: " + name);
+ }
+ setField(f, entry.getValue());
+ } else if (f.isAnnotationPresent(HotSpotVMAddress.class)) {
+ HotSpotVMAddress annotation = f.getAnnotation(HotSpotVMAddress.class);
+ String name = annotation.name();
+ VMAddresses.Address entry = vmAddresses.get(name);
+ if (entry == null) {
+ if (!isRequired(osName, annotation.os())) {
+ continue;
+ }
+ throw new JVMCIError(f.getName() + ": expected VM address not found: " + name);
+ }
+ setField(f, entry.getValue());
+ } else if (f.isAnnotationPresent(HotSpotVMFlag.class)) {
+ HotSpotVMFlag annotation = f.getAnnotation(HotSpotVMFlag.class);
+ String name = annotation.name();
+ Flags.Flag entry = flags.get(name);
+ if (entry == null) {
+ if (annotation.optional() || !isRequired(osArch, annotation.archs())) {
+ continue;
+ }
+ throw new JVMCIError(f.getName() + ": expected VM flag not found: " + name);
+
+ }
+ setField(f, entry.getValue());
+ }
+ }
+ }
+
+ private final CompressEncoding oopEncoding;
+ private final CompressEncoding klassEncoding;
+
+ public CompressEncoding getOopEncoding() {
+ return oopEncoding;
+ }
+
+ public CompressEncoding getKlassEncoding() {
+ return klassEncoding;
+ }
+
+ private void setField(Field field, Object value) {
+ try {
+ Class<?> fieldType = field.getType();
+ if (fieldType == boolean.class) {
+ if (value instanceof String) {
+ field.setBoolean(this, Boolean.valueOf((String) value));
+ } else if (value instanceof Boolean) {
+ field.setBoolean(this, (boolean) value);
+ } else if (value instanceof Long) {
+ field.setBoolean(this, ((long) value) != 0);
+ } else {
+ throw new JVMCIError(value.getClass().getSimpleName());
+ }
+ } else if (fieldType == byte.class) {
+ if (value instanceof Long) {
+ field.setByte(this, (byte) (long) value);
+ } else {
+ throw new JVMCIError(value.getClass().getSimpleName());
+ }
+ } else if (fieldType == int.class) {
+ if (value instanceof Integer) {
+ field.setInt(this, (int) value);
+ } else if (value instanceof Long) {
+ field.setInt(this, (int) (long) value);
+ } else {
+ throw new JVMCIError(value.getClass().getSimpleName());
+ }
+ } else if (fieldType == long.class) {
+ field.setLong(this, (long) value);
+ } else {
+ throw new JVMCIError(field.toString());
+ }
+ } catch (IllegalAccessException e) {
+ throw new JVMCIError("%s: %s", field, e);
+ }
+ }
+
+ /**
+ * Gets the host operating system name.
+ */
+ private static String getHostOSName() {
+ String osName = System.getProperty("os.name");
+ switch (osName) {
+ case "Linux":
+ osName = "linux";
+ break;
+ case "SunOS":
+ osName = "solaris";
+ break;
+ case "Mac OS X":
+ osName = "bsd";
+ break;
+ default:
+ // Of course Windows is different...
+ if (osName.startsWith("Windows")) {
+ osName = "windows";
+ } else {
+ throw new JVMCIError("Unexpected OS name: " + osName);
+ }
+ }
+ return osName;
+ }
+
+ /**
+ * Gets the host architecture name for the purpose of finding the corresponding
+ * {@linkplain HotSpotJVMCIBackendFactory backend}.
+ */
+ public String getHostArchitectureName() {
+ String arch = System.getProperty("os.arch");
+ switch (arch) {
+ case "x86_64":
+ arch = "amd64";
+ break;
+ case "sparcv9":
+ arch = "sparc";
+ break;
+ }
+ return arch;
+ }
+
+ /**
+ * Determines if the current specification is included in a given set of specifications.
+ *
+ * @param current
+ * @param specification specifies a set of specifications, e.g. architectures or operating
+ * systems. A zero length value implies all.
+ */
+ private static boolean isRequired(String current, String[] specification) {
+ if (specification.length == 0) {
+ return true;
+ }
+ for (String arch : specification) {
+ if (arch.equals(current)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * VMStructEntry (see {@code vmStructs.hpp}).
+ */
+ @HotSpotVMData(index = 0) @Stable private long gHotSpotVMStructs;
+ @HotSpotVMData(index = 1) @Stable private long gHotSpotVMStructEntryTypeNameOffset;
+ @HotSpotVMData(index = 2) @Stable private long gHotSpotVMStructEntryFieldNameOffset;
+ @HotSpotVMData(index = 3) @Stable private long gHotSpotVMStructEntryTypeStringOffset;
+ @HotSpotVMData(index = 4) @Stable private long gHotSpotVMStructEntryIsStaticOffset;
+ @HotSpotVMData(index = 5) @Stable private long gHotSpotVMStructEntryOffsetOffset;
+ @HotSpotVMData(index = 6) @Stable private long gHotSpotVMStructEntryAddressOffset;
+ @HotSpotVMData(index = 7) @Stable private long gHotSpotVMStructEntryArrayStride;
+
+ final class VMFields implements Iterable<VMFields.Field> {
+
+ private final long address;
+
+ public VMFields(long address) {
+ this.address = address;
+ }
+
+ public Iterator<VMFields.Field> iterator() {
+ return new Iterator<VMFields.Field>() {
+
+ private int index = 0;
+
+ private Field current() {
+ return new Field(address + gHotSpotVMStructEntryArrayStride * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL fieldName.
+ */
+ public boolean hasNext() {
+ Field entry = current();
+ return entry.getFieldName() != null;
+ }
+
+ public Field next() {
+ Field entry = current();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Field {
+
+ private final long entryAddress;
+
+ Field(long address) {
+ this.entryAddress = address;
+ }
+
+ public String getTypeName() {
+ long typeNameAddress = UNSAFE.getAddress(entryAddress + gHotSpotVMStructEntryTypeNameOffset);
+ return readCString(UNSAFE, typeNameAddress);
+ }
+
+ public String getFieldName() {
+ long fieldNameAddress = UNSAFE.getAddress(entryAddress + gHotSpotVMStructEntryFieldNameOffset);
+ return readCString(UNSAFE, fieldNameAddress);
+ }
+
+ public String getTypeString() {
+ long typeStringAddress = UNSAFE.getAddress(entryAddress + gHotSpotVMStructEntryTypeStringOffset);
+ return readCString(UNSAFE, typeStringAddress);
+ }
+
+ public boolean isStatic() {
+ return UNSAFE.getInt(entryAddress + gHotSpotVMStructEntryIsStaticOffset) != 0;
+ }
+
+ public long getOffset() {
+ return UNSAFE.getLong(entryAddress + gHotSpotVMStructEntryOffsetOffset);
+ }
+
+ public long getAddress() {
+ return UNSAFE.getAddress(entryAddress + gHotSpotVMStructEntryAddressOffset);
+ }
+
+ public String getName() {
+ String typeName = getTypeName();
+ String fieldName = getFieldName();
+ return typeName + "::" + fieldName;
+ }
+
+ public long getValue() {
+ String type = getTypeString();
+ switch (type) {
+ case "bool":
+ return UNSAFE.getByte(getAddress());
+ case "int":
+ return UNSAFE.getInt(getAddress());
+ case "uint64_t":
+ return UNSAFE.getLong(getAddress());
+ case "address":
+ case "intptr_t":
+ case "uintptr_t":
+ return UNSAFE.getAddress(getAddress());
+ default:
+ // All foo* types are addresses.
+ if (type.endsWith("*")) {
+ return UNSAFE.getAddress(getAddress());
+ }
+ throw new JVMCIError(type);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Field[typeName=%s, fieldName=%s, typeString=%s, isStatic=%b, offset=%d, address=0x%x]", getTypeName(), getFieldName(), getTypeString(), isStatic(), getOffset(),
+ getAddress());
+ }
+ }
+ }
+
+ /**
+ * VMTypeEntry (see vmStructs.hpp).
+ */
+ @HotSpotVMData(index = 8) @Stable private long gHotSpotVMTypes;
+ @HotSpotVMData(index = 9) @Stable private long gHotSpotVMTypeEntryTypeNameOffset;
+ @HotSpotVMData(index = 10) @Stable private long gHotSpotVMTypeEntrySuperclassNameOffset;
+ @HotSpotVMData(index = 11) @Stable private long gHotSpotVMTypeEntryIsOopTypeOffset;
+ @HotSpotVMData(index = 12) @Stable private long gHotSpotVMTypeEntryIsIntegerTypeOffset;
+ @HotSpotVMData(index = 13) @Stable private long gHotSpotVMTypeEntryIsUnsignedOffset;
+ @HotSpotVMData(index = 14) @Stable private long gHotSpotVMTypeEntrySizeOffset;
+ @HotSpotVMData(index = 15) @Stable private long gHotSpotVMTypeEntryArrayStride;
+
+ final class VMTypes implements Iterable<VMTypes.Type> {
+
+ private final long address;
+
+ public VMTypes(long address) {
+ this.address = address;
+ }
+
+ public Iterator<VMTypes.Type> iterator() {
+ return new Iterator<VMTypes.Type>() {
+
+ private int index = 0;
+
+ private Type current() {
+ return new Type(address + gHotSpotVMTypeEntryArrayStride * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL type name.
+ */
+ public boolean hasNext() {
+ Type entry = current();
+ return entry.getTypeName() != null;
+ }
+
+ public Type next() {
+ Type entry = current();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Type {
+
+ private final long entryAddress;
+
+ Type(long address) {
+ this.entryAddress = address;
+ }
+
+ public String getTypeName() {
+ long typeNameAddress = UNSAFE.getAddress(entryAddress + gHotSpotVMTypeEntryTypeNameOffset);
+ return readCString(UNSAFE, typeNameAddress);
+ }
+
+ public String getSuperclassName() {
+ long superclassNameAddress = UNSAFE.getAddress(entryAddress + gHotSpotVMTypeEntrySuperclassNameOffset);
+ return readCString(UNSAFE, superclassNameAddress);
+ }
+
+ public boolean isOopType() {
+ return UNSAFE.getInt(entryAddress + gHotSpotVMTypeEntryIsOopTypeOffset) != 0;
+ }
+
+ public boolean isIntegerType() {
+ return UNSAFE.getInt(entryAddress + gHotSpotVMTypeEntryIsIntegerTypeOffset) != 0;
+ }
+
+ public boolean isUnsigned() {
+ return UNSAFE.getInt(entryAddress + gHotSpotVMTypeEntryIsUnsignedOffset) != 0;
+ }
+
+ public long getSize() {
+ return UNSAFE.getLong(entryAddress + gHotSpotVMTypeEntrySizeOffset);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Type[typeName=%s, superclassName=%s, isOopType=%b, isIntegerType=%b, isUnsigned=%b, size=%d]", getTypeName(), getSuperclassName(), isOopType(), isIntegerType(),
+ isUnsigned(), getSize());
+ }
+ }
+ }
+
+ public abstract class AbstractConstant {
+
+ protected final long address;
+ protected final long nameOffset;
+ protected final long valueOffset;
+
+ AbstractConstant(long address, long nameOffset, long valueOffset) {
+ this.address = address;
+ this.nameOffset = nameOffset;
+ this.valueOffset = valueOffset;
+ }
+
+ public String getName() {
+ long nameAddress = UNSAFE.getAddress(address + nameOffset);
+ return readCString(UNSAFE, nameAddress);
+ }
+
+ public abstract long getValue();
+ }
+
+ /**
+ * VMIntConstantEntry (see vmStructs.hpp).
+ */
+ @HotSpotVMData(index = 16) @Stable private long gHotSpotVMIntConstants;
+ @HotSpotVMData(index = 17) @Stable private long gHotSpotVMIntConstantEntryNameOffset;
+ @HotSpotVMData(index = 18) @Stable private long gHotSpotVMIntConstantEntryValueOffset;
+ @HotSpotVMData(index = 19) @Stable private long gHotSpotVMIntConstantEntryArrayStride;
+
+ final class VMIntConstants implements Iterable<VMIntConstants.Constant> {
+
+ private final long address;
+
+ public VMIntConstants(long address) {
+ this.address = address;
+ }
+
+ public Iterator<VMIntConstants.Constant> iterator() {
+ return new Iterator<VMIntConstants.Constant>() {
+
+ private int index = 0;
+
+ private Constant current() {
+ return new Constant(address + gHotSpotVMIntConstantEntryArrayStride * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL name.
+ */
+ public boolean hasNext() {
+ Constant entry = current();
+ return entry.getName() != null;
+ }
+
+ public Constant next() {
+ Constant entry = current();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Constant extends AbstractConstant {
+
+ Constant(long address) {
+ super(address, gHotSpotVMIntConstantEntryNameOffset, gHotSpotVMIntConstantEntryValueOffset);
+ }
+
+ @Override
+ public long getValue() {
+ return UNSAFE.getInt(address + valueOffset);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("IntConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
+ }
+ }
+ }
+
+ /**
+ * VMLongConstantEntry (see vmStructs.hpp).
+ */
+ @HotSpotVMData(index = 20) @Stable private long gHotSpotVMLongConstants;
+ @HotSpotVMData(index = 21) @Stable private long gHotSpotVMLongConstantEntryNameOffset;
+ @HotSpotVMData(index = 22) @Stable private long gHotSpotVMLongConstantEntryValueOffset;
+ @HotSpotVMData(index = 23) @Stable private long gHotSpotVMLongConstantEntryArrayStride;
+
+ final class VMLongConstants implements Iterable<VMLongConstants.Constant> {
+
+ private final long address;
+
+ public VMLongConstants(long address) {
+ this.address = address;
+ }
+
+ public Iterator<VMLongConstants.Constant> iterator() {
+ return new Iterator<VMLongConstants.Constant>() {
+
+ private int index = 0;
+
+ private Constant currentEntry() {
+ return new Constant(address + gHotSpotVMLongConstantEntryArrayStride * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL name.
+ */
+ public boolean hasNext() {
+ Constant entry = currentEntry();
+ return entry.getName() != null;
+ }
+
+ public Constant next() {
+ Constant entry = currentEntry();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Constant extends AbstractConstant {
+
+ Constant(long address) {
+ super(address, gHotSpotVMLongConstantEntryNameOffset, gHotSpotVMLongConstantEntryValueOffset);
+ }
+
+ @Override
+ public long getValue() {
+ return UNSAFE.getLong(address + valueOffset);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("LongConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
+ }
+ }
+ }
+
+ /**
+ * VMAddressEntry (see vmStructs.hpp).
+ */
+ @HotSpotVMData(index = 24) @Stable private long gHotSpotVMAddresses;
+ @HotSpotVMData(index = 25) @Stable private long gHotSpotVMAddressEntryNameOffset;
+ @HotSpotVMData(index = 26) @Stable private long gHotSpotVMAddressEntryValueOffset;
+ @HotSpotVMData(index = 27) @Stable private long gHotSpotVMAddressEntryArrayStride;
+
+ final class VMAddresses implements Iterable<VMAddresses.Address> {
+
+ private final long address;
+
+ public VMAddresses(long address) {
+ this.address = address;
+ }
+
+ public Iterator<VMAddresses.Address> iterator() {
+ return new Iterator<VMAddresses.Address>() {
+
+ private int index = 0;
+
+ private Address currentEntry() {
+ return new Address(address + gHotSpotVMAddressEntryArrayStride * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL name.
+ */
+ public boolean hasNext() {
+ Address entry = currentEntry();
+ return entry.getName() != null;
+ }
+
+ public Address next() {
+ Address entry = currentEntry();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Address extends AbstractConstant {
+
+ Address(long address) {
+ super(address, gHotSpotVMAddressEntryNameOffset, gHotSpotVMAddressEntryValueOffset);
+ }
+
+ @Override
+ public long getValue() {
+ return UNSAFE.getLong(address + valueOffset);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Address[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
+ }
+ }
+ }
+
+ final class Flags implements Iterable<Flags.Flag> {
+
+ private final long address;
+ private final long entrySize;
+ private final long typeOffset;
+ private final long nameOffset;
+ private final long addrOffset;
+
+ public Flags(HashMap<String, VMFields.Field> vmStructs, HashMap<String, VMTypes.Type> vmTypes) {
+ address = vmStructs.get("Flag::flags").getValue();
+ entrySize = vmTypes.get("Flag").getSize();
+ typeOffset = vmStructs.get("Flag::_type").getOffset();
+ nameOffset = vmStructs.get("Flag::_name").getOffset();
+ addrOffset = vmStructs.get("Flag::_addr").getOffset();
+
+ assert vmTypes.get("bool").getSize() == Byte.BYTES;
+ assert vmTypes.get("intx").getSize() == Long.BYTES;
+ assert vmTypes.get("uintx").getSize() == Long.BYTES;
+ }
+
+ public Iterator<Flags.Flag> iterator() {
+ return new Iterator<Flags.Flag>() {
+
+ private int index = 0;
+
+ private Flag current() {
+ return new Flag(address + entrySize * index);
+ }
+
+ /**
+ * The last entry is identified by a NULL name.
+ */
+ public boolean hasNext() {
+ Flag entry = current();
+ return entry.getName() != null;
+ }
+
+ public Flag next() {
+ Flag entry = current();
+ index++;
+ return entry;
+ }
+ };
+ }
+
+ final class Flag {
+
+ private final long entryAddress;
+
+ Flag(long address) {
+ this.entryAddress = address;
+ }
+
+ public String getType() {
+ long typeAddress = UNSAFE.getAddress(entryAddress + typeOffset);
+ return readCString(UNSAFE, typeAddress);
+ }
+
+ public String getName() {
+ long nameAddress = UNSAFE.getAddress(entryAddress + nameOffset);
+ return readCString(UNSAFE, nameAddress);
+ }
+
+ public long getAddr() {
+ return UNSAFE.getAddress(entryAddress + addrOffset);
+ }
+
+ public Object getValue() {
+ switch (getType()) {
+ case "bool":
+ return Boolean.valueOf(UNSAFE.getByte(getAddr()) != 0);
+ case "intx":
+ case "uintx":
+ case "uint64_t":
+ return Long.valueOf(UNSAFE.getLong(getAddr()));
+ case "double":
+ return Double.valueOf(UNSAFE.getDouble(getAddr()));
+ case "ccstr":
+ case "ccstrlist":
+ return readCString(UNSAFE, getAddr());
+ default:
+ throw new JVMCIError(getType());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Flag[type=%s, name=%s, value=%s]", getType(), getName(), getValue());
+ }
+ }
+ }
+
+ @HotSpotVMConstant(name = "ASSERT") @Stable public boolean cAssertions;
+ public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+
+ @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment;
+ @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops;
+ @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime;
+ @HotSpotVMFlag(name = "CITimeEach") @Stable public boolean ciTimeEach;
+ @HotSpotVMFlag(name = "CompileTheWorldStartAt", optional = true) @Stable public int compileTheWorldStartAt;
+ @HotSpotVMFlag(name = "CompileTheWorldStopAt", optional = true) @Stable public int compileTheWorldStopAt;
+ @HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods;
+ @HotSpotVMFlag(name = "HugeMethodLimit") @Stable public int hugeMethodLimit;
+ @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining;
+ @HotSpotVMFlag(name = "JVMCIUseFastLocking") @Stable public boolean useFastLocking;
+ @HotSpotVMFlag(name = "ForceUnreachable") @Stable public boolean forceUnreachable;
+ @HotSpotVMFlag(name = "CodeCacheSegmentSize") @Stable public int codeSegmentSize;
+
+ @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB;
+ @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking;
+ @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction;
+ @HotSpotVMFlag(name = "UseCountLeadingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountLeadingZerosInstruction;
+ @HotSpotVMFlag(name = "UseCountTrailingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountTrailingZerosInstruction;
+ @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics;
+ @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics;
+ @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC;
+ @HotSpotVMFlag(name = "UseConcMarkSweepGC") @Stable public boolean useCMSGC;
+
+ @HotSpotVMFlag(name = "AllocatePrefetchStyle") @Stable public int allocatePrefetchStyle;
+ @HotSpotVMFlag(name = "AllocatePrefetchInstr") @Stable public int allocatePrefetchInstr;
+ @HotSpotVMFlag(name = "AllocatePrefetchLines") @Stable public int allocatePrefetchLines;
+ @HotSpotVMFlag(name = "AllocateInstancePrefetchLines") @Stable public int allocateInstancePrefetchLines;
+ @HotSpotVMFlag(name = "AllocatePrefetchStepSize") @Stable public int allocatePrefetchStepSize;
+ @HotSpotVMFlag(name = "AllocatePrefetchDistance") @Stable public int allocatePrefetchDistance;
+
+ @HotSpotVMFlag(name = "FlightRecorder", optional = true) @Stable public boolean flightRecorder;
+
+ @HotSpotVMField(name = "Universe::_collectedHeap", type = "CollectedHeap*", get = HotSpotVMField.Type.VALUE) @Stable private long universeCollectedHeap;
+ @HotSpotVMField(name = "CollectedHeap::_total_collections", type = "unsigned int", get = HotSpotVMField.Type.OFFSET) @Stable private int collectedHeapTotalCollectionsOffset;
+
+ public long gcTotalCollectionsAddress() {
+ return universeCollectedHeap + collectedHeapTotalCollectionsOffset;
+ }
+
+ @HotSpotVMFlag(name = "ReduceInitialCardMarks") @Stable public boolean useDeferredInitBarriers;
+
+ // Compressed Oops related values.
+ @HotSpotVMFlag(name = "UseCompressedOops") @Stable public boolean useCompressedOops;
+ @HotSpotVMFlag(name = "UseCompressedClassPointers") @Stable public boolean useCompressedClassPointers;
+
+ @HotSpotVMField(name = "Universe::_narrow_oop._base", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long narrowOopBase;
+ @HotSpotVMField(name = "Universe::_narrow_oop._shift", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int narrowOopShift;
+ @HotSpotVMFlag(name = "ObjectAlignmentInBytes") @Stable public int objectAlignment;
+
+ public final int minObjAlignment() {
+ return objectAlignment / heapWordSize;
+ }
+
+ public final int logMinObjAlignment() {
+ return (int) (Math.log(objectAlignment) / Math.log(2));
+ }
+
+ @HotSpotVMType(name = "narrowKlass", get = HotSpotVMType.Type.SIZE) @Stable public int narrowKlassSize;
+ @HotSpotVMField(name = "Universe::_narrow_klass._base", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long narrowKlassBase;
+ @HotSpotVMField(name = "Universe::_narrow_klass._shift", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int narrowKlassShift;
+ @HotSpotVMConstant(name = "LogKlassAlignmentInBytes") @Stable public int logKlassAlignment;
+
+ // CPU capabilities
+ @HotSpotVMFlag(name = "UseSSE") @Stable public int useSSE;
+ @HotSpotVMFlag(name = "UseAVX", archs = {"amd64"}) @Stable public int useAVX;
+
+ @HotSpotVMField(name = "Abstract_VM_Version::_reserve_for_allocation_prefetch", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int abstractVmVersionReserveForAllocationPrefetch;
+
+ // X86 specific values
+ @HotSpotVMField(name = "VM_Version::_cpuFeatures", type = "uint64_t", get = HotSpotVMField.Type.VALUE, archs = {"amd64"}) @Stable public long x86CPUFeatures;
+ @HotSpotVMConstant(name = "VM_Version::CPU_CX8", archs = {"amd64"}) @Stable public long cpuCX8;
+ @HotSpotVMConstant(name = "VM_Version::CPU_CMOV", archs = {"amd64"}) @Stable public long cpuCMOV;
+ @HotSpotVMConstant(name = "VM_Version::CPU_FXSR", archs = {"amd64"}) @Stable public long cpuFXSR;
+ @HotSpotVMConstant(name = "VM_Version::CPU_HT", archs = {"amd64"}) @Stable public long cpuHT;
+ @HotSpotVMConstant(name = "VM_Version::CPU_MMX", archs = {"amd64"}) @Stable public long cpuMMX;
+ @HotSpotVMConstant(name = "VM_Version::CPU_3DNOW_PREFETCH", archs = {"amd64"}) @Stable public long cpu3DNOWPREFETCH;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE", archs = {"amd64"}) @Stable public long cpuSSE;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE2", archs = {"amd64"}) @Stable public long cpuSSE2;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE3", archs = {"amd64"}) @Stable public long cpuSSE3;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSSE3", archs = {"amd64"}) @Stable public long cpuSSSE3;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE4A", archs = {"amd64"}) @Stable public long cpuSSE4A;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE4_1", archs = {"amd64"}) @Stable public long cpuSSE41;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SSE4_2", archs = {"amd64"}) @Stable public long cpuSSE42;
+ @HotSpotVMConstant(name = "VM_Version::CPU_POPCNT", archs = {"amd64"}) @Stable public long cpuPOPCNT;
+ @HotSpotVMConstant(name = "VM_Version::CPU_LZCNT", archs = {"amd64"}) @Stable public long cpuLZCNT;
+ @HotSpotVMConstant(name = "VM_Version::CPU_TSC", archs = {"amd64"}) @Stable public long cpuTSC;
+ @HotSpotVMConstant(name = "VM_Version::CPU_TSCINV", archs = {"amd64"}) @Stable public long cpuTSCINV;
+ @HotSpotVMConstant(name = "VM_Version::CPU_AVX", archs = {"amd64"}) @Stable public long cpuAVX;
+ @HotSpotVMConstant(name = "VM_Version::CPU_AVX2", archs = {"amd64"}) @Stable public long cpuAVX2;
+ @HotSpotVMConstant(name = "VM_Version::CPU_AES", archs = {"amd64"}) @Stable public long cpuAES;
+ @HotSpotVMConstant(name = "VM_Version::CPU_ERMS", archs = {"amd64"}) @Stable public long cpuERMS;
+ @HotSpotVMConstant(name = "VM_Version::CPU_CLMUL", archs = {"amd64"}) @Stable public long cpuCLMUL;
+ @HotSpotVMConstant(name = "VM_Version::CPU_BMI1", archs = {"amd64"}) @Stable public long cpuBMI1;
+
+ // SPARC specific values
+ @HotSpotVMField(name = "VM_Version::_features", type = "int", get = HotSpotVMField.Type.VALUE, archs = {"sparc"}) @Stable public int sparcFeatures;
+ @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int vis3Instructions;
+ @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int vis2Instructions;
+ @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int vis1Instructions;
+ @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int cbcondInstructions;
+ @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 = "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;
+
+ @HotSpotVMField(name = "Klass::_prototype_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int prototypeMarkWordOffset;
+ @HotSpotVMField(name = "Klass::_subklass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int subklassOffset;
+ @HotSpotVMField(name = "Klass::_next_sibling", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int nextSiblingOffset;
+ @HotSpotVMField(name = "Klass::_super_check_offset", type = "juint", get = HotSpotVMField.Type.OFFSET) @Stable public int superCheckOffsetOffset;
+ @HotSpotVMField(name = "Klass::_secondary_super_cache", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySuperCacheOffset;
+ @HotSpotVMField(name = "Klass::_secondary_supers", type = "Array<Klass*>*", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySupersOffset;
+
+ /**
+ * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
+ */
+ @HotSpotVMField(name = "Klass::_java_mirror", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int classMirrorOffset;
+
+ @HotSpotVMField(name = "Klass::_super", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSuperKlassOffset;
+ @HotSpotVMField(name = "Klass::_modifier_flags", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int klassModifierFlagsOffset;
+ @HotSpotVMField(name = "Klass::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassAccessFlagsOffset;
+ @HotSpotVMField(name = "Klass::_layout_helper", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int klassLayoutHelperOffset;
+
+ @HotSpotVMConstant(name = "Klass::_lh_neutral_value") @Stable public int klassLayoutHelperNeutralValue;
+ @HotSpotVMConstant(name = "Klass::_lh_instance_slow_path_bit") @Stable public int klassLayoutHelperInstanceSlowPathBit;
+ @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_shift") @Stable public int layoutHelperLog2ElementSizeShift;
+ @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_mask") @Stable public int layoutHelperLog2ElementSizeMask;
+ @HotSpotVMConstant(name = "Klass::_lh_element_type_shift") @Stable public int layoutHelperElementTypeShift;
+ @HotSpotVMConstant(name = "Klass::_lh_element_type_mask") @Stable public int layoutHelperElementTypeMask;
+ @HotSpotVMConstant(name = "Klass::_lh_header_size_shift") @Stable public int layoutHelperHeaderSizeShift;
+ @HotSpotVMConstant(name = "Klass::_lh_header_size_mask") @Stable public int layoutHelperHeaderSizeMask;
+ @HotSpotVMConstant(name = "Klass::_lh_array_tag_shift") @Stable public int layoutHelperArrayTagShift;
+ @HotSpotVMConstant(name = "Klass::_lh_array_tag_type_value") @Stable public int layoutHelperArrayTagTypeValue;
+ @HotSpotVMConstant(name = "Klass::_lh_array_tag_obj_value") @Stable public int layoutHelperArrayTagObjectValue;
+
+ /**
+ * This filters out the bit that differentiates a type array from an object array.
+ */
+ public int layoutHelperElementTypePrimitiveInPlace() {
+ return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift;
+ }
+
+ /**
+ * Bit pattern in the klass layout helper that can be used to identify arrays.
+ */
+ public final int arrayKlassLayoutHelperIdentifier = 0x80000000;
+
+ @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize;
+ @HotSpotVMField(name = "vtableEntry::_method", type = "Method*", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset;
+
+ @HotSpotVMType(name = "InstanceKlass", get = HotSpotVMType.Type.SIZE) @Stable public int instanceKlassSize;
+ @HotSpotVMField(name = "InstanceKlass::_source_file_name_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassSourceFileNameIndexOffset;
+ @HotSpotVMField(name = "InstanceKlass::_init_state", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassInitStateOffset;
+ @HotSpotVMField(name = "InstanceKlass::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset;
+ @HotSpotVMField(name = "InstanceKlass::_fields", type = "Array<u2>*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassFieldsOffset;
+ @HotSpotVMField(name = "InstanceKlass::_vtable_len", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassVtableLengthOffset;
+
+ @HotSpotVMConstant(name = "InstanceKlass::linked") @Stable public int instanceKlassStateLinked;
+ @HotSpotVMConstant(name = "InstanceKlass::fully_initialized") @Stable public int instanceKlassStateFullyInitialized;
+
+ /**
+ * See {@code InstanceKlass::vtable_start_offset()}.
+ */
+ public final int instanceKlassVtableStartOffset() {
+ return roundUp(instanceKlassSize, heapWordSize);
+ }
+
+ // TODO use CodeUtil method once it's moved from NumUtil
+ private static int roundUp(int number, int mod) {
+ return ((number + mod - 1) / mod) * mod;
+ }
+
+ @HotSpotVMType(name = "arrayOopDesc", get = HotSpotVMType.Type.SIZE) @Stable public int arrayOopDescSize;
+
+ /**
+ * The offset of the array length word in an array object's header.
+ *
+ * See {@code arrayOopDesc::length_offset_in_bytes()}.
+ */
+ public final int arrayOopDescLengthOffset() {
+ return useCompressedClassPointers ? hubOffset + narrowKlassSize : arrayOopDescSize;
+ }
+
+ @HotSpotVMField(name = "Array<int>::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayU1LengthOffset;
+ @HotSpotVMField(name = "Array<u1>::_data", type = "", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayU1DataOffset;
+ @HotSpotVMField(name = "Array<u2>::_data", type = "", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayU2DataOffset;
+ @HotSpotVMField(name = "Array<Klass*>::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset;
+ @HotSpotVMField(name = "Array<Klass*>::_data[0]", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset;
+
+ @HotSpotVMField(name = "ObjArrayKlass::_element_klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayClassElementOffset;
+
+ @HotSpotVMConstant(name = "FieldInfo::access_flags_offset") @Stable public int fieldInfoAccessFlagsOffset;
+ @HotSpotVMConstant(name = "FieldInfo::name_index_offset") @Stable public int fieldInfoNameIndexOffset;
+ @HotSpotVMConstant(name = "FieldInfo::signature_index_offset") @Stable public int fieldInfoSignatureIndexOffset;
+ @HotSpotVMConstant(name = "FieldInfo::initval_index_offset") @Stable public int fieldInfoInitvalIndexOffset;
+ @HotSpotVMConstant(name = "FieldInfo::low_packed_offset") @Stable public int fieldInfoLowPackedOffset;
+ @HotSpotVMConstant(name = "FieldInfo::high_packed_offset") @Stable public int fieldInfoHighPackedOffset;
+ @HotSpotVMConstant(name = "FieldInfo::field_slots") @Stable public int fieldInfoFieldSlots;
+
+ @HotSpotVMConstant(name = "FIELDINFO_TAG_SIZE") @Stable public int fieldInfoTagSize;
+
+ @HotSpotVMConstant(name = "JVM_ACC_FIELD_INTERNAL") @Stable public int jvmAccFieldInternal;
+ @HotSpotVMConstant(name = "JVM_ACC_FIELD_STABLE") @Stable public int jvmAccFieldStable;
+ @HotSpotVMConstant(name = "JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE") @Stable public int jvmAccFieldHasGenericSignature;
+ @HotSpotVMConstant(name = "JVM_ACC_WRITTEN_FLAGS") @Stable public int jvmAccWrittenFlags;
+
+ @HotSpotVMField(name = "Thread::_tlab", type = "ThreadLocalAllocBuffer", get = HotSpotVMField.Type.OFFSET) @Stable public int threadTlabOffset;
+
+ @HotSpotVMField(name = "JavaThread::_anchor", type = "JavaFrameAnchor", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadAnchorOffset;
+ @HotSpotVMField(name = "JavaThread::_threadObj", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectOffset;
+ @HotSpotVMField(name = "JavaThread::_osthread", type = "OSThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadOffset;
+ @HotSpotVMField(name = "JavaThread::_dirty_card_queue", type = "DirtyCardQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadDirtyCardQueueOffset;
+ @HotSpotVMField(name = "JavaThread::_is_method_handle_return", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int threadIsMethodHandleReturnOffset;
+ @HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "ObjPtrQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset;
+ @HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset;
+ @HotSpotVMField(name = "JavaThread::_jvmci_counters", type = "jlong*", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciCountersThreadOffset;
+
+ /**
+ * An invalid value for {@link #rtldDefault}.
+ */
+ public static final long INVALID_RTLD_DEFAULT_HANDLE = 0xDEADFACE;
+
+ /**
+ * Address of the library lookup routine. The C signature of this routine is:
+ *
+ * <pre>
+ * void* (const char *filename, char *ebuf, int ebuflen)
+ * </pre>
+ */
+ @HotSpotVMAddress(name = "os::dll_load") @Stable public long dllLoad;
+
+ /**
+ * Address of the library lookup routine. The C signature of this routine is:
+ *
+ * <pre>
+ * void* (void* handle, const char* name)
+ * </pre>
+ */
+ @HotSpotVMAddress(name = "os::dll_lookup") @Stable public long dllLookup;
+
+ /**
+ * A pseudo-handle which when used as the first argument to {@link #dllLookup} means lookup will
+ * return the first occurrence of the desired symbol using the default library search order. If
+ * this field is {@value #INVALID_RTLD_DEFAULT_HANDLE}, then this capability is not supported on
+ * the current platform.
+ */
+ @HotSpotVMAddress(name = "RTLD_DEFAULT", os = {"bsd", "linux"}) @Stable public long rtldDefault = INVALID_RTLD_DEFAULT_HANDLE;
+
+ /**
+ * This field is used to pass exception objects into and out of the runtime system during
+ * exception handling for compiled code.
+ */
+ @HotSpotVMField(name = "JavaThread::_exception_oop", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionOopOffset;
+ @HotSpotVMField(name = "JavaThread::_exception_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionPcOffset;
+ @HotSpotVMField(name = "ThreadShadow::_pending_exception", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset;
+
+ @HotSpotVMField(name = "JavaThread::_pending_deoptimization", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset;
+ @HotSpotVMField(name = "JavaThread::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset;
+ @HotSpotVMField(name = "JavaThread::_pending_transfer_to_interpreter", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingTransferToInterpreterOffset;
+
+ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset;
+ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset;
+ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset;
+ @HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset;
+
+ public int threadLastJavaSpOffset() {
+ return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset;
+ }
+
+ public int threadLastJavaPcOffset() {
+ return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset;
+ }
+
+ /**
+ * This value is only valid on AMD64.
+ */
+ public int threadLastJavaFpOffset() {
+ // TODO add an assert for AMD64
+ return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset;
+ }
+
+ /**
+ * This value is only valid on SPARC.
+ */
+ public int threadJavaFrameAnchorFlagsOffset() {
+ // TODO add an assert for SPARC
+ return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset;
+ }
+
+ // These are only valid on AMD64.
+ @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", archs = {"amd64"}) @Stable public int runtimeCallStackSize;
+ @HotSpotVMConstant(name = "frame::interpreter_frame_sender_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameSenderSpOffset;
+ @HotSpotVMConstant(name = "frame::interpreter_frame_last_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameLastSpOffset;
+
+ @HotSpotVMField(name = "PtrQueue::_active", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset;
+ @HotSpotVMField(name = "PtrQueue::_buf", type = "void**", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset;
+ @HotSpotVMField(name = "PtrQueue::_index", type = "size_t", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueIndexOffset;
+
+ @HotSpotVMField(name = "OSThread::_interrupted", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadInterruptedOffset;
+
+ @HotSpotVMConstant(name = "markOopDesc::unlocked_value") @Stable public int unlockedMask;
+ @HotSpotVMConstant(name = "markOopDesc::biased_lock_mask_in_place") @Stable public int biasedLockMaskInPlace;
+ @HotSpotVMConstant(name = "markOopDesc::age_mask_in_place") @Stable public int ageMaskInPlace;
+ @HotSpotVMConstant(name = "markOopDesc::epoch_mask_in_place") @Stable public int epochMaskInPlace;
+
+ @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public long markOopDescHashShift;
+ @HotSpotVMConstant(name = "markOopDesc::hash_mask") @Stable public long markOopDescHashMask;
+ @HotSpotVMConstant(name = "markOopDesc::hash_mask_in_place") @Stable public long markOopDescHashMaskInPlace;
+
+ @HotSpotVMConstant(name = "markOopDesc::biased_lock_pattern") @Stable public int biasedLockPattern;
+ @HotSpotVMConstant(name = "markOopDesc::no_hash_in_place") @Stable public int markWordNoHashInPlace;
+ @HotSpotVMConstant(name = "markOopDesc::no_lock_in_place") @Stable public int markWordNoLockInPlace;
+
+ /**
+ * See {@code markOopDesc::prototype()}.
+ */
+ public long arrayPrototypeMarkWord() {
+ return markWordNoHashInPlace | markWordNoLockInPlace;
+ }
+
+ /**
+ * See {@code markOopDesc::copy_set_hash()}.
+ */
+ public long tlabIntArrayMarkWord() {
+ long tmp = arrayPrototypeMarkWord() & (~markOopDescHashMaskInPlace);
+ tmp |= ((0x2 & markOopDescHashMask) << markOopDescHashShift);
+ return tmp;
+ }
+
+ /**
+ * Mark word right shift to get identity hash code.
+ */
+ @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public int identityHashCodeShift;
+
+ /**
+ * Identity hash code value when uninitialized.
+ */
+ @HotSpotVMConstant(name = "markOopDesc::no_hash") @Stable public int uninitializedIdentityHashCodeValue;
+
+ @HotSpotVMField(name = "Method::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset;
+ @HotSpotVMField(name = "Method::_constMethod", type = "ConstMethod*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset;
+ @HotSpotVMField(name = "Method::_intrinsic_id", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset;
+ @HotSpotVMField(name = "Method::_flags", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
+ @HotSpotVMField(name = "Method::_vtable_index", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset;
+
+ @HotSpotVMConstant(name = "Method::_jfr_towrite") @Stable public int methodFlagsJfrTowrite;
+ @HotSpotVMConstant(name = "Method::_caller_sensitive") @Stable public int methodFlagsCallerSensitive;
+ @HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline;
+ @HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline;
+ @HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden;
+ @HotSpotVMConstant(name = "Method::nonvirtual_vtable_index") @Stable public int nonvirtualVtableIndex;
+ @HotSpotVMConstant(name = "Method::invalid_vtable_index") @Stable public int invalidVtableIndex;
+
+ @HotSpotVMConstant(name = "InvocationEntryBci") @Stable public int invocationEntryBci;
+
+ @HotSpotVMField(name = "JVMCIEnv::_task", type = "CompileTask*", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciEnvTaskOffset;
+ @HotSpotVMField(name = "JVMCIEnv::_jvmti_can_hotswap_or_post_breakpoint", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciEnvJvmtiCanHotswapOrPostBreakpointOffset;
+ @HotSpotVMField(name = "CompileTask::_num_inlined_bytecodes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int compileTaskNumInlinedBytecodesOffset;
+
+ /**
+ * See {@code Method::extra_stack_entries()}.
+ */
+ @HotSpotVMConstant(name = "Method::extra_stack_entries_for_jsr292") @Stable public int extraStackEntries;
+
+ @HotSpotVMField(name = "ConstMethod::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodConstantsOffset;
+ @HotSpotVMField(name = "ConstMethod::_flags", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodFlagsOffset;
+ @HotSpotVMField(name = "ConstMethod::_code_size", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodCodeSizeOffset;
+ @HotSpotVMField(name = "ConstMethod::_name_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodNameIndexOffset;
+ @HotSpotVMField(name = "ConstMethod::_signature_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodSignatureIndexOffset;
+ @HotSpotVMField(name = "ConstMethod::_max_stack", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodMaxStackOffset;
+ @HotSpotVMField(name = "ConstMethod::_max_locals", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodMaxLocalsOffset;
+
+ @HotSpotVMConstant(name = "ConstMethod::_has_linenumber_table") @Stable public int constMethodHasLineNumberTable;
+ @HotSpotVMConstant(name = "ConstMethod::_has_localvariable_table") @Stable public int constMethodHasLocalVariableTable;
+ @HotSpotVMConstant(name = "ConstMethod::_has_exception_table") @Stable public int constMethodHasExceptionTable;
+
+ @HotSpotVMType(name = "ExceptionTableElement", get = HotSpotVMType.Type.SIZE) @Stable public int exceptionTableElementSize;
+ @HotSpotVMField(name = "ExceptionTableElement::start_pc", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int exceptionTableElementStartPcOffset;
+ @HotSpotVMField(name = "ExceptionTableElement::end_pc", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int exceptionTableElementEndPcOffset;
+ @HotSpotVMField(name = "ExceptionTableElement::handler_pc", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int exceptionTableElementHandlerPcOffset;
+ @HotSpotVMField(name = "ExceptionTableElement::catch_type_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int exceptionTableElementCatchTypeIndexOffset;
+
+ @HotSpotVMType(name = "LocalVariableTableElement", get = HotSpotVMType.Type.SIZE) @Stable public int localVariableTableElementSize;
+ @HotSpotVMField(name = "LocalVariableTableElement::start_bci", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementStartBciOffset;
+ @HotSpotVMField(name = "LocalVariableTableElement::length", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementLengthOffset;
+ @HotSpotVMField(name = "LocalVariableTableElement::name_cp_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementNameCpIndexOffset;
+ @HotSpotVMField(name = "LocalVariableTableElement::descriptor_cp_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementDescriptorCpIndexOffset;
+ @HotSpotVMField(name = "LocalVariableTableElement::signature_cp_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementSignatureCpIndexOffset;
+ @HotSpotVMField(name = "LocalVariableTableElement::slot", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int localVariableTableElementSlotOffset;
+
+ @HotSpotVMType(name = "ConstantPool", get = HotSpotVMType.Type.SIZE) @Stable public int constantPoolSize;
+ @HotSpotVMField(name = "ConstantPool::_tags", type = "Array<u1>*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolTagsOffset;
+ @HotSpotVMField(name = "ConstantPool::_pool_holder", type = "InstanceKlass*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolHolderOffset;
+ @HotSpotVMField(name = "ConstantPool::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolLengthOffset;
+
+ @HotSpotVMConstant(name = "ConstantPool::CPCACHE_INDEX_TAG") @Stable public int constantPoolCpCacheIndexTag;
+
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Utf8") @Stable public int jvmConstantUtf8;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Integer") @Stable public int jvmConstantInteger;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Long") @Stable public int jvmConstantLong;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Float") @Stable public int jvmConstantFloat;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Double") @Stable public int jvmConstantDouble;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Class") @Stable public int jvmConstantClass;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_UnresolvedClass") @Stable public int jvmConstantUnresolvedClass;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_UnresolvedClassInError") @Stable public int jvmConstantUnresolvedClassInError;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_String") @Stable public int jvmConstantString;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Fieldref") @Stable public int jvmConstantFieldref;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_Methodref") @Stable public int jvmConstantMethodref;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_InterfaceMethodref") @Stable public int jvmConstantInterfaceMethodref;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_NameAndType") @Stable public int jvmConstantNameAndType;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_MethodHandle") @Stable public int jvmConstantMethodHandle;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_MethodHandleInError") @Stable public int jvmConstantMethodHandleInError;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_MethodType") @Stable public int jvmConstantMethodType;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_MethodTypeInError") @Stable public int jvmConstantMethodTypeInError;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_InvokeDynamic") @Stable public int jvmConstantInvokeDynamic;
+
+ @HotSpotVMConstant(name = "JVM_CONSTANT_ExternalMax") @Stable public int jvmConstantExternalMax;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_InternalMin") @Stable public int jvmConstantInternalMin;
+ @HotSpotVMConstant(name = "JVM_CONSTANT_InternalMax") @Stable public int jvmConstantInternalMax;
+
+ @HotSpotVMConstant(name = "HeapWordSize") @Stable public int heapWordSize;
+
+ @HotSpotVMType(name = "Symbol*", get = HotSpotVMType.Type.SIZE) @Stable public int symbolPointerSize;
+ @HotSpotVMField(name = "Symbol::_length", type = "unsigned short", get = HotSpotVMField.Type.OFFSET) @Stable public int symbolLengthOffset;
+ @HotSpotVMField(name = "Symbol::_body[0]", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int symbolBodyOffset;
+
+ @HotSpotVMField(name = "vmSymbols::_symbols[0]", type = "Symbol*", get = HotSpotVMField.Type.ADDRESS) @Stable public long vmSymbolsSymbols;
+ @HotSpotVMConstant(name = "vmSymbols::FIRST_SID") @Stable public int vmSymbolsFirstSID;
+ @HotSpotVMConstant(name = "vmSymbols::SID_LIMIT") @Stable public int vmSymbolsSIDLimit;
+
+ @HotSpotVMConstant(name = "JVM_ACC_HAS_FINALIZER") @Stable public int klassHasFinalizerFlag;
+
+ // Modifier.SYNTHETIC is not public so we get it via vmStructs.
+ @HotSpotVMConstant(name = "JVM_ACC_SYNTHETIC") @Stable public int syntheticFlag;
+
+ /**
+ * @see HotSpotResolvedObjectTypeImpl#createField
+ */
+ @HotSpotVMConstant(name = "JVM_RECOGNIZED_FIELD_MODIFIERS") @Stable public int recognizedFieldModifiers;
+
+ /**
+ * Bit pattern that represents a non-oop. Neither the high bits nor the low bits of this value
+ * are allowed to look like (respectively) the high or low bits of a real oop.
+ */
+ @HotSpotVMField(name = "Universe::_non_oop_bits", type = "intptr_t", get = HotSpotVMField.Type.VALUE) @Stable public long nonOopBits;
+
+ @HotSpotVMField(name = "StubRoutines::_verify_oop_count", type = "jint", get = HotSpotVMField.Type.ADDRESS) @Stable public long verifyOopCounterAddress;
+ @HotSpotVMField(name = "Universe::_verify_oop_mask", type = "uintptr_t", get = HotSpotVMField.Type.VALUE) @Stable public long verifyOopMask;
+ @HotSpotVMField(name = "Universe::_verify_oop_bits", type = "uintptr_t", get = HotSpotVMField.Type.VALUE) @Stable public long verifyOopBits;
+ @HotSpotVMField(name = "Universe::_base_vtable_size", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int universeBaseVtableSize;
+
+ public final int baseVtableLength() {
+ return universeBaseVtableSize / vtableEntrySize;
+ }
+
+ @HotSpotVMField(name = "CollectedHeap::_barrier_set", type = "BarrierSet*", get = HotSpotVMField.Type.OFFSET) @Stable public int collectedHeapBarrierSetOffset;
+
+ @HotSpotVMField(name = "HeapRegion::LogOfHRGrainBytes", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int logOfHRGrainBytes;
+
+ @HotSpotVMField(name = "BarrierSet::_fake_rtti", type = "BarrierSet::FakeRtti", get = HotSpotVMField.Type.OFFSET) @Stable private int barrierSetFakeRttiOffset;
+ @HotSpotVMConstant(name = "BarrierSet::CardTableModRef") @Stable public int barrierSetCardTableModRef;
+ @HotSpotVMConstant(name = "BarrierSet::CardTableForRS") @Stable public int barrierSetCardTableForRS;
+ @HotSpotVMConstant(name = "BarrierSet::CardTableExtension") @Stable public int barrierSetCardTableExtension;
+ @HotSpotVMConstant(name = "BarrierSet::G1SATBCT") @Stable public int barrierSetG1SATBCT;
+ @HotSpotVMConstant(name = "BarrierSet::G1SATBCTLogging") @Stable public int barrierSetG1SATBCTLogging;
+ @HotSpotVMConstant(name = "BarrierSet::ModRef") @Stable public int barrierSetModRef;
+
+ @HotSpotVMField(name = "BarrierSet::FakeRtti::_concrete_tag", type = "BarrierSet::Name", get = HotSpotVMField.Type.OFFSET) @Stable private int fakeRttiConcreteTagOffset;
+
+ @HotSpotVMField(name = "CardTableModRefBS::byte_map_base", type = "jbyte*", get = HotSpotVMField.Type.OFFSET) @Stable private int cardTableModRefBSByteMapBaseOffset;
+ @HotSpotVMConstant(name = "CardTableModRefBS::card_shift") @Stable public int cardTableModRefBSCardShift;
+
+ @HotSpotVMConstant(name = "CardTableModRefBS::dirty_card") @Stable public byte dirtyCardValue;
+ @HotSpotVMConstant(name = "G1SATBCardTableModRefBS::g1_young_gen") @Stable public byte g1YoungCardValue;
+
+ private final long cardtableStartAddress;
+ private final int cardtableShift;
+
+ public long cardtableStartAddress() {
+ if (cardtableStartAddress == -1) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+ return cardtableStartAddress;
+ }
+
+ public int cardtableShift() {
+ if (cardtableShift == -1) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+ return cardtableShift;
+ }
+
+ @HotSpotVMField(name = "os::_polling_page", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long safepointPollingAddress;
+
+ // G1 Collector Related Values.
+
+ public int g1CardQueueIndexOffset() {
+ return javaThreadDirtyCardQueueOffset + ptrQueueIndexOffset;
+ }
+
+ public int g1CardQueueBufferOffset() {
+ return javaThreadDirtyCardQueueOffset + ptrQueueBufferOffset;
+ }
+
+ public int g1SATBQueueMarkingOffset() {
+ return javaThreadSatbMarkQueueOffset + ptrQueueActiveOffset;
+ }
+
+ public int g1SATBQueueIndexOffset() {
+ return javaThreadSatbMarkQueueOffset + ptrQueueIndexOffset;
+ }
+
+ public int g1SATBQueueBufferOffset() {
+ return javaThreadSatbMarkQueueOffset + ptrQueueBufferOffset;
+ }
+
+ @HotSpotVMField(name = "java_lang_Class::_klass_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int klassOffset;
+ @HotSpotVMField(name = "java_lang_Class::_array_klass_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int arrayKlassOffset;
+
+ @HotSpotVMField(name = "Method::_method_counters", type = "MethodCounters*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodCountersOffset;
+ @HotSpotVMField(name = "Method::_method_data", type = "MethodData*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOffset;
+ @HotSpotVMField(name = "Method::_from_compiled_entry", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int methodCompiledEntryOffset;
+ @HotSpotVMField(name = "Method::_code", type = "nmethod*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodCodeOffset;
+
+ @HotSpotVMField(name = "MethodCounters::_invocation_counter", type = "InvocationCounter", get = HotSpotVMField.Type.OFFSET) @Stable public int invocationCounterOffset;
+ @HotSpotVMField(name = "MethodCounters::_backedge_counter", type = "InvocationCounter", get = HotSpotVMField.Type.OFFSET) @Stable public int backedgeCounterOffset;
+ @HotSpotVMConstant(name = "InvocationCounter::count_increment") @Stable public int invocationCounterIncrement;
+ @HotSpotVMConstant(name = "InvocationCounter::count_shift") @Stable public int invocationCounterShift;
+
+ @HotSpotVMField(name = "MethodData::_size", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataSize;
+ @HotSpotVMField(name = "MethodData::_data_size", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataDataSize;
+ @HotSpotVMField(name = "MethodData::_data[0]", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopDataOffset;
+ @HotSpotVMField(name = "MethodData::_trap_hist._array[0]", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopTrapHistoryOffset;
+ @HotSpotVMField(name = "MethodData::_jvmci_ir_size", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataIRSizeOffset;
+
+ @HotSpotVMField(name = "nmethod::_verified_entry_point", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset;
+ @HotSpotVMField(name = "nmethod::_comp_level", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodCompLevelOffset;
+
+ @HotSpotVMConstant(name = "CompLevel_full_optimization") @Stable public int compilationLevelFullOptimization;
+
+ @HotSpotVMType(name = "BasicLock", get = HotSpotVMType.Type.SIZE) @Stable public int basicLockSize;
+ @HotSpotVMField(name = "BasicLock::_displaced_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int basicLockDisplacedHeaderOffset;
+
+ @HotSpotVMField(name = "Thread::_allocated_bytes", type = "jlong", get = HotSpotVMField.Type.OFFSET) @Stable public int threadAllocatedBytesOffset;
+
+ @HotSpotVMFlag(name = "TLABWasteIncrement") @Stable public int tlabRefillWasteIncrement;
+
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferStartOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferEndOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferTopOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_pf_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferPfTopOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_slow_allocations", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferSlowAllocationsOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_fast_refill_waste", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferFastRefillWasteOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_number_of_refills", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferNumberOfRefillsOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_refill_waste_limit", type = "size_t", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferRefillWasteLimitOffset;
+ @HotSpotVMField(name = "ThreadLocalAllocBuffer::_desired_size", type = "size_t", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferDesiredSizeOffset;
+
+ public int tlabSlowAllocationsOffset() {
+ return threadTlabOffset + threadLocalAllocBufferSlowAllocationsOffset;
+ }
+
+ public int tlabFastRefillWasteOffset() {
+ return threadTlabOffset + threadLocalAllocBufferFastRefillWasteOffset;
+ }
+
+ public int tlabNumberOfRefillsOffset() {
+ return threadTlabOffset + threadLocalAllocBufferNumberOfRefillsOffset;
+ }
+
+ public int tlabRefillWasteLimitOffset() {
+ return threadTlabOffset + threadLocalAllocBufferRefillWasteLimitOffset;
+ }
+
+ public int threadTlabSizeOffset() {
+ return threadTlabOffset + threadLocalAllocBufferDesiredSizeOffset;
+ }
+
+ public int threadTlabStartOffset() {
+ return threadTlabOffset + threadLocalAllocBufferStartOffset;
+ }
+
+ public int threadTlabEndOffset() {
+ return threadTlabOffset + threadLocalAllocBufferEndOffset;
+ }
+
+ public int threadTlabTopOffset() {
+ return threadTlabOffset + threadLocalAllocBufferTopOffset;
+ }
+
+ public int threadTlabPfTopOffset() {
+ return threadTlabOffset + threadLocalAllocBufferPfTopOffset;
+ }
+
+ /**
+ * See: {@code ThreadLocalAllocBuffer::end_reserve()}.
+ */
+ public final int threadLocalAllocBufferEndReserve() {
+ final int typeSizeInBytes = roundUp(arrayOopDescLengthOffset() + Integer.BYTES, heapWordSize);
+ // T_INT arrays need not be 8 byte aligned.
+ final int reserveSize = typeSizeInBytes / heapWordSize;
+ return Integer.max(reserveSize, abstractVmVersionReserveForAllocationPrefetch);
+ }
+
+ /**
+ * See: {@code ThreadLocalAllocBuffer::alignment_reserve()}.
+ */
+ public final int tlabAlignmentReserve() {
+ return roundUp(threadLocalAllocBufferEndReserve(), minObjAlignment());
+ }
+
+ @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
+
+ // FIXME This is only temporary until the GC code is changed.
+ @HotSpotVMField(name = "CompilerToVM::_supports_inline_contig_alloc", type = "bool", get = HotSpotVMField.Type.VALUE) @Stable public boolean inlineContiguousAllocationSupported;
+ @HotSpotVMField(name = "CompilerToVM::_heap_end_addr", type = "HeapWord**", get = HotSpotVMField.Type.VALUE) @Stable public long heapEndAddress;
+ @HotSpotVMField(name = "CompilerToVM::_heap_top_addr", type = "HeapWord**", get = HotSpotVMField.Type.VALUE) @Stable public long heapTopAddress;
+
+ /**
+ * The DataLayout header size is the same as the cell size.
+ */
+ @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutHeaderSize;
+ @HotSpotVMField(name = "DataLayout::_header._struct._tag", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutTagOffset;
+ @HotSpotVMField(name = "DataLayout::_header._struct._flags", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutFlagsOffset;
+ @HotSpotVMField(name = "DataLayout::_header._struct._bci", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutBCIOffset;
+ @HotSpotVMField(name = "DataLayout::_cells[0]", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutCellsOffset;
+ @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutCellSize;
+
+ @HotSpotVMConstant(name = "DataLayout::no_tag") @Stable public int dataLayoutNoTag;
+ @HotSpotVMConstant(name = "DataLayout::bit_data_tag") @Stable public int dataLayoutBitDataTag;
+ @HotSpotVMConstant(name = "DataLayout::counter_data_tag") @Stable public int dataLayoutCounterDataTag;
+ @HotSpotVMConstant(name = "DataLayout::jump_data_tag") @Stable public int dataLayoutJumpDataTag;
+ @HotSpotVMConstant(name = "DataLayout::receiver_type_data_tag") @Stable public int dataLayoutReceiverTypeDataTag;
+ @HotSpotVMConstant(name = "DataLayout::virtual_call_data_tag") @Stable public int dataLayoutVirtualCallDataTag;
+ @HotSpotVMConstant(name = "DataLayout::ret_data_tag") @Stable public int dataLayoutRetDataTag;
+ @HotSpotVMConstant(name = "DataLayout::branch_data_tag") @Stable public int dataLayoutBranchDataTag;
+ @HotSpotVMConstant(name = "DataLayout::multi_branch_data_tag") @Stable public int dataLayoutMultiBranchDataTag;
+ @HotSpotVMConstant(name = "DataLayout::arg_info_data_tag") @Stable public int dataLayoutArgInfoDataTag;
+ @HotSpotVMConstant(name = "DataLayout::call_type_data_tag") @Stable public int dataLayoutCallTypeDataTag;
+ @HotSpotVMConstant(name = "DataLayout::virtual_call_type_data_tag") @Stable public int dataLayoutVirtualCallTypeDataTag;
+ @HotSpotVMConstant(name = "DataLayout::parameters_type_data_tag") @Stable public int dataLayoutParametersTypeDataTag;
+ @HotSpotVMConstant(name = "DataLayout::speculative_trap_data_tag") @Stable public int dataLayoutSpeculativeTrapDataTag;
+
+ @HotSpotVMFlag(name = "BciProfileWidth") @Stable public int bciProfileWidth;
+ @HotSpotVMFlag(name = "TypeProfileWidth") @Stable public int typeProfileWidth;
+ @HotSpotVMFlag(name = "MethodProfileWidth") @Stable public int methodProfileWidth;
+
+ @HotSpotVMField(name = "CodeBlob::_code_offset", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable private int codeBlobCodeOffsetOffset;
+ @HotSpotVMField(name = "DeoptimizationBlob::_unpack_offset", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable private int deoptimizationBlobUnpackOffsetOffset;
+ @HotSpotVMField(name = "DeoptimizationBlob::_uncommon_trap_offset", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable private int deoptimizationBlobUncommonTrapOffsetOffset;
+
+ @HotSpotVMField(name = "SharedRuntime::_ic_miss_blob", type = "RuntimeStub*", get = HotSpotVMField.Type.VALUE) @Stable private long inlineCacheMissBlob;
+ @HotSpotVMField(name = "SharedRuntime::_wrong_method_blob", type = "RuntimeStub*", get = HotSpotVMField.Type.VALUE) @Stable private long wrongMethodBlob;
+ @HotSpotVMField(name = "SharedRuntime::_deopt_blob", type = "DeoptimizationBlob*", get = HotSpotVMField.Type.VALUE) @Stable private long deoptBlob;
+
+ @HotSpotVMManual(name = "SharedRuntime::get_ic_miss_stub()") public final long inlineCacheMissStub;
+ @HotSpotVMManual(name = "SharedRuntime::get_handle_wrong_method_stub()") public final long handleWrongMethodStub;
+
+ @HotSpotVMManual(name = "SharedRuntime::deopt_blob()->unpack()") public final long handleDeoptStub;
+ @HotSpotVMManual(name = "SharedRuntime::deopt_blob()->uncommon_trap()") public final long uncommonTrapStub;
+
+ @HotSpotVMField(name = "CodeCache::_low_bound", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long codeCacheLowBound;
+ @HotSpotVMField(name = "CodeCache::_high_bound", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long codeCacheHighBound;
+
+ @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
+ @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub;
+ @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_encryptAESCrypt", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingEncryptAESCryptStub;
+ @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_decryptAESCrypt", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingDecryptAESCryptStub;
+ @HotSpotVMField(name = "StubRoutines::_updateBytesCRC32", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long updateBytesCRC32Stub;
+ @HotSpotVMField(name = "StubRoutines::_crc_table_adr", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long crcTableAddress;
+
+ @HotSpotVMField(name = "StubRoutines::_jbyte_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopArraycopyUninit;
+ @HotSpotVMField(name = "StubRoutines::_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopDisjointArraycopyUninit;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopyUninit;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopyUninit;
+ @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopyUninit;
+ @HotSpotVMField(name = "StubRoutines::_unsafe_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long unsafeArraycopy;
+ @HotSpotVMField(name = "StubRoutines::_generic_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long genericArraycopy;
+
+ @HotSpotVMAddress(name = "JVMCIRuntime::new_instance") @Stable public long newInstanceAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::new_array") @Stable public long newArrayAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::new_multi_array") @Stable public long newMultiArrayAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::dynamic_new_array") @Stable public long dynamicNewArrayAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::dynamic_new_instance") @Stable public long dynamicNewInstanceAddress;
+
+ @HotSpotVMAddress(name = "JVMCIRuntime::thread_is_interrupted") @Stable public long threadIsInterruptedAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::vm_message") @Stable public long vmMessageAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::identity_hash_code") @Stable public long identityHashCodeAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::exception_handler_for_pc") @Stable public long exceptionHandlerForPcAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::monitorenter") @Stable public long monitorenterAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::monitorexit") @Stable public long monitorexitAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::create_null_exception") @Stable public long createNullPointerExceptionAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::create_out_of_bounds_exception") @Stable public long createOutOfBoundsExceptionAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::log_primitive") @Stable public long logPrimitiveAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::log_object") @Stable public long logObjectAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::log_printf") @Stable public long logPrintfAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::vm_error") @Stable public long vmErrorAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::load_and_clear_exception") @Stable public long loadAndClearExceptionAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::write_barrier_pre") @Stable public long writeBarrierPreAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::write_barrier_post") @Stable public long writeBarrierPostAddress;
+ @HotSpotVMAddress(name = "JVMCIRuntime::validate_object") @Stable public long validateObject;
+
+ @HotSpotVMAddress(name = "JVMCIRuntime::test_deoptimize_call_int") @Stable public long testDeoptimizeCallInt;
+
+ @HotSpotVMAddress(name = "SharedRuntime::register_finalizer") @Stable public long registerFinalizerAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::exception_handler_for_return_address") @Stable public long exceptionHandlerForReturnAddressAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::OSR_migration_end") @Stable public long osrMigrationEndAddress;
+
+ @HotSpotVMAddress(name = "os::javaTimeMillis") @Stable public long javaTimeMillisAddress;
+ @HotSpotVMAddress(name = "os::javaTimeNanos") @Stable public long javaTimeNanosAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dsin") @Stable public long arithmeticSinAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dcos") @Stable public long arithmeticCosAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dtan") @Stable public long arithmeticTanAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dexp") @Stable public long arithmeticExpAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dlog") @Stable public long arithmeticLogAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::dlog10") @Stable public long arithmeticLog10Address;
+ @HotSpotVMAddress(name = "SharedRuntime::dpow") @Stable public long arithmeticPowAddress;
+
+ @HotSpotVMFlag(name = "JVMCICounterSize") @Stable public int jvmciCountersSize;
+
+ @HotSpotVMAddress(name = "Deoptimization::fetch_unroll_info") @Stable public long deoptimizationFetchUnrollInfo;
+ @HotSpotVMAddress(name = "Deoptimization::uncommon_trap") @Stable public long deoptimizationUncommonTrap;
+ @HotSpotVMAddress(name = "Deoptimization::unpack_frames") @Stable public long deoptimizationUnpackFrames;
+
+ @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_class_check") @Stable public int deoptReasonClassCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_array_check") @Stable public int deoptReasonArrayCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_unreached0") @Stable public int deoptReasonUnreached0;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_type_checked_inlining") @Stable public int deoptReasonTypeCheckInlining;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_optimized_type_check") @Stable public int deoptReasonOptimizedTypeCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_not_compiled_exception_handler") @Stable public int deoptReasonNotCompiledExceptionHandler;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_unresolved") @Stable public int deoptReasonUnresolved;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_jsr_mismatch") @Stable public int deoptReasonJsrMismatch;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_div0_check") @Stable public int deoptReasonDiv0Check;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_aliasing") @Stable public int deoptReasonAliasing;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_transfer_to_interpreter") @Stable public int deoptReasonTransferToInterpreter;
+ @HotSpotVMConstant(name = "Deoptimization::Reason_LIMIT") @Stable public int deoptReasonOSROffset;
+
+ @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone;
+ @HotSpotVMConstant(name = "Deoptimization::Action_maybe_recompile") @Stable public int deoptActionMaybeRecompile;
+ @HotSpotVMConstant(name = "Deoptimization::Action_reinterpret") @Stable public int deoptActionReinterpret;
+ @HotSpotVMConstant(name = "Deoptimization::Action_make_not_entrant") @Stable public int deoptActionMakeNotEntrant;
+ @HotSpotVMConstant(name = "Deoptimization::Action_make_not_compilable") @Stable public int deoptActionMakeNotCompilable;
+
+ @HotSpotVMConstant(name = "Deoptimization::_action_bits") @Stable public int deoptimizationActionBits;
+ @HotSpotVMConstant(name = "Deoptimization::_reason_bits") @Stable public int deoptimizationReasonBits;
+ @HotSpotVMConstant(name = "Deoptimization::_debug_id_bits") @Stable public int deoptimizationDebugIdBits;
+ @HotSpotVMConstant(name = "Deoptimization::_action_shift") @Stable public int deoptimizationActionShift;
+ @HotSpotVMConstant(name = "Deoptimization::_reason_shift") @Stable public int deoptimizationReasonShift;
+ @HotSpotVMConstant(name = "Deoptimization::_debug_id_shift") @Stable public int deoptimizationDebugIdShift;
+
+ @HotSpotVMConstant(name = "Deoptimization::Unpack_deopt") @Stable public int deoptimizationUnpackDeopt;
+ @HotSpotVMConstant(name = "Deoptimization::Unpack_exception") @Stable public int deoptimizationUnpackException;
+ @HotSpotVMConstant(name = "Deoptimization::Unpack_uncommon_trap") @Stable public int deoptimizationUnpackUncommonTrap;
+ @HotSpotVMConstant(name = "Deoptimization::Unpack_reexecute") @Stable public int deoptimizationUnpackReexecute;
+
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_size_of_deoptimized_frame", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset;
+ @HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset;
+
+ @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic;
+ @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual;
+ @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic;
+ @HotSpotVMConstant(name = "vmIntrinsics::_linkToSpecial") @Stable public int vmIntrinsicLinkToSpecial;
+ @HotSpotVMConstant(name = "vmIntrinsics::_linkToInterface") @Stable public int vmIntrinsicLinkToInterface;
+
+ @HotSpotVMConstant(name = "JVMCIEnv::ok") @Stable public int codeInstallResultOk;
+ @HotSpotVMConstant(name = "JVMCIEnv::dependencies_failed") @Stable public int codeInstallResultDependenciesFailed;
+ @HotSpotVMConstant(name = "JVMCIEnv::dependencies_invalid") @Stable public int codeInstallResultDependenciesInvalid;
+ @HotSpotVMConstant(name = "JVMCIEnv::cache_full") @Stable public int codeInstallResultCacheFull;
+ @HotSpotVMConstant(name = "JVMCIEnv::code_too_large") @Stable public int codeInstallResultCodeTooLarge;
+
+ public String getCodeInstallResultDescription(int codeInstallResult) {
+ if (codeInstallResult == codeInstallResultOk) {
+ return "ok";
+ }
+ if (codeInstallResult == codeInstallResultDependenciesFailed) {
+ return "dependencies failed";
+ }
+ if (codeInstallResult == codeInstallResultDependenciesInvalid) {
+ return "dependencies invalid";
+ }
+ if (codeInstallResult == codeInstallResultCacheFull) {
+ return "code cache is full";
+ }
+ if (codeInstallResult == codeInstallResultCodeTooLarge) {
+ return "code is too large";
+ }
+ assert false : codeInstallResult;
+ return "unknown";
+ }
+
+ @HotSpotVMConstant(name = "CompilerToVM::KLASS_TAG") @Stable public int compilerToVMKlassTag;
+ @HotSpotVMConstant(name = "CompilerToVM::SYMBOL_TAG") @Stable public int compilerToVMSymbolTag;
+
+ // Checkstyle: stop
+ @HotSpotVMConstant(name = "CodeInstaller::VERIFIED_ENTRY") @Stable public int MARKID_VERIFIED_ENTRY;
+ @HotSpotVMConstant(name = "CodeInstaller::UNVERIFIED_ENTRY") @Stable public int MARKID_UNVERIFIED_ENTRY;
+ @HotSpotVMConstant(name = "CodeInstaller::OSR_ENTRY") @Stable public int MARKID_OSR_ENTRY;
+ @HotSpotVMConstant(name = "CodeInstaller::EXCEPTION_HANDLER_ENTRY") @Stable public int MARKID_EXCEPTION_HANDLER_ENTRY;
+ @HotSpotVMConstant(name = "CodeInstaller::DEOPT_HANDLER_ENTRY") @Stable public int MARKID_DEOPT_HANDLER_ENTRY;
+ @HotSpotVMConstant(name = "CodeInstaller::INVOKEINTERFACE") @Stable public int MARKID_INVOKEINTERFACE;
+ @HotSpotVMConstant(name = "CodeInstaller::INVOKEVIRTUAL") @Stable public int MARKID_INVOKEVIRTUAL;
+ @HotSpotVMConstant(name = "CodeInstaller::INVOKESTATIC") @Stable public int MARKID_INVOKESTATIC;
+ @HotSpotVMConstant(name = "CodeInstaller::INVOKESPECIAL") @Stable public int MARKID_INVOKESPECIAL;
+ @HotSpotVMConstant(name = "CodeInstaller::INLINE_INVOKE") @Stable public int MARKID_INLINE_INVOKE;
+ @HotSpotVMConstant(name = "CodeInstaller::POLL_NEAR") @Stable public int MARKID_POLL_NEAR;
+ @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int MARKID_POLL_RETURN_NEAR;
+ @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int MARKID_POLL_FAR;
+ @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int MARKID_POLL_RETURN_FAR;
+ @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_ADDRESS") @Stable public int MARKID_CARD_TABLE_ADDRESS;
+ @HotSpotVMConstant(name = "CodeInstaller::HEAP_TOP_ADDRESS") @Stable public int MARKID_HEAP_TOP_ADDRESS;
+ @HotSpotVMConstant(name = "CodeInstaller::HEAP_END_ADDRESS") @Stable public int MARKID_HEAP_END_ADDRESS;
+ @HotSpotVMConstant(name = "CodeInstaller::NARROW_KLASS_BASE_ADDRESS") @Stable public int MARKID_NARROW_KLASS_BASE_ADDRESS;
+ @HotSpotVMConstant(name = "CodeInstaller::CRC_TABLE_ADDRESS") @Stable public int MARKID_CRC_TABLE_ADDRESS;
+ @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int MARKID_INVOKE_INVALID;
+
+ // Checkstyle: resume
+
+ private boolean check() {
+ for (Field f : getClass().getDeclaredFields()) {
+ int modifiers = f.getModifiers();
+ if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
+ assert Modifier.isFinal(modifiers) || f.getAnnotation(Stable.class) != null : "field should either be final or @Stable: " + f;
+ }
+ }
+
+ assert codeEntryAlignment > 0 : codeEntryAlignment;
+ assert(layoutHelperArrayTagObjectValue & (1 << (Integer.SIZE - 1))) != 0 : "object array must have first bit set";
+ assert(layoutHelperArrayTagTypeValue & (1 << (Integer.SIZE - 1))) != 0 : "type array must have first bit set";
+
+ return true;
+ }
+
+ /**
+ * A compact representation of the different encoding strategies for Objects and metadata.
+ */
+ public static class CompressEncoding {
+ public final long base;
+ public final int shift;
+ public final int alignment;
+
+ CompressEncoding(long base, int shift, int alignment) {
+ this.base = base;
+ this.shift = shift;
+ this.alignment = alignment;
+ }
+
+ public int compress(long ptr) {
+ if (ptr == 0L) {
+ return 0;
+ } else {
+ return (int) ((ptr - base) >>> shift);
+ }
+ }
+
+ public long uncompress(int ptr) {
+ if (ptr == 0) {
+ return 0L;
+ } else {
+ return ((ptr & 0xFFFFFFFFL) << shift) + base;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "base: " + base + " shift: " + shift + " alignment: " + alignment;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + alignment;
+ result = prime * result + (int) (base ^ (base >>> 32));
+ result = prime * result + shift;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CompressEncoding) {
+ CompressEncoding other = (CompressEncoding) obj;
+ return alignment == other.alignment && base == other.base && shift == other.shift;
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.lang.String.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.internal.org.objectweb.asm.*;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.vm.ci.common.*;
+import sun.misc.*;
+
+/**
+ * A {@link ClassVisitor} that verifies {@link HotSpotVMConfig} does not access {@link Unsafe} from
+ * any of its non-static, non-constructor methods. This ensures that a deserialized
+ * {@link HotSpotVMConfig} object does not perform any unsafe reads on addresses that are only valid
+ * in the context in which the object was serialized. Note that this does not catch cases where a
+ * client uses an address stored in a {@link HotSpotVMConfig} field.
+ */
+final class HotSpotVMConfigVerifier extends ClassVisitor {
+
+ public static boolean check() {
+ Class<?> cls = HotSpotVMConfig.class;
+ String classFilePath = "/" + cls.getName().replace('.', '/') + ".class";
+ try {
+ InputStream classfile = cls.getResourceAsStream(classFilePath);
+ ClassReader cr = new ClassReader(Objects.requireNonNull(classfile, "Could not find class file for " + cls.getName()));
+ ClassVisitor cv = new HotSpotVMConfigVerifier();
+ cr.accept(cv, 0);
+ return true;
+ } catch (IOException e) {
+ throw new JVMCIError(e);
+ }
+ }
+
+ /**
+ * Source file context for error reporting.
+ */
+ String sourceFile = null;
+
+ /**
+ * Line number for error reporting.
+ */
+ int lineNo = -1;
+
+ private static Class<?> resolve(String name) {
+ try {
+ return Class.forName(name.replace('/', '.'));
+ } catch (ClassNotFoundException e) {
+ throw new JVMCIError(e);
+ }
+ }
+
+ HotSpotVMConfigVerifier() {
+ super(Opcodes.ASM5);
+ }
+
+ @Override
+ public void visitSource(String source, String debug) {
+ this.sourceFile = source;
+ }
+
+ void verify(boolean condition, String message) {
+ if (!condition) {
+ error(message);
+ }
+ }
+
+ void error(String message) {
+ String errorMessage = format("%s:%d: %s is not allowed in the context of compilation replay. The unsafe access should be moved into the %s constructor and the result cached in a field",
+ sourceFile, lineNo, message, HotSpotVMConfig.class.getSimpleName());
+ throw new JVMCIError(errorMessage);
+
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
+ if (!Modifier.isStatic(access) && Modifier.isPublic(access) && !name.equals("<init>")) {
+ return new MethodVisitor(Opcodes.ASM5) {
+
+ @Override
+ public void visitLineNumber(int line, Label start) {
+ lineNo = line;
+ }
+
+ private Executable resolveMethod(String owner, String methodName, String methodDesc) {
+ Class<?> declaringClass = resolve(owner);
+ while (declaringClass != null) {
+ if (methodName.equals("<init>")) {
+ for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
+ if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
+ return c;
+ }
+ }
+ } else {
+ Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
+ for (Method m : declaringClass.getDeclaredMethods()) {
+ if (m.getName().equals(methodName)) {
+ if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
+ if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
+ return m;
+ }
+ }
+ }
+ }
+ }
+ declaringClass = declaringClass.getSuperclass();
+ }
+ throw new NoSuchMethodError(owner + "." + methodName + methodDesc);
+ }
+
+ /**
+ * Checks whether a given method is allowed to be called.
+ */
+ private boolean checkInvokeTarget(Executable method) {
+ if (method.getDeclaringClass().equals(Unsafe.class)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
+ Executable callee = resolveMethod(owner, methodName, methodDesc);
+ verify(checkInvokeTarget(callee), "invocation of " + callee);
+ }
+ };
+ } else {
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.meta.*;
+
+public interface HotSpotVMEventListener {
+
+ /**
+ * Notifies this client that the VM is shutting down.
+ */
+ default void notifyShutdown() {
+ }
+
+ /**
+ * Notify on successful install into the CodeCache.
+ *
+ * @param hotSpotCodeCacheProvider
+ * @param installedCode
+ * @param compResult
+ */
+ default void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompilationResult compResult) {
+ }
+
+ /**
+ * Perform any extra initialization required.
+ *
+ * @param runtime
+ */
+ default void completeInitialization(HotSpotJVMCIRuntime runtime) {
+ }
+
+ /**
+ * Create a custom {@link JVMCIMetaAccessContext} to be used for managing the lifetime of loaded
+ * metadata. It a custom one isn't created then the default implementation will be a single
+ * context with globally shared instances of {@link ResolvedJavaType} that are never released.
+ *
+ * @param hotSpotJVMCIRuntime
+ * @return a custom context or null
+ */
+ default JVMCIMetaAccessContext createMetaAccessContext(HotSpotJVMCIRuntime hotSpotJVMCIRuntime) {
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import sun.misc.*;
+
+/**
+ * Class to access the C++ {@code vmSymbols} table.
+ */
+public final class HotSpotVmSymbols {
+
+ /**
+ * Returns the symbol in the {@code vmSymbols} table at position {@code index} as {@link String}
+ * .
+ *
+ * @param index position in the symbol table
+ * @return the symbol at position id
+ */
+ public static String symbolAt(int index) {
+ HotSpotJVMCIRuntimeProvider runtime = runtime();
+ HotSpotVMConfig config = runtime.getConfig();
+ assert config.vmSymbolsFirstSID <= index && index < config.vmSymbolsSIDLimit : "index " + index + " is out of bounds";
+ assert config.symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
+ return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(config.vmSymbolsSymbols + index * config.symbolPointerSize));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object.
+ *
+ * It would preferable if this were the base class containing the pointer but that would require
+ * mixins since most of the wrapper types have complex supertype hierarchies.
+ */
+public interface MetaspaceWrapperObject {
+
+ long getMetaspacePointer();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation functions as an alias for the sun.invoke.Stable annotation within JVMCI code. It
+ * is specially recognized during class file parsing in the same way as that annotation.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Stable {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+public @interface SuppressFBWarnings {
+ /**
+ * The set of FindBugs <a
+ * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+ * suppressed in annotated element. The value can be a bug category, kind or pattern.
+ */
+ String[] value();
+
+ /**
+ * Reason why the warning is suppressed.
+ */
+ String justification();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2012, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+/**
+ * Package private access to the {@link Unsafe} capability.
+ */
+class UnsafeAccess {
+
+ static final Unsafe UNSAFE = initUnsafe();
+
+ private static Unsafe initUnsafe() {
+ try {
+ // Fast path when we are trusted.
+ return Unsafe.getUnsafe();
+ } catch (SecurityException se) {
+ // Slow path when we are not trusted.
+ try {
+ Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+ theUnsafe.setAccessible(true);
+ return (Unsafe) theUnsafe.get(Unsafe.class);
+ } catch (Exception e) {
+ throw new RuntimeException("exception while trying to get Unsafe", e);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot.events;
+
+import jdk.vm.ci.common.*;
+
+/**
+ * An empty implementation for {@link EventProvider}. This implementation is used when no logging is
+ * requested.
+ */
+public final class EmptyEventProvider implements EventProvider {
+
+ public CompilationEvent newCompilationEvent() {
+ return new EmptyCompilationEvent();
+ }
+
+ public static class EmptyCompilationEvent implements CompilationEvent {
+ public void commit() {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public boolean shouldWrite() {
+ // Events of this class should never been written.
+ return false;
+ }
+
+ public void begin() {
+ }
+
+ public void end() {
+ }
+
+ public void setMethod(String method) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setCompileId(int compileId) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setCompileLevel(int compileLevel) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setSucceeded(boolean succeeded) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setIsOsr(boolean isOsr) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setCodeSize(int codeSize) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setInlinedBytes(int inlinedBytes) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+ }
+
+ public CompilerFailureEvent newCompilerFailureEvent() {
+ return new EmptyCompilerFailureEvent();
+ }
+
+ public static class EmptyCompilerFailureEvent implements CompilerFailureEvent {
+ public void commit() {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public boolean shouldWrite() {
+ // Events of this class should never been written.
+ return false;
+ }
+
+ public void setCompileId(int compileId) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+
+ public void setMessage(String message) {
+ throw JVMCIError.shouldNotReachHere();
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EventProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot.events;
+
+/**
+ * A provider that provides a specific implementation for events that can be logged in the compiler.
+ */
+public interface EventProvider {
+
+ /**
+ * An instant event is an event that is not considered to have taken any time.
+ */
+ interface InstantEvent {
+ /**
+ * Commits the event.
+ */
+ void commit();
+
+ /**
+ * Determines if this particular event instance would be committed to the data stream right
+ * now if application called {@link #commit()}. This in turn depends on whether the event is
+ * enabled and possible other factors.
+ *
+ * @return if this event would be committed on a call to {@link #commit()}.
+ */
+ boolean shouldWrite();
+ }
+
+ /**
+ * Timed events describe an operation that somehow consumes time.
+ */
+ interface TimedEvent extends InstantEvent {
+ /**
+ * Starts the timing for this event.
+ */
+ void begin();
+
+ /**
+ * Ends the timing period for this event.
+ */
+ void end();
+ }
+
+ /**
+ * Creates a new {@link CompilationEvent}.
+ *
+ * @return a compilation event
+ */
+ CompilationEvent newCompilationEvent();
+
+ /**
+ * A compilation event.
+ */
+ interface CompilationEvent extends TimedEvent {
+ void setMethod(String method);
+
+ void setCompileId(int compileId);
+
+ void setCompileLevel(int compileLevel);
+
+ void setSucceeded(boolean succeeded);
+
+ void setIsOsr(boolean isOsr);
+
+ void setCodeSize(int codeSize);
+
+ void setInlinedBytes(int inlinedBytes);
+ }
+
+ /**
+ * Creates a new {@link CompilerFailureEvent}.
+ *
+ * @return a compiler failure event
+ */
+ CompilerFailureEvent newCompilerFailureEvent();
+
+ /**
+ * A compiler failure event.
+ */
+ interface CompilerFailureEvent extends InstantEvent {
+ void setCompileId(int compileId);
+
+ void setMessage(String message);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/logging/package-info.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+/**
+ * Logging framework for the HotSpot CRI implementation.
+ */
+package jdk.vm.ci.hotspot.logging;
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a C++ address in the VM.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMAddress {
+
+ /**
+ * Returns the name of the symbol this address is referring to.
+ *
+ * @return name of symbol of this address
+ */
+ String name();
+
+ /**
+ * List of architectures where this constant is required. Names are derived from
+ * {@link HotSpotVMConfig#getHostArchitectureName()}. An empty list implies that the constant is
+ * required on all architectures.
+ */
+ @SuppressWarnings("javadoc")
+ String[] archs() default {};
+
+ /**
+ * List of operating systems where this constant is required. Names are derived from
+ * {@link HotSpotVMConfig#getHostOSName()}. An empty list implies that the constant is required
+ * on all operating systems.
+ */
+ @SuppressWarnings("javadoc")
+ String[] os() default {};
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a C++ constant in the VM.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMConstant {
+
+ /**
+ * Returns the name of the constant.
+ *
+ * @return name of constant
+ */
+ String name();
+
+ /**
+ * List of architectures where this constant is required. Names are derived from
+ * {@link HotSpotVMConfig#getHostArchitectureName()}. An empty list implies that the constant is
+ * required on all architectures.
+ */
+ @SuppressWarnings("javadoc")
+ String[] archs() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a entry in {@code gHotSpotVMData}.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMData {
+
+ /**
+ * Returns the array index of this field.
+ *
+ * @return array index of field
+ */
+ int index();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a C++ field in the VM.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMField {
+
+ /**
+ * Types of information this annotation can return.
+ */
+ enum Type {
+ /**
+ * Returns the offset of this field within the type. Only valid for instance fields.
+ */
+ OFFSET,
+
+ /**
+ * Returns the absolute address of this field. Only valid for static fields.
+ */
+ ADDRESS,
+
+ /**
+ * Returns the value of this field. Only valid for static fields.
+ */
+ VALUE;
+ }
+
+ /**
+ * Specifies what type of information to return.
+ *
+ * @see Type
+ */
+ Type get();
+
+ /**
+ * Returns the type name containing this field.
+ *
+ * @return name of containing type
+ */
+ String type();
+
+ /**
+ * Returns the name of this field.
+ *
+ * @return name of field
+ */
+ String name();
+
+ /**
+ * List of architectures where this constant is required. Names are derived from
+ * {@link HotSpotVMConfig#getHostArchitectureName()}. An empty list implies that the constant is
+ * required on all architectures.
+ */
+ @SuppressWarnings("javadoc")
+ String[] archs() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a C++ flag in the VM.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMFlag {
+
+ /**
+ * Returns the name of this flag.
+ *
+ * @return name of flag.
+ */
+ String name();
+
+ /**
+ * List of architectures where this constant is required. Names are derived from
+ * {@link HotSpotVMConfig#getHostArchitectureName()}. An empty list implies that the constant is
+ * required on all architectures.
+ */
+ @SuppressWarnings("javadoc")
+ String[] archs() default {};
+
+ boolean optional() default false;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotates a field in HotSpotVMConfig which is not read from the VM but is calculated manually.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMManual {
+
+ /**
+ * Returns the name associated with that field.
+ *
+ * @return name associated with field
+ */
+ String name();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.hotspotvmconfig;
+
+import java.lang.annotation.*;
+
+/**
+ * Refers to a C++ type in the VM.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMType {
+
+ /**
+ * Types of information this annotation can return.
+ */
+ enum Type {
+ /**
+ * Returns the size of the type (C++ {@code sizeof()}).
+ */
+ SIZE;
+ }
+
+ /**
+ * Specifies what type of information to return.
+ *
+ * @see Type
+ */
+ Type get();
+
+ /**
+ * Returns the name of the type.
+ *
+ * @return name of type
+ */
+ String name();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.inittimer/src/jdk/vm/ci/inittimer/InitTimer.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.inittimer;
+
+/**
+ * A facility for timing a step in the runtime initialization sequence. This is independent from all
+ * other JVMCI code so as to not perturb the initialization sequence. It is enabled by setting the
+ * {@code "jvmci.inittimer"} system property to {@code "true"}.
+ */
+public final class InitTimer implements AutoCloseable {
+ final String name;
+ final long start;
+
+ private InitTimer(String name) {
+ this.name = name;
+ this.start = System.currentTimeMillis();
+ System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name);
+ assert Thread.currentThread() == initializingThread : Thread.currentThread() + " != " + initializingThread;
+ timerDepth++;
+ }
+
+ @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "only the initializing thread accesses this field")
+ public void close() {
+ final long end = System.currentTimeMillis();
+ timerDepth--;
+ System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]");
+ }
+
+ public static InitTimer timer(String name) {
+ return ENABLED ? new InitTimer(name) : null;
+ }
+
+ public static InitTimer timer(String name, Object suffix) {
+ return ENABLED ? new InitTimer(name + suffix) : null;
+ }
+
+ /**
+ * Specifies if initialization timing is enabled.
+ */
+ private static final boolean ENABLED = Boolean.getBoolean("jvmci.inittimer") || Boolean.getBoolean("jvmci.runtime.TimeInit");
+
+ public static int timerDepth = 0;
+ public static final String SPACES = " ";
+
+ /**
+ * Used to assert the invariant that all initialization happens on the same thread.
+ */
+ public static final Thread initializingThread;
+ static {
+ if (ENABLED) {
+ initializingThread = Thread.currentThread();
+ System.out.println("INITIALIZING THREAD: " + initializingThread);
+ } else {
+ initializingThread = null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.inittimer/src/jdk/vm/ci/inittimer/SuppressFBWarnings.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.inittimer;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+public @interface SuppressFBWarnings {
+ /**
+ * The set of FindBugs <a
+ * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+ * suppressed in annotated element. The value can be a bug category, kind or pattern.
+ */
+ String[] value();
+
+ /**
+ * Reason why the warning is suppressed.
+ */
+ String justification();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/overview.html Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+Copyright (c) 2012, 2015, 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.
+-->
+
+</head>
+<body>
+
+The <code>jdk.vm.ci.meta</code> project provides an API to the runtime data structures
+for various Java elements. Unlike standard Java reflection, it can model elements that are not yet loaded.
+It can also expose profiling information collected by the runtime system.
+
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractJavaProfile.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * This object holds probability information for a set of items that were profiled at a specific
+ * BCI. The precision of the supplied values may vary, but a runtime that provides this information
+ * should be aware that it will be used to guide performance-critical decisions like speculative
+ * inlining, etc.
+ *
+ * @param <T> a subclass of AbstractProfiledItem
+ * @param <U> the class of the items that are profiled at the specific BCI and for which
+ * probabilities are stored. E.g., a ResolvedJavaType or a ResolvedJavaMethod.
+ */
+public abstract class AbstractJavaProfile<T extends AbstractProfiledItem<U>, U> {
+
+ private final double notRecordedProbability;
+ private final T[] pitems;
+
+ public AbstractJavaProfile(double notRecordedProbability, T[] pitems) {
+ this.pitems = pitems;
+ assert !Double.isNaN(notRecordedProbability);
+ this.notRecordedProbability = notRecordedProbability;
+ assert isSorted();
+ assert totalProbablility() >= 0 && totalProbablility() <= 1.0001 : totalProbablility() + " " + this;
+ }
+
+ private double totalProbablility() {
+ double total = notRecordedProbability;
+ for (T item : pitems) {
+ total += item.probability;
+ }
+ return total;
+ }
+
+ /**
+ * Determines if an array of profiled items are sorted in descending order of their
+ * probabilities.
+ */
+ private boolean isSorted() {
+ for (int i = 1; i < pitems.length; i++) {
+ if (pitems[i - 1].getProbability() < pitems[i].getProbability()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the estimated probability of all types that could not be recorded due to profiling
+ * limitations.
+ *
+ * @return double value ≥ 0.0 and ≤ 1.0
+ */
+ public double getNotRecordedProbability() {
+ return notRecordedProbability;
+ }
+
+ protected T[] getItems() {
+ return pitems;
+ }
+
+ /**
+ * Searches for an entry of a given resolved Java type.
+ *
+ * @param type the type for which an entry should be searched
+ * @return the entry or null if no entry for this type can be found
+ */
+ public T findEntry(ResolvedJavaType type) {
+ if (pitems != null) {
+ for (T pt : pitems) {
+ if (pt.getItem().equals(type)) {
+ return pt;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(this.getClass().getName());
+ builder.append("[");
+ if (pitems != null) {
+ for (T pt : pitems) {
+ builder.append(pt.toString());
+ builder.append(", ");
+ }
+ }
+ builder.append(this.notRecordedProbability);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public boolean isIncluded(U item) {
+ if (this.getNotRecordedProbability() > 0.0) {
+ return true;
+ } else {
+ for (int i = 0; i < getItems().length; i++) {
+ T pitem = getItems()[i];
+ U curType = pitem.getItem();
+ if (curType == item) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof AbstractJavaProfile)) {
+ return false;
+ }
+ AbstractJavaProfile<?, ?> that = (AbstractJavaProfile<?, ?>) obj;
+ if (that.notRecordedProbability != notRecordedProbability) {
+ return false;
+ }
+ if (that.pitems.length != pitems.length) {
+ return false;
+ }
+ for (int i = 0; i < pitems.length; ++i) {
+ if (!pitems[i].equals(that.pitems[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) Double.doubleToLongBits(notRecordedProbability) + pitems.length * 13;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractProfiledItem.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * A profiled type that has a probability. Profiled types are naturally sorted in descending order
+ * of their probabilities.
+ */
+public abstract class AbstractProfiledItem<T> implements Comparable<AbstractProfiledItem<?>> {
+
+ protected final T item;
+ protected final double probability;
+
+ public AbstractProfiledItem(T item, double probability) {
+ assert item != null;
+ assert probability >= 0.0D && probability <= 1.0D;
+ this.item = item;
+ this.probability = probability;
+ }
+
+ protected T getItem() {
+ return item;
+ }
+
+ /**
+ * Returns the estimated probability of {@link #getItem()}.
+ *
+ * @return double value ≥ 0.0 and ≤ 1.0
+ */
+ public double getProbability() {
+ return probability;
+ }
+
+ @Override
+ public int compareTo(AbstractProfiledItem<?> o) {
+ if (getProbability() > o.getProbability()) {
+ return -1;
+ } else if (getProbability() < o.getProbability()) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(probability);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + item.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AbstractProfiledItem<?> other = (AbstractProfiledItem<?>) obj;
+ if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
+ return false;
+ }
+ return item.equals(other.item);
+ }
+
+ @Override
+ public abstract String toString();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AllocatableValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Common base class for values that are stored in some location that's managed by the register
+ * allocator (e.g. register, stack slot).
+ */
+public abstract class AllocatableValue extends Value implements JavaValue {
+
+ public static final AllocatableValue[] NONE = {};
+
+ public AllocatableValue(LIRKind lirKind) {
+ super(lirKind);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.invoke.*;
+import java.util.*;
+
+/**
+ * Class for recording assumptions made during compilation.
+ */
+public final class Assumptions implements Iterable<Assumptions.Assumption> {
+
+ /**
+ * Abstract base class for assumptions. An assumption assumes a property of the runtime that may
+ * be invalidated by subsequent execution (e.g., that a class has no subclasses implementing
+ * {@link NoFinalizableSubclass Object.finalize()}).
+ */
+ public abstract static class Assumption {
+ }
+
+ /**
+ * A class for providing information that is only valid in association with a set of
+ * {@link Assumption}s.
+ *
+ * @param <T>
+ */
+ public static class AssumptionResult<T> {
+ Assumption[] assumptions;
+ final T result;
+
+ private static final Assumption[] EMPTY = new Assumption[0];
+
+ public AssumptionResult(T result, Assumption... assumptions) {
+ this.result = result;
+ this.assumptions = assumptions;
+ }
+
+ public AssumptionResult(T result) {
+ this(result, EMPTY);
+ }
+
+ public T getResult() {
+ return result;
+ }
+
+ public boolean isAssumptionFree() {
+ return assumptions.length == 0;
+ }
+
+ public void add(AssumptionResult<T> other) {
+ Assumption[] newAssumptions = Arrays.copyOf(this.assumptions, this.assumptions.length + other.assumptions.length);
+ System.arraycopy(other.assumptions, 0, newAssumptions, this.assumptions.length, other.assumptions.length);
+ this.assumptions = newAssumptions;
+ }
+
+ public boolean canRecordTo(Assumptions target) {
+ /*
+ * We can use the result if it is either assumption free, or if we have a valid
+ * Assumptions object where we can record assumptions.
+ */
+ return assumptions.length == 0 || target != null;
+ }
+
+ public void recordTo(Assumptions target) {
+ assert canRecordTo(target);
+
+ if (assumptions.length > 0) {
+ for (Assumption assumption : assumptions) {
+ target.record(assumption);
+ }
+ }
+ }
+ }
+
+ /**
+ * An assumption that a given class has no subclasses implementing {@link Object#finalize()}).
+ */
+ public static final class NoFinalizableSubclass extends Assumption {
+
+ private ResolvedJavaType receiverType;
+
+ public NoFinalizableSubclass(ResolvedJavaType receiverType) {
+ this.receiverType = receiverType;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 + receiverType.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NoFinalizableSubclass) {
+ NoFinalizableSubclass other = (NoFinalizableSubclass) obj;
+ return other.receiverType.equals(receiverType);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "NoFinalizableSubclass[receiverType=" + receiverType.toJavaName() + "]";
+ }
+
+ }
+
+ /**
+ * An assumption that a given abstract or interface type has one direct concrete subtype. There
+ * is no requirement that the subtype is a leaf type.
+ */
+ public static final class ConcreteSubtype extends Assumption {
+
+ /**
+ * Type the assumption is made about.
+ */
+ public final ResolvedJavaType context;
+
+ /**
+ * Assumed concrete sub-type of the context type.
+ */
+ public final ResolvedJavaType subtype;
+
+ public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
+ this.context = context;
+ this.subtype = subtype;
+ assert context.isAbstract();
+ assert subtype.isConcrete() || context.isInterface() : subtype.toString() + " : " + context.toString();
+ assert !subtype.isArray() || subtype.getElementalType().isFinalFlagSet() : subtype.toString() + " : " + context.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + context.hashCode();
+ result = prime * result + subtype.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ConcreteSubtype) {
+ ConcreteSubtype other = (ConcreteSubtype) obj;
+ return other.context.equals(context) && other.subtype.equals(subtype);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "ConcreteSubtype[context=" + context.toJavaName() + ", subtype=" + subtype.toJavaName() + "]";
+ }
+ }
+
+ /**
+ * An assumption that a given type has no subtypes.
+ */
+ public static final class LeafType extends Assumption {
+
+ /**
+ * Type the assumption is made about.
+ */
+ public final ResolvedJavaType context;
+
+ public LeafType(ResolvedJavaType context) {
+ this.context = context;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + context.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LeafType) {
+ LeafType other = (LeafType) obj;
+ return other.context.equals(context);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "LeafSubtype[context=" + context.toJavaName() + "]";
+ }
+ }
+
+ /**
+ * An assumption that a given virtual method has a given unique implementation.
+ */
+ public static final class ConcreteMethod extends Assumption {
+
+ /**
+ * A virtual (or interface) method whose unique implementation for the receiver type in
+ * {@link #context} is {@link #impl}.
+ */
+ public final ResolvedJavaMethod method;
+
+ /**
+ * A receiver type.
+ */
+ public final ResolvedJavaType context;
+
+ /**
+ * The unique implementation of {@link #method} for {@link #context}.
+ */
+ public final ResolvedJavaMethod impl;
+
+ public ConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
+ this.method = method;
+ this.context = context;
+ this.impl = impl;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + method.hashCode();
+ result = prime * result + context.hashCode();
+ result = prime * result + impl.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ConcreteMethod) {
+ ConcreteMethod other = (ConcreteMethod) obj;
+ return other.method.equals(method) && other.context.equals(context) && other.impl.equals(impl);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "ConcreteMethod[method=" + method.format("%H.%n(%p)%r") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)%r") + "]";
+ }
+ }
+
+ /**
+ * An assumption that a given call site's method handle did not change.
+ */
+ public static final class CallSiteTargetValue extends Assumption {
+
+ public final CallSite callSite;
+ public final MethodHandle methodHandle;
+
+ public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) {
+ this.callSite = callSite;
+ this.methodHandle = methodHandle;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + callSite.hashCode();
+ result = prime * result + methodHandle.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CallSiteTargetValue) {
+ CallSiteTargetValue other = (CallSiteTargetValue) obj;
+ return callSite.equals(other.callSite) && methodHandle.equals(other.methodHandle);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]";
+ }
+ }
+
+ private final Set<Assumption> assumptions = new HashSet<>();
+
+ /**
+ * Returns whether any assumptions have been registered.
+ *
+ * @return {@code true} if at least one assumption has been registered, {@code false} otherwise.
+ */
+ public boolean isEmpty() {
+ return assumptions.isEmpty();
+ }
+
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException("hashCode");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Assumptions) {
+ Assumptions that = (Assumptions) obj;
+ if (!this.assumptions.equals(that.assumptions)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Iterator<Assumption> iterator() {
+ return assumptions.iterator();
+ }
+
+ /**
+ * Records an assumption that the specified type has no finalizable subclasses.
+ *
+ * @param receiverType the type that is assumed to have no finalizable subclasses
+ */
+ public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
+ record(new NoFinalizableSubclass(receiverType));
+ }
+
+ /**
+ * Records that {@code subtype} is the only concrete subtype in the class hierarchy below
+ * {@code context}.
+ *
+ * @param context the root of the subtree of the class hierarchy that this assumptions is about
+ * @param subtype the one concrete subtype
+ */
+ public void recordConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
+ record(new ConcreteSubtype(context, subtype));
+ }
+
+ /**
+ * Records that {@code impl} is the only possible concrete target for a virtual call to
+ * {@code method} with a receiver of type {@code context}.
+ *
+ * @param method a method that is the target of a virtual call
+ * @param context the receiver type of a call to {@code method}
+ * @param impl the concrete method that is the only possible target for the virtual call
+ */
+ public void recordConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
+ record(new ConcreteMethod(method, context, impl));
+ }
+
+ public void record(Assumption assumption) {
+ assumptions.add(assumption);
+ }
+
+ /**
+ * Gets a copy of the assumptions recorded in this object as an array.
+ */
+ public Assumption[] toArray() {
+ return assumptions.toArray(new Assumption[assumptions.size()]);
+ }
+
+ /**
+ * Copies assumptions recorded by another {@link Assumptions} object into this object.
+ */
+ public void record(Assumptions other) {
+ assert other != this;
+ assumptions.addAll(other.assumptions);
+ }
+
+ @Override
+ public String toString() {
+ return "Assumptions[" + assumptions + "]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a compile-time constant (boxed) value within the compiler.
+ */
+public interface Constant {
+
+ boolean isDefaultForKind();
+
+ String toValueString();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents the runtime representation of the constant pool that is used by the compiler when
+ * parsing bytecode. Provides methods to look up a constant pool entry without performing
+ * resolution. They are used during compilation.
+ */
+public interface ConstantPool {
+
+ /**
+ * Returns the number of entries the constant pool.
+ *
+ * @return number of entries in the constant pool
+ */
+ int length();
+
+ /**
+ * Ensures that the type referenced by the specified constant pool entry is loaded and
+ * initialized. This can be used to compile time resolve a type. It works for field, method, or
+ * type constant pool entries.
+ *
+ * @param cpi the index of the constant pool entry that references the type
+ * @param opcode the opcode of the instruction that references the type
+ */
+ void loadReferencedType(int cpi, int opcode);
+
+ /**
+ * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks
+ * specific to the bytecode it denotes are performed if the field is already resolved. Should
+ * any of these checks fail, an unresolved field reference is returned.
+ *
+ * @param cpi the constant pool index
+ * @param opcode the opcode of the instruction for which the lookup is being performed or
+ * {@code -1}
+ * @return a reference to the field at {@code cpi} in this pool
+ * @throws ClassFormatError if the entry at {@code cpi} is not a field
+ */
+ JavaField lookupField(int cpi, int opcode);
+
+ /**
+ * Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks
+ * specific to the bytecode it denotes are performed if the method is already resolved. Should
+ * any of these checks fail, an unresolved method reference is returned.
+ *
+ * @param cpi the constant pool index
+ * @param opcode the opcode of the instruction for which the lookup is being performed or
+ * {@code -1}
+ * @return a reference to the method at {@code cpi} in this pool
+ * @throws ClassFormatError if the entry at {@code cpi} is not a method
+ */
+ JavaMethod lookupMethod(int cpi, int opcode);
+
+ /**
+ * Looks up a reference to a type. If {@code opcode} is non-negative, then resolution checks
+ * specific to the bytecode it denotes are performed if the type is already resolved. Should any
+ * of these checks fail, an unresolved type reference is returned.
+ *
+ * @param cpi the constant pool index
+ * @param opcode the opcode of the instruction for which the lookup is being performed or
+ * {@code -1}
+ * @return a reference to the compiler interface type
+ */
+ JavaType lookupType(int cpi, int opcode);
+
+ /**
+ * Looks up an Utf8 string.
+ *
+ * @param cpi the constant pool index
+ * @return the Utf8 string at index {@code cpi} in this constant pool
+ */
+ String lookupUtf8(int cpi);
+
+ /**
+ * Looks up a method signature.
+ *
+ * @param cpi the constant pool index
+ * @return the method signature at index {@code cpi} in this constant pool
+ */
+ Signature lookupSignature(int cpi);
+
+ /**
+ * Looks up a constant at the specified index.
+ *
+ * @param cpi the constant pool index
+ * @return the {@code Constant} or {@code JavaType} instance representing the constant pool
+ * entry
+ */
+ Object lookupConstant(int cpi);
+
+ /**
+ * Looks up the appendix at the specified index.
+ *
+ * @param cpi the constant pool index
+ * @param opcode the opcode of the instruction for which the lookup is being performed or
+ * {@code -1}
+ * @return the appendix if it exists and is resolved or {@code null}
+ */
+ JavaConstant lookupAppendix(int cpi, int opcode);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.invoke.*;
+
+/**
+ * Reflection operations on values represented as {@linkplain JavaConstant constants}. All methods
+ * in this interface require the VM to access the actual object encapsulated in
+ * {@link JavaKind#Object object} constants. This access is not always possible, depending on kind
+ * of VM and the state that the VM is in. Therefore, all methods can return {@code null} at any
+ * time, to indicate that the result is not available at this point. The caller is responsible to
+ * check for {@code null} results and handle them properly, e.g., not perform an optimization.
+ */
+public interface ConstantReflectionProvider {
+
+ /**
+ * Compares two constants for equality. The equality relationship is symmetric. Returns
+ * {@link Boolean#TRUE true} if the two constants represent the same run time value,
+ * {@link Boolean#FALSE false} if they are different. Returns {@code null} if the constants
+ * cannot be compared at this point.
+ */
+ Boolean constantEquals(Constant x, Constant y);
+
+ /**
+ * Returns the length of the array constant. Returns {@code null} if the constant is not an
+ * array, or if the array length is not available at this point.
+ */
+ Integer readArrayLength(JavaConstant array);
+
+ /**
+ * Reads a value from the given array at the given index. Returns {@code null} if the constant
+ * is not an array, if the index is out of bounds, or if the value is not available at this
+ * point.
+ */
+ JavaConstant readArrayElement(JavaConstant array, int index);
+
+ /**
+ * Reads a value from the given array at the given index if it is a stable array. Returns
+ * {@code null} if the constant is not a stable array, if it is a default value, if the index is
+ * out of bounds, or if the value is not available at this point.
+ */
+ JavaConstant readConstantArrayElement(JavaConstant array, int index);
+
+ /**
+ * Reads a value from the given array at the given offset if it is a stable array. The offset
+ * will be decoded relative to the platform addressing into an index into the array. Returns
+ * {@code null} if the constant is not a stable array, if it is a default value, if the offset
+ * is out of bounds, or if the value is not available at this point.
+ */
+ JavaConstant readConstantArrayElementForOffset(JavaConstant array, long offset);
+
+ /**
+ * Gets the constant value of this field. Note that a {@code static final} field may not be
+ * considered constant if its declaring class is not yet initialized or if it is a well known
+ * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
+ *
+ * @param receiver object from which this field's value is to be read. This value is ignored if
+ * this field is static.
+ * @return the constant value of this field or {@code null} if this field is not considered
+ * constant by the runtime
+ */
+ JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver);
+
+ /**
+ * Gets the current value of this field for a given object, if available.
+ *
+ * There is no guarantee that the same value will be returned by this method for a field unless
+ * the field is considered to be {@linkplain #readConstantFieldValue(JavaField, JavaConstant)
+ * constant} by the runtime.
+ *
+ * @param receiver object from which this field's value is to be read. This value is ignored if
+ * this field is static.
+ * @return the value of this field or {@code null} if the value is not available (e.g., because
+ * the field holder is not yet initialized).
+ */
+ JavaConstant readFieldValue(JavaField field, JavaConstant receiver);
+
+ /**
+ * Gets the current value of this field for a given object, if available. Like
+ * {@link #readFieldValue(JavaField, JavaConstant)} but treats array fields as stable.
+ *
+ * There is no guarantee that the same value will be returned by this method for a field unless
+ * the field is considered to be {@linkplain #readConstantFieldValue(JavaField, JavaConstant)
+ * constant} by the runtime.
+ *
+ * @param receiver object from which this field's value is to be read. This value is ignored if
+ * this field is static.
+ * @param isDefaultStable if {@code true}, default values are considered stable
+ * @return the value of this field or {@code null} if the value is not available (e.g., because
+ * the field holder is not yet initialized).
+ */
+ JavaConstant readStableFieldValue(JavaField field, JavaConstant receiver, boolean isDefaultStable);
+
+ /**
+ * Converts the given {@link JavaKind#isPrimitive() primitive} constant to a boxed
+ * {@link JavaKind#Object object} constant, according to the Java boxing rules. Returns
+ * {@code null} if the source is is not a primitive constant, or the boxed value is not
+ * available at this point.
+ */
+ JavaConstant boxPrimitive(JavaConstant source);
+
+ /**
+ * Converts the given {@link JavaKind#Object object} constant to a
+ * {@link JavaKind#isPrimitive() primitive} constant, according to the Java unboxing rules.
+ * Returns {@code null} if the source is is not an object constant that can be unboxed, or the
+ * unboxed value is not available at this point.
+ */
+ JavaConstant unboxPrimitive(JavaConstant source);
+
+ /**
+ * Gets a string as a {@link JavaConstant}.
+ */
+ JavaConstant forString(String value);
+
+ /**
+ * Returns the {@link ResolvedJavaType} for a {@link Class} object (or any other object regarded
+ * as a class by the VM) encapsulated in the given constant. Returns {@code null} if the
+ * constant does not encapsulate a class, or if the type is not available at this point.
+ */
+ ResolvedJavaType asJavaType(Constant constant);
+
+ /**
+ * Check if the constant is embeddable in the code.
+ */
+ boolean isEmbeddable(Constant constant);
+
+ /**
+ * Gets access to the internals of {@link MethodHandle}.
+ */
+ MethodHandleAccessProvider getMethodHandleAccess();
+
+ /**
+ * Gets raw memory access.
+ */
+ MemoryAccessProvider getMemoryAccessProvider();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * An implementation of {@link ProfilingInfo} that can used in the absence of real profile
+ * information.
+ */
+public final class DefaultProfilingInfo implements ProfilingInfo {
+
+ private static final ProfilingInfo[] NO_PROFILING_INFO = new ProfilingInfo[]{new DefaultProfilingInfo(TriState.TRUE), new DefaultProfilingInfo(TriState.FALSE),
+ new DefaultProfilingInfo(TriState.UNKNOWN)};
+
+ private final TriState exceptionSeen;
+
+ DefaultProfilingInfo(TriState exceptionSeen) {
+ this.exceptionSeen = exceptionSeen;
+ }
+
+ @Override
+ public int getCodeSize() {
+ return 0;
+ }
+
+ @Override
+ public JavaTypeProfile getTypeProfile(int bci) {
+ return null;
+ }
+
+ @Override
+ public JavaMethodProfile getMethodProfile(int bci) {
+ return null;
+ }
+
+ @Override
+ public double getBranchTakenProbability(int bci) {
+ return -1;
+ }
+
+ @Override
+ public double[] getSwitchProbabilities(int bci) {
+ return null;
+ }
+
+ @Override
+ public TriState getExceptionSeen(int bci) {
+ return exceptionSeen;
+ }
+
+ @Override
+ public TriState getNullSeen(int bci) {
+ return TriState.UNKNOWN;
+ }
+
+ @Override
+ public int getExecutionCount(int bci) {
+ return -1;
+ }
+
+ public static ProfilingInfo get(TriState exceptionSeen) {
+ return NO_PROFILING_INFO[exceptionSeen.ordinal()];
+ }
+
+ @Override
+ public int getDeoptimizationCount(DeoptimizationReason reason) {
+ return 0;
+ }
+
+ @Override
+ public boolean isMature() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseProfilingInfo<" + this.toString(null, "; ") + ">";
+ }
+
+ public void setMature() {
+ // Do nothing
+ }
+
+ public boolean setCompilerIRSize(Class<?> irType, int nodeCount) {
+ return false;
+ }
+
+ public int getCompilerIRSize(Class<?> irType) {
+ return -1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Specifies the action that should be taken by the runtime in case a certain deoptimization is
+ * triggered.
+ */
+public enum DeoptimizationAction {
+ /**
+ * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
+ * it's highly likely nothing will change the likelihood of the deoptimization happening again.
+ * For example, a compiled array allocation where the size is negative.
+ */
+ None(false),
+
+ /**
+ * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
+ * triggered too often.
+ */
+ RecompileIfTooManyDeopts(true),
+
+ /**
+ * Invalidate the machine code and reset the profiling information.
+ */
+ InvalidateReprofile(true),
+
+ /**
+ * Invalidate the machine code and immediately schedule a recompilation. This is typically used
+ * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
+ * required to determine that the deoptimization will not re-occur.
+ */
+ InvalidateRecompile(true),
+
+ /**
+ * Invalidate the machine code and stop compiling the outermost method of this compilation.
+ */
+ InvalidateStopCompiling(true);
+
+ private final boolean invalidatesCompilation;
+
+ private DeoptimizationAction(boolean invalidatesCompilation) {
+ this.invalidatesCompilation = invalidatesCompilation;
+ }
+
+ public boolean doesInvalidateCompilation() {
+ return invalidatesCompilation;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Enumeration of reasons for why a deoptimization is happening.
+ */
+public enum DeoptimizationReason {
+ None,
+ NullCheckException,
+ BoundsCheckException,
+ ClassCastException,
+ ArrayStoreException,
+ UnreachedCode,
+ TypeCheckedInliningViolated,
+ OptimizedTypeCheckViolated,
+ NotCompiledExceptionHandler,
+ Unresolved,
+ JavaSubroutineMismatch,
+ ArithmeticException,
+ RuntimeConstraint,
+ LoopLimitCheck,
+ Aliasing,
+ TransferToInterpreter,
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+/**
+ * Represents an exception handler within the bytecodes.
+ */
+public final class ExceptionHandler {
+
+ private final int startBCI;
+ private final int endBCI;
+ private final int handlerBCI;
+ private final int catchTypeCPI;
+ private final JavaType catchType;
+
+ /**
+ * Creates a new exception handler with the specified ranges.
+ *
+ * @param startBCI the start index of the protected range
+ * @param endBCI the end index of the protected range
+ * @param catchBCI the index of the handler
+ * @param catchTypeCPI the index of the throwable class in the constant pool
+ * @param catchType the type caught by this exception handler
+ */
+ public ExceptionHandler(int startBCI, int endBCI, int catchBCI, int catchTypeCPI, JavaType catchType) {
+ this.startBCI = startBCI;
+ this.endBCI = endBCI;
+ this.handlerBCI = catchBCI;
+ this.catchTypeCPI = catchTypeCPI;
+ this.catchType = catchType;
+ }
+
+ /**
+ * Returns the start bytecode index of the protected range of this handler.
+ */
+ public int getStartBCI() {
+ return startBCI;
+ }
+
+ /**
+ * Returns the end bytecode index of the protected range of this handler.
+ */
+ public int getEndBCI() {
+ return endBCI;
+ }
+
+ /**
+ * Returns the bytecode index of the handler block of this handler.
+ */
+ public int getHandlerBCI() {
+ return handlerBCI;
+ }
+
+ /**
+ * Returns the index into the constant pool representing the type of exception caught by this
+ * handler.
+ */
+ public int catchTypeCPI() {
+ return catchTypeCPI;
+ }
+
+ /**
+ * Checks whether this handler catches all exceptions.
+ *
+ * @return {@code true} if this handler catches all exceptions
+ */
+ public boolean isCatchAll() {
+ return catchTypeCPI == 0;
+ }
+
+ /**
+ * Returns the type of exception caught by this exception handler.
+ */
+ public JavaType getCatchType() {
+ return catchType;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ExceptionHandler)) {
+ return false;
+ }
+ ExceptionHandler that = (ExceptionHandler) obj;
+ if (this.startBCI != that.startBCI || this.endBCI != that.endBCI || this.handlerBCI != that.handlerBCI || this.catchTypeCPI != that.catchTypeCPI) {
+ return false;
+ }
+ return Objects.equals(this.catchType, that.catchType);
+ }
+
+ @Override
+ public String toString() {
+ return "ExceptionHandler<startBCI=" + startBCI + ", endBCI=" + endBCI + ", handlerBCI=" + handlerBCI + ", catchTypeCPI=" + catchTypeCPI + ", catchType=" + catchType + ">";
+ }
+
+ @Override
+ public int hashCode() {
+ return catchTypeCPI ^ endBCI ^ handlerBCI;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2013, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents the resolved target of an invocation.
+ */
+public interface InvokeTarget {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * A context in which the results looking up the {@link ResolvedJavaType} for a {@link Class} are
+ * cached.
+ */
+public interface JVMCIMetaAccessContext {
+
+ /**
+ * Gets the JVMCI mirror for a {@link Class} object.
+ *
+ * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+ */
+
+ ResolvedJavaType fromClass(Class<?> clazz);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a constant (boxed) value, such as an integer, floating point number, or object
+ * reference, within the compiler and across the compiler/runtime interface. Exports a set of
+ * {@code JavaConstant} instances that represent frequently used constant values, such as
+ * {@link #NULL_POINTER}.
+ */
+public interface JavaConstant extends Constant, JavaValue {
+ /*
+ * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is
+ * not enough to justify the impact on startup time.
+ */
+ JavaConstant NULL_POINTER = new NullConstant();
+ PrimitiveConstant INT_MINUS_1 = new PrimitiveConstant(JavaKind.Int, -1);
+ PrimitiveConstant INT_0 = new PrimitiveConstant(JavaKind.Int, 0);
+ PrimitiveConstant INT_1 = new PrimitiveConstant(JavaKind.Int, 1);
+ PrimitiveConstant INT_2 = new PrimitiveConstant(JavaKind.Int, 2);
+ PrimitiveConstant LONG_0 = new PrimitiveConstant(JavaKind.Long, 0L);
+ PrimitiveConstant LONG_1 = new PrimitiveConstant(JavaKind.Long, 1L);
+ PrimitiveConstant FLOAT_0 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(0.0F));
+ PrimitiveConstant FLOAT_1 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(1.0F));
+ PrimitiveConstant DOUBLE_0 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(0.0D));
+ PrimitiveConstant DOUBLE_1 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(1.0D));
+ PrimitiveConstant TRUE = new PrimitiveConstant(JavaKind.Boolean, 1L);
+ PrimitiveConstant FALSE = new PrimitiveConstant(JavaKind.Boolean, 0L);
+
+ /**
+ * Returns the Java kind of this constant.
+ */
+ JavaKind getJavaKind();
+
+ /**
+ * Checks whether this constant is null.
+ *
+ * @return {@code true} if this constant is the null constant
+ */
+ boolean isNull();
+
+ static boolean isNull(Constant c) {
+ if (c instanceof JavaConstant) {
+ return ((JavaConstant) c).isNull();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether this constant is non-null.
+ *
+ * @return {@code true} if this constant is a primitive, or an object constant that is not null
+ */
+ default boolean isNonNull() {
+ return !isNull();
+ }
+
+ /**
+ * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
+ *
+ * @return {@code true} if this constant is the default value for its kind
+ */
+ boolean isDefaultForKind();
+
+ /**
+ * Returns the value of this constant as a boxed Java value.
+ *
+ * @return the value of this constant
+ */
+ Object asBoxedPrimitive();
+
+ /**
+ * Returns the primitive int value this constant represents. The constant must have a
+ * {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
+ *
+ * @return the constant value
+ */
+ int asInt();
+
+ /**
+ * Returns the primitive boolean value this constant represents. The constant must have kind
+ * {@link JavaKind#Boolean}.
+ *
+ * @return the constant value
+ */
+ boolean asBoolean();
+
+ /**
+ * Returns the primitive long value this constant represents. The constant must have kind
+ * {@link JavaKind#Long}, a {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
+ *
+ * @return the constant value
+ */
+ long asLong();
+
+ /**
+ * Returns the primitive float value this constant represents. The constant must have kind
+ * {@link JavaKind#Float}.
+ *
+ * @return the constant value
+ */
+ float asFloat();
+
+ /**
+ * Returns the primitive double value this constant represents. The constant must have kind
+ * {@link JavaKind#Double}.
+ *
+ * @return the constant value
+ */
+ double asDouble();
+
+ default String toValueString() {
+ if (getJavaKind() == JavaKind.Illegal) {
+ return "illegal";
+ } else {
+ return getJavaKind().format(asBoxedPrimitive());
+ }
+ }
+
+ static String toString(JavaConstant constant) {
+ if (constant.getJavaKind() == JavaKind.Illegal) {
+ return "illegal";
+ } else {
+ return constant.getJavaKind().getJavaName() + "[" + constant.toValueString() + "]";
+ }
+ }
+
+ /**
+ * Creates a boxed double constant.
+ *
+ * @param d the double value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forDouble(double d) {
+ if (Double.compare(0.0D, d) == 0) {
+ return DOUBLE_0;
+ }
+ if (Double.compare(d, 1.0D) == 0) {
+ return DOUBLE_1;
+ }
+ return new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(d));
+ }
+
+ /**
+ * Creates a boxed float constant.
+ *
+ * @param f the float value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forFloat(float f) {
+ if (Float.compare(f, 0.0F) == 0) {
+ return FLOAT_0;
+ }
+ if (Float.compare(f, 1.0F) == 0) {
+ return FLOAT_1;
+ }
+ return new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(f));
+ }
+
+ /**
+ * Creates a boxed long constant.
+ *
+ * @param i the long value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forLong(long i) {
+ if (i == 0) {
+ return LONG_0;
+ } else if (i == 1) {
+ return LONG_1;
+ } else {
+ return new PrimitiveConstant(JavaKind.Long, i);
+ }
+ }
+
+ /**
+ * Creates a boxed integer constant.
+ *
+ * @param i the integer value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forInt(int i) {
+ switch (i) {
+ case -1:
+ return INT_MINUS_1;
+ case 0:
+ return INT_0;
+ case 1:
+ return INT_1;
+ case 2:
+ return INT_2;
+ default:
+ return new PrimitiveConstant(JavaKind.Int, i);
+ }
+ }
+
+ /**
+ * Creates a boxed byte constant.
+ *
+ * @param i the byte value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forByte(byte i) {
+ return new PrimitiveConstant(JavaKind.Byte, i);
+ }
+
+ /**
+ * Creates a boxed boolean constant.
+ *
+ * @param i the boolean value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forBoolean(boolean i) {
+ return i ? TRUE : FALSE;
+ }
+
+ /**
+ * Creates a boxed char constant.
+ *
+ * @param i the char value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forChar(char i) {
+ return new PrimitiveConstant(JavaKind.Char, i);
+ }
+
+ /**
+ * Creates a boxed short constant.
+ *
+ * @param i the short value to box
+ * @return a boxed copy of {@code value}
+ */
+ static PrimitiveConstant forShort(short i) {
+ return new PrimitiveConstant(JavaKind.Short, i);
+ }
+
+ /**
+ * Creates a {@link JavaConstant} from a primitive integer of a certain kind.
+ */
+ static PrimitiveConstant forIntegerKind(JavaKind kind, long i) {
+ switch (kind) {
+ case Boolean:
+ return forBoolean(i != 0);
+ case Byte:
+ return forByte((byte) i);
+ case Short:
+ return forShort((short) i);
+ case Char:
+ return forChar((char) i);
+ case Int:
+ return forInt((int) i);
+ case Long:
+ return forLong(i);
+ default:
+ throw new IllegalArgumentException("not an integer kind: " + kind);
+ }
+ }
+
+ /**
+ * Creates a {@link JavaConstant} from a primitive integer of a certain width.
+ */
+ static PrimitiveConstant forPrimitiveInt(int bits, long i) {
+ assert bits <= 64;
+ switch (bits) {
+ case 1:
+ return forBoolean(i != 0);
+ case 8:
+ return forByte((byte) i);
+ case 16:
+ return forShort((short) i);
+ case 32:
+ return forInt((int) i);
+ case 64:
+ return forLong(i);
+ default:
+ throw new IllegalArgumentException("unsupported integer width: " + bits);
+ }
+ }
+
+ /**
+ * Creates a boxed constant for the given boxed primitive value.
+ *
+ * @param value the Java boxed value
+ * @return the primitive constant holding the {@code value}
+ */
+ static PrimitiveConstant forBoxedPrimitive(Object value) {
+ if (value instanceof Boolean) {
+ return forBoolean((Boolean) value);
+ } else if (value instanceof Byte) {
+ return forByte((Byte) value);
+ } else if (value instanceof Character) {
+ return forChar((Character) value);
+ } else if (value instanceof Short) {
+ return forShort((Short) value);
+ } else if (value instanceof Integer) {
+ return forInt((Integer) value);
+ } else if (value instanceof Long) {
+ return forLong((Long) value);
+ } else if (value instanceof Float) {
+ return forFloat((Float) value);
+ } else if (value instanceof Double) {
+ return forDouble((Double) value);
+ } else {
+ return null;
+ }
+ }
+
+ static PrimitiveConstant forIllegal() {
+ return new PrimitiveConstant(JavaKind.Illegal, 0);
+ }
+
+ /**
+ * Returns a constant with the default value for the given kind.
+ */
+ static JavaConstant defaultForKind(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ return FALSE;
+ case Byte:
+ return forByte((byte) 0);
+ case Char:
+ return forChar((char) 0);
+ case Short:
+ return forShort((short) 0);
+ case Int:
+ return INT_0;
+ case Double:
+ return DOUBLE_0;
+ case Float:
+ return FLOAT_0;
+ case Long:
+ return LONG_0;
+ case Object:
+ return NULL_POINTER;
+ default:
+ throw new IllegalArgumentException(kind.toString());
+ }
+ }
+
+ /**
+ * Returns the zero value for a given numeric kind.
+ */
+ static JavaConstant zero(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ return FALSE;
+ case Byte:
+ return forByte((byte) 0);
+ case Char:
+ return forChar((char) 0);
+ case Double:
+ return DOUBLE_0;
+ case Float:
+ return FLOAT_0;
+ case Int:
+ return INT_0;
+ case Long:
+ return LONG_0;
+ case Short:
+ return forShort((short) 0);
+ default:
+ throw new IllegalArgumentException(kind.toString());
+ }
+ }
+
+ /**
+ * Returns the one value for a given numeric kind.
+ */
+ static JavaConstant one(JavaKind kind) {
+ switch (kind) {
+ case Boolean:
+ return TRUE;
+ case Byte:
+ return forByte((byte) 1);
+ case Char:
+ return forChar((char) 1);
+ case Double:
+ return DOUBLE_1;
+ case Float:
+ return FLOAT_1;
+ case Int:
+ return INT_1;
+ case Long:
+ return LONG_1;
+ case Short:
+ return forShort((short) 1);
+ default:
+ throw new IllegalArgumentException(kind.toString());
+ }
+ }
+
+ /**
+ * Adds two numeric constants.
+ */
+ static JavaConstant add(JavaConstant x, JavaConstant y) {
+ assert x.getJavaKind() == y.getJavaKind();
+ switch (x.getJavaKind()) {
+ case Byte:
+ return forByte((byte) (x.asInt() + y.asInt()));
+ case Char:
+ return forChar((char) (x.asInt() + y.asInt()));
+ case Double:
+ return forDouble(x.asDouble() + y.asDouble());
+ case Float:
+ return forFloat(x.asFloat() + y.asFloat());
+ case Int:
+ return forInt(x.asInt() + y.asInt());
+ case Long:
+ return forLong(x.asLong() + y.asLong());
+ case Short:
+ return forShort((short) (x.asInt() + y.asInt()));
+ default:
+ throw new IllegalArgumentException(x.getJavaKind().toString());
+ }
+ }
+
+ /**
+ * Multiplies two numeric constants.
+ */
+ static PrimitiveConstant mul(JavaConstant x, JavaConstant y) {
+ assert x.getJavaKind() == y.getJavaKind();
+ switch (x.getJavaKind()) {
+ case Byte:
+ return forByte((byte) (x.asInt() * y.asInt()));
+ case Char:
+ return forChar((char) (x.asInt() * y.asInt()));
+ case Double:
+ return forDouble(x.asDouble() * y.asDouble());
+ case Float:
+ return forFloat(x.asFloat() * y.asFloat());
+ case Int:
+ return forInt(x.asInt() * y.asInt());
+ case Long:
+ return forLong(x.asLong() * y.asLong());
+ case Short:
+ return forShort((short) (x.asInt() * y.asInt()));
+ default:
+ throw new IllegalArgumentException(x.getJavaKind().toString());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+/**
+ * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
+ * methods and types, are resolved through {@link ConstantPool constant pools}.
+ */
+public interface JavaField extends TrustedInterface {
+
+ /**
+ * Returns the name of this field.
+ */
+ String getName();
+
+ /**
+ * Returns a {@link JavaType} object that identifies the declared type for this field.
+ */
+ JavaType getType();
+
+ /**
+ * Returns the kind of this field. This is the same as calling {@link #getType}.
+ * {@link JavaType#getJavaKind getJavaKind}.
+ */
+ default JavaKind getJavaKind() {
+ return getType().getJavaKind();
+ }
+
+ /**
+ * Returns the {@link JavaType} object representing the class or interface that declares this
+ * field.
+ */
+ JavaType getDeclaringClass();
+
+ /**
+ * Gets a string for this field formatted according to a given format specification. A format
+ * specification is composed of characters that are to be copied verbatim to the result and
+ * specifiers that denote an attribute of this field that is to be copied to the result. A
+ * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+ * field attributes they denote are described below:
+ *
+ * <pre>
+ * Specifier | Description | Example(s)
+ * ----------+------------------------------------------------------------------------------------------
+ * 'T' | Qualified type | "int" "java.lang.String"
+ * 't' | Unqualified type | "int" "String"
+ * 'H' | Qualified holder | "java.util.Map.Entry"
+ * 'h' | Unqualified holder | "Entry"
+ * 'n' | Field name | "age"
+ * 'f' | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
+ * '%' | A '%' character | "%"
+ * </pre>
+ *
+ * @param format a format specification
+ * @return the result of formatting this field according to {@code format}
+ * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+ */
+ @SuppressWarnings("fallthrough")
+ default String format(String format) throws IllegalFormatException {
+ StringBuilder sb = new StringBuilder();
+ int index = 0;
+ JavaType type = getType();
+ while (index < format.length()) {
+ char ch = format.charAt(index++);
+ if (ch == '%') {
+ if (index >= format.length()) {
+ throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
+ }
+ char specifier = format.charAt(index++);
+ switch (specifier) {
+ case 'T':
+ case 't': {
+ sb.append(type.toJavaName(specifier == 'T'));
+ break;
+ }
+ case 'H':
+ case 'h': {
+ sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
+ break;
+ }
+ case 'n': {
+ sb.append(getName());
+ break;
+ }
+ case 'f': {
+ sb.append(!(this instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) this).isStatic() ? "static" : "instance");
+ break;
+ }
+ case '%': {
+ sb.append('%');
+ break;
+ }
+ default: {
+ throw new UnknownFormatConversionException(String.valueOf(specifier));
+ }
+ }
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.*;
+
+//JaCoCo Exclude
+
+/**
+ * Denotes the basic kinds of types in CRI, including the all the Java primitive types, for example,
+ * {@link JavaKind#Int} for {@code int} and {@link JavaKind#Object} for all object types. A kind has
+ * a single character short name, a Java name, and a set of flags further describing its behavior.
+ */
+public enum JavaKind implements PlatformKind {
+ /** The primitive boolean kind, represented as an int on the stack. */
+ Boolean('z', "boolean", 1, true, java.lang.Boolean.TYPE, java.lang.Boolean.class),
+
+ /** The primitive byte kind, represented as an int on the stack. */
+ Byte('b', "byte", 1, true, java.lang.Byte.TYPE, java.lang.Byte.class),
+
+ /** The primitive short kind, represented as an int on the stack. */
+ Short('s', "short", 1, true, java.lang.Short.TYPE, java.lang.Short.class),
+
+ /** The primitive char kind, represented as an int on the stack. */
+ Char('c', "char", 1, true, java.lang.Character.TYPE, java.lang.Character.class),
+
+ /** The primitive int kind, represented as an int on the stack. */
+ Int('i', "int", 1, true, java.lang.Integer.TYPE, java.lang.Integer.class),
+
+ /** The primitive float kind. */
+ Float('f', "float", 1, false, java.lang.Float.TYPE, java.lang.Float.class),
+
+ /** The primitive long kind. */
+ Long('j', "long", 2, false, java.lang.Long.TYPE, java.lang.Long.class),
+
+ /** The primitive double kind. */
+ Double('d', "double", 2, false, java.lang.Double.TYPE, java.lang.Double.class),
+
+ /** The Object kind, also used for arrays. */
+ Object('a', "Object", 1, false, null, null),
+
+ /** The void float kind. */
+ Void('v', "void", 0, false, java.lang.Void.TYPE, java.lang.Void.class),
+
+ /** The non-type. */
+ Illegal('-', "illegal", 0, false, null, null);
+
+ private final char typeChar;
+ private final String javaName;
+ private final boolean isStackInt;
+ private final Class<?> primitiveJavaClass;
+ private final Class<?> boxedJavaClass;
+ private final EnumKey<JavaKind> key = new EnumKey<>(this);
+ private final int slotCount;
+
+ private JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class<?> primitiveJavaClass, Class<?> boxedJavaClass) {
+ this.typeChar = typeChar;
+ this.javaName = javaName;
+ this.slotCount = slotCount;
+ this.isStackInt = isStackInt;
+ this.primitiveJavaClass = primitiveJavaClass;
+ this.boxedJavaClass = boxedJavaClass;
+ assert primitiveJavaClass == null || javaName.equals(primitiveJavaClass.getName());
+ }
+
+ /**
+ * Returns the number of stack slots occupied by this kind according to the Java bytecodes
+ * specification.
+ */
+ public int getSlotCount() {
+ return this.slotCount;
+ }
+
+ /**
+ * Returns whether this kind occupied two stack slots.
+ */
+ public boolean needsTwoSlots() {
+ return this.slotCount == 2;
+ }
+
+ /**
+ * Returns the name of the kind as a single character.
+ */
+ public char getTypeChar() {
+ return typeChar;
+ }
+
+ /**
+ * Returns the name of this kind which will also be it Java programming language name if it is
+ * {@linkplain #isPrimitive() primitive} or {@code void}.
+ */
+ public String getJavaName() {
+ return javaName;
+ }
+
+ public Key getKey() {
+ return key;
+ }
+
+ /**
+ * Checks whether this type is a Java primitive type.
+ *
+ * @return {@code true} if this is {@link #Boolean}, {@link #Byte}, {@link #Char},
+ * {@link #Short}, {@link #Int}, {@link #Long}, {@link #Float}, {@link #Double}, or
+ * {@link #Void}.
+ */
+ public boolean isPrimitive() {
+ return primitiveJavaClass != null;
+ }
+
+ /**
+ * Returns the kind that represents this kind when on the Java operand stack.
+ *
+ * @return the kind used on the operand stack
+ */
+ public JavaKind getStackKind() {
+ if (isStackInt) {
+ return Int;
+ }
+ return this;
+ }
+
+ /**
+ * Checks whether this type is a Java primitive type representing an integer number.
+ *
+ * @return {@code true} if the stack kind is {@link #Int} or {@link #Long}.
+ */
+ public boolean isNumericInteger() {
+ return isStackInt || this == JavaKind.Long;
+ }
+
+ /**
+ * Checks whether this type is a Java primitive type representing an unsigned number.
+ *
+ * @return {@code true} if the kind is {@link #Boolean} or {@link #Char}.
+ */
+ public boolean isUnsigned() {
+ return this == JavaKind.Boolean || this == JavaKind.Char;
+ }
+
+ /**
+ * Checks whether this type is a Java primitive type representing a floating point number.
+ *
+ * @return {@code true} if this is {@link #Float} or {@link #Double}.
+ */
+ public boolean isNumericFloat() {
+ return this == JavaKind.Float || this == JavaKind.Double;
+ }
+
+ /**
+ * Checks whether this represent an Object of some sort.
+ *
+ * @return {@code true} if this is {@link #Object}.
+ */
+ public boolean isObject() {
+ return this == JavaKind.Object;
+ }
+
+ /**
+ * Returns the kind corresponding to the Java type string.
+ *
+ * @param typeString the Java type string
+ * @return the kind
+ */
+ public static JavaKind fromTypeString(String typeString) {
+ assert typeString.length() > 0;
+ final char first = typeString.charAt(0);
+ if (first == '[' || first == 'L') {
+ return JavaKind.Object;
+ }
+ return JavaKind.fromPrimitiveOrVoidTypeChar(first);
+ }
+
+ /**
+ * Returns the kind of a word given the size of a word in bytes.
+ *
+ * @param wordSizeInBytes the size of a word in bytes
+ * @return the kind representing a word value
+ */
+ public static JavaKind fromWordSize(int wordSizeInBytes) {
+ if (wordSizeInBytes == 8) {
+ return JavaKind.Long;
+ } else {
+ assert wordSizeInBytes == 4 : "Unsupported word size!";
+ return JavaKind.Int;
+ }
+ }
+
+ /**
+ * Returns the kind from the character describing a primitive or void.
+ *
+ * @param ch the character
+ * @return the kind
+ */
+ public static JavaKind fromPrimitiveOrVoidTypeChar(char ch) {
+ switch (ch) {
+ case 'Z':
+ return Boolean;
+ case 'C':
+ return Char;
+ case 'F':
+ return Float;
+ case 'D':
+ return Double;
+ case 'B':
+ return Byte;
+ case 'S':
+ return Short;
+ case 'I':
+ return Int;
+ case 'J':
+ return Long;
+ case 'V':
+ return Void;
+ }
+ throw new IllegalArgumentException("unknown primitive or void type character: " + ch);
+ }
+
+ /**
+ * Returns the Kind representing the given Java class.
+ *
+ * @param klass the class
+ * @return the kind
+ */
+ public static JavaKind fromJavaClass(Class<?> klass) {
+ if (klass == Boolean.primitiveJavaClass) {
+ return Boolean;
+ } else if (klass == Byte.primitiveJavaClass) {
+ return Byte;
+ } else if (klass == Short.primitiveJavaClass) {
+ return Short;
+ } else if (klass == Char.primitiveJavaClass) {
+ return Char;
+ } else if (klass == Int.primitiveJavaClass) {
+ return Int;
+ } else if (klass == Long.primitiveJavaClass) {
+ return Long;
+ } else if (klass == Float.primitiveJavaClass) {
+ return Float;
+ } else if (klass == Double.primitiveJavaClass) {
+ return Double;
+ } else if (klass == Void.primitiveJavaClass) {
+ return Void;
+ } else {
+ return Object;
+ }
+ }
+
+ /**
+ * Returns the Java class representing this kind.
+ *
+ * @return the Java class
+ */
+ public Class<?> toJavaClass() {
+ return primitiveJavaClass;
+ }
+
+ /**
+ * Returns the Java class for instances of boxed values of this kind.
+ *
+ * @return the Java class
+ */
+ public Class<?> toBoxedJavaClass() {
+ return boxedJavaClass;
+ }
+
+ /**
+ * Converts this value type to a string.
+ */
+ @Override
+ public String toString() {
+ return javaName;
+ }
+
+ /**
+ * Marker interface for types that should be {@linkplain JavaKind#format(Object) formatted} with
+ * their {@link Object#toString()} value. Calling {@link Object#toString()} on other objects
+ * poses a security risk because it can potentially call user code.
+ */
+ public interface FormatWithToString {
+ }
+
+ /**
+ * Classes for which invoking {@link Object#toString()} does not run user code.
+ */
+ private static boolean isToStringSafe(Class<?> c) {
+ return c == Boolean.class || c == Byte.class || c == Character.class || c == Short.class || c == Integer.class || c == Float.class || c == Long.class || c == Double.class;
+ }
+
+ /**
+ * Gets a formatted string for a given value of this kind.
+ *
+ * @param value a value of this kind
+ * @return a formatted string for {@code value} based on this kind
+ */
+ public String format(Object value) {
+ if (isPrimitive()) {
+ assert isToStringSafe(value.getClass());
+ return value.toString();
+ } else {
+ if (value == null) {
+ return "null";
+ } else {
+ if (value instanceof String) {
+ String s = (String) value;
+ if (s.length() > 50) {
+ return "String:\"" + s.substring(0, 30) + "...\"";
+ } else {
+ return "String:\"" + s + '"';
+ }
+ } else if (value instanceof JavaType) {
+ return "JavaType:" + ((JavaType) value).toJavaName();
+ } else if (value instanceof Enum) {
+ return MetaUtil.getSimpleName(value.getClass(), true) + ":" + ((Enum<?>) value).name();
+ } else if (value instanceof FormatWithToString) {
+ return MetaUtil.getSimpleName(value.getClass(), true) + ":" + String.valueOf(value);
+ } else if (value instanceof Class<?>) {
+ return "Class:" + ((Class<?>) value).getName();
+ } else if (isToStringSafe(value.getClass())) {
+ return value.toString();
+ } else if (value.getClass().isArray()) {
+ return formatArray(value);
+ } else {
+ return MetaUtil.getSimpleName(value.getClass(), true) + "@" + System.identityHashCode(value);
+ }
+ }
+ }
+ }
+
+ private static final int MAX_FORMAT_ARRAY_LENGTH = 5;
+
+ private static String formatArray(Object array) {
+ Class<?> componentType = array.getClass().getComponentType();
+ assert componentType != null;
+ int arrayLength = Array.getLength(array);
+ StringBuilder buf = new StringBuilder(MetaUtil.getSimpleName(componentType, true)).append('[').append(arrayLength).append("]{");
+ int length = Math.min(MAX_FORMAT_ARRAY_LENGTH, arrayLength);
+ boolean primitive = componentType.isPrimitive();
+ for (int i = 0; i < length; i++) {
+ if (primitive) {
+ buf.append(Array.get(array, i));
+ } else {
+ Object o = ((Object[]) array)[i];
+ buf.append(JavaKind.Object.format(o));
+ }
+ if (i != length - 1) {
+ buf.append(", ");
+ }
+ }
+ if (arrayLength != length) {
+ buf.append(", ...");
+ }
+ return buf.append('}').toString();
+ }
+
+ /**
+ * The minimum value that can be represented as a value of this kind.
+ *
+ * @return the minimum value
+ */
+ public long getMinValue() {
+ switch (this) {
+ case Boolean:
+ return 0;
+ case Byte:
+ return java.lang.Byte.MIN_VALUE;
+ case Char:
+ return java.lang.Character.MIN_VALUE;
+ case Short:
+ return java.lang.Short.MIN_VALUE;
+ case Int:
+ return java.lang.Integer.MIN_VALUE;
+ case Long:
+ return java.lang.Long.MIN_VALUE;
+ default:
+ throw new IllegalArgumentException("illegal call to minValue on " + this);
+ }
+ }
+
+ /**
+ * The maximum value that can be represented as a value of this kind.
+ *
+ * @return the maximum value
+ */
+ public long getMaxValue() {
+ switch (this) {
+ case Boolean:
+ return 1;
+ case Byte:
+ return java.lang.Byte.MAX_VALUE;
+ case Char:
+ return java.lang.Character.MAX_VALUE;
+ case Short:
+ return java.lang.Short.MAX_VALUE;
+ case Int:
+ return java.lang.Integer.MAX_VALUE;
+ case Long:
+ return java.lang.Long.MAX_VALUE;
+ default:
+ throw new IllegalArgumentException("illegal call to maxValue on " + this);
+ }
+ }
+
+ /**
+ * Number of bytes that are necessary to represent a value of this kind.
+ *
+ * @return the number of bytes
+ */
+ public int getByteCount() {
+ if (this == Boolean) {
+ return 1;
+ } else {
+ return getBitCount() >> 3;
+ }
+ }
+
+ /**
+ * Number of bits that are necessary to represent a value of this kind.
+ *
+ * @return the number of bits
+ */
+ public int getBitCount() {
+ switch (this) {
+ case Boolean:
+ return 1;
+ case Byte:
+ return 8;
+ case Char:
+ case Short:
+ return 16;
+ case Float:
+ return 32;
+ case Int:
+ return 32;
+ case Double:
+ return 64;
+ case Long:
+ return 64;
+ default:
+ throw new IllegalArgumentException("illegal call to bits on " + this);
+ }
+ }
+
+ public JavaConstant getDefaultValue() {
+ switch (this) {
+ case Boolean:
+ return JavaConstant.FALSE;
+ case Int:
+ return JavaConstant.INT_0;
+ case Long:
+ return JavaConstant.LONG_0;
+ case Float:
+ return JavaConstant.FLOAT_0;
+ case Double:
+ return JavaConstant.DOUBLE_0;
+ case Object:
+ return JavaConstant.NULL_POINTER;
+ case Byte:
+ case Char:
+ case Short:
+ return new PrimitiveConstant(this, 0);
+ default:
+ throw new IllegalArgumentException("illegal call to getDefaultValue on " + this);
+ }
+ }
+
+ @Override
+ public int getSizeInBytes() {
+ return getByteCount();
+ }
+
+ @Override
+ public int getVectorLength() {
+ return 1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2009, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+/**
+ * Represents a reference to a Java method, either resolved or unresolved. Methods, like fields and
+ * types, are resolved through {@link ConstantPool constant pools}.
+ */
+public interface JavaMethod extends TrustedInterface {
+
+ /**
+ * Returns the name of this method.
+ */
+ String getName();
+
+ /**
+ * Returns the {@link JavaType} object representing the class or interface that declares this
+ * method.
+ */
+ JavaType getDeclaringClass();
+
+ /**
+ * Returns the signature of this method.
+ */
+ Signature getSignature();
+
+ /**
+ * Gets a string for this method formatted according to a given format specification. A format
+ * specification is composed of characters that are to be copied verbatim to the result and
+ * specifiers that denote an attribute of this method that is to be copied to the result. A
+ * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+ * method attributes they denote are described below:
+ *
+ * <pre>
+ * Specifier | Description | Example(s)
+ * ----------+------------------------------------------------------------------------------------------
+ * 'R' | Qualified return type | "int" "java.lang.String"
+ * 'r' | Unqualified return type | "int" "String"
+ * 'H' | Qualified holder | "java.util.Map.Entry"
+ * 'h' | Unqualified holder | "Entry"
+ * 'n' | Method name | "add"
+ * 'P' | Qualified parameter types, separated by ', ' | "int, java.lang.String"
+ * 'p' | Unqualified parameter types, separated by ', ' | "int, String"
+ * 'f' | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
+ * '%' | A '%' character | "%"
+ * </pre>
+ *
+ * @param format a format specification
+ * @return the result of formatting this method according to {@code format}
+ * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+ */
+ @SuppressWarnings("fallthrough")
+ default String format(String format) throws IllegalFormatException {
+ StringBuilder sb = new StringBuilder();
+ int index = 0;
+ Signature sig = null;
+ while (index < format.length()) {
+ char ch = format.charAt(index++);
+ if (ch == '%') {
+ if (index >= format.length()) {
+ throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
+ }
+ char specifier = format.charAt(index++);
+ switch (specifier) {
+ case 'R':
+ case 'r': {
+ if (sig == null) {
+ sig = getSignature();
+ }
+ sb.append(sig.getReturnType(null).toJavaName(specifier == 'R'));
+ break;
+ }
+ case 'H':
+ case 'h': {
+ sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
+ break;
+ }
+ case 'n': {
+ sb.append(getName());
+ break;
+ }
+ case 'P':
+ case 'p': {
+ if (sig == null) {
+ sig = getSignature();
+ }
+ for (int i = 0; i < sig.getParameterCount(false); i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append(sig.getParameterType(i, null).toJavaName(specifier == 'P'));
+ }
+ break;
+ }
+ case 'f': {
+ sb.append(!(this instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) this).isStatic() ? "static" : "virtual");
+ break;
+ }
+ case '%': {
+ sb.append('%');
+ break;
+ }
+ default: {
+ throw new UnknownFormatConversionException(String.valueOf(specifier));
+ }
+ }
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.meta;
+
+import jdk.vm.ci.meta.JavaMethodProfile.*;
+
+/**
+ * This profile object represents the method profile at a specific BCI. The precision of the
+ * supplied values may vary, but a runtime that provides this information should be aware that it
+ * will be used to guide performance-critical decisions like speculative inlining, etc.
+ */
+public final class JavaMethodProfile extends AbstractJavaProfile<ProfiledMethod, ResolvedJavaMethod> {
+
+ public JavaMethodProfile(double notRecordedProbability, ProfiledMethod[] pitems) {
+ super(notRecordedProbability, pitems);
+ }
+
+ public ProfiledMethod[] getMethods() {
+ return super.getItems();
+ }
+
+ public static class ProfiledMethod extends AbstractProfiledItem<ResolvedJavaMethod> {
+
+ public ProfiledMethod(ResolvedJavaMethod method, double probability) {
+ super(method, probability);
+ }
+
+ /**
+ * Returns the type for this profile entry.
+ */
+ public ResolvedJavaMethod getMethod() {
+ return getItem();
+ }
+
+ @Override
+ public String toString() {
+ return "{" + item.getName() + ", " + probability + "}";
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import static jdk.vm.ci.meta.MetaUtil.*;
+
+/**
+ * Represents a resolved or unresolved type. Types include primitives, objects, {@code void}, and
+ * arrays thereof.
+ */
+public interface JavaType extends TrustedInterface {
+
+ /**
+ * Returns the name of this type in internal form. The following are examples of strings
+ * returned by this method:
+ *
+ * <pre>
+ * "Ljava/lang/Object;"
+ * "I"
+ * "[[B"
+ * </pre>
+ */
+ String getName();
+
+ /**
+ * Returns an unqualified name of this type.
+ *
+ * <pre>
+ * "Object"
+ * "Integer"
+ * </pre>
+ */
+ default String getUnqualifiedName() {
+ String name = getName();
+ if (name.indexOf('/') != -1) {
+ name = name.substring(name.lastIndexOf('/') + 1);
+ }
+ if (name.endsWith(";")) {
+ name = name.substring(0, name.length() - 1);
+ }
+ return name;
+ }
+
+ /**
+ * For array types, gets the type of the components, or {@code null} if this is not an array
+ * type. This method is analogous to {@link Class#getComponentType()}.
+ */
+ JavaType getComponentType();
+
+ /**
+ * Gets the elemental type for this given type. The elemental type is the corresponding zero
+ * dimensional type of an array type. For example, the elemental type of {@code int[][][]} is
+ * {@code int}. A non-array type is its own elemental type.
+ */
+ default JavaType getElementalType() {
+ JavaType t = this;
+ while (t.getComponentType() != null) {
+ t = t.getComponentType();
+ }
+ return t;
+ }
+
+ /**
+ * Gets the array class type representing an array with elements of this type.
+ */
+ JavaType getArrayClass();
+
+ /**
+ * Gets the {@link JavaKind} of this type.
+ */
+ JavaKind getJavaKind();
+
+ /**
+ * Resolves this type to a {@link ResolvedJavaType}.
+ *
+ * @param accessingClass the context of resolution (must not be null)
+ * @return the resolved Java type
+ * @throws LinkageError if the resolution failed
+ * @throws NullPointerException if {@code accessingClass} is {@code null}
+ */
+ ResolvedJavaType resolve(ResolvedJavaType accessingClass);
+
+ /**
+ * Gets the Java programming language name for this type. The following are examples of strings
+ * returned by this method:
+ *
+ * <pre>
+ * java.lang.Object
+ * int
+ * boolean[][]
+ * </pre>
+ *
+ * @return the Java name corresponding to this type
+ */
+ default String toJavaName() {
+ return internalNameToJava(getName(), true, false);
+ }
+
+ /**
+ * Gets the Java programming language name for this type. The following are examples of strings
+ * returned by this method:
+ *
+ * <pre>
+ * qualified == true:
+ * java.lang.Object
+ * int
+ * boolean[][]
+ * qualified == false:
+ * Object
+ * int
+ * boolean[][]
+ * </pre>
+ *
+ * @param qualified specifies if the package prefix of this type should be included in the
+ * returned name
+ * @return the Java name corresponding to this type
+ */
+ default String toJavaName(boolean qualified) {
+ JavaKind kind = getJavaKind();
+ if (kind == JavaKind.Object) {
+ return internalNameToJava(getName(), qualified, false);
+ }
+ return getJavaKind().getJavaName();
+ }
+
+ /**
+ * Returns this type's name in the same format as {@link Class#getName()}.
+ */
+ default String toClassName() {
+ return internalNameToJava(getName(), true, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2011, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.JavaTypeProfile.*;
+
+/**
+ * This profile object represents the type profile at a specific BCI. The precision of the supplied
+ * values may vary, but a runtime that provides this information should be aware that it will be
+ * used to guide performance-critical decisions like speculative inlining, etc.
+ */
+public final class JavaTypeProfile extends AbstractJavaProfile<ProfiledType, ResolvedJavaType> {
+
+ private static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
+
+ private final TriState nullSeen;
+
+ public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType[] pitems) {
+ super(notRecordedProbability, pitems);
+ this.nullSeen = nullSeen;
+ }
+
+ /**
+ * Returns whether a null value was at the type check.
+ */
+ public TriState getNullSeen() {
+ return nullSeen;
+ }
+
+ /**
+ * A list of types for which the runtime has recorded probability information. Note that this
+ * includes both positive and negative types where a positive type is a subtype of the checked
+ * type and a negative type is not.
+ */
+ public ProfiledType[] getTypes() {
+ return getItems();
+ }
+
+ public JavaTypeProfile restrict(JavaTypeProfile otherProfile) {
+ if (otherProfile.getNotRecordedProbability() > 0.0) {
+ // Not useful for restricting since there is an unknown set of types occurring.
+ return this;
+ }
+
+ if (this.getNotRecordedProbability() > 0.0) {
+ // We are unrestricted, so the other profile is always a better estimate.
+ return otherProfile;
+ }
+
+ ArrayList<ProfiledType> result = new ArrayList<>();
+ for (int i = 0; i < getItems().length; i++) {
+ ProfiledType ptype = getItems()[i];
+ ResolvedJavaType type = ptype.getItem();
+ if (otherProfile.isIncluded(type)) {
+ result.add(ptype);
+ }
+ }
+
+ TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : getNullSeen();
+ double newNotRecorded = getNotRecordedProbability();
+ return createAdjustedProfile(result, newNullSeen, newNotRecorded);
+ }
+
+ public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) {
+ ArrayList<ProfiledType> result = new ArrayList<>();
+ for (int i = 0; i < getItems().length; i++) {
+ ProfiledType ptype = getItems()[i];
+ ResolvedJavaType type = ptype.getItem();
+ if (declaredType.isAssignableFrom(type)) {
+ result.add(ptype);
+ }
+ }
+
+ TriState newNullSeen = (nonNull) ? TriState.FALSE : getNullSeen();
+ double newNotRecorded = this.getNotRecordedProbability();
+ // Assume for the types not recorded, the incompatibility rate is the same.
+ if (getItems().length != 0) {
+ newNotRecorded *= ((double) result.size() / (double) getItems().length);
+ }
+ return createAdjustedProfile(result, newNullSeen, newNotRecorded);
+ }
+
+ private JavaTypeProfile createAdjustedProfile(ArrayList<ProfiledType> result, TriState newNullSeen, double newNotRecorded) {
+ if (result.size() != this.getItems().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != getNullSeen()) {
+ if (result.size() == 0) {
+ return new JavaTypeProfile(newNullSeen, 1.0, EMPTY_ARRAY);
+ }
+ double factor;
+ if (result.size() == this.getItems().length) {
+ /* List of types did not change, no need to recompute probabilities. */
+ factor = 1.0;
+ } else {
+ double probabilitySum = 0.0;
+ for (int i = 0; i < result.size(); i++) {
+ probabilitySum += result.get(i).getProbability();
+ }
+ probabilitySum += newNotRecorded;
+
+ factor = 1.0 / probabilitySum; // Normalize to 1.0
+ assert factor >= 1.0;
+ }
+ ProfiledType[] newResult = new ProfiledType[result.size()];
+ for (int i = 0; i < newResult.length; ++i) {
+ ProfiledType curType = result.get(i);
+ newResult[i] = new ProfiledType(curType.getItem(), Math.min(1.0, curType.getProbability() * factor));
+ }
+ double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor);
+ return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult);
+ }
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return super.equals(other) && nullSeen.equals(((JavaTypeProfile) other).nullSeen);
+ }
+
+ @Override
+ public int hashCode() {
+ return nullSeen.hashCode() + super.hashCode();
+ }
+
+ public static class ProfiledType extends AbstractProfiledItem<ResolvedJavaType> {
+
+ public ProfiledType(ResolvedJavaType type, double probability) {
+ super(type, probability);
+ assert type.isArray() || type.isConcrete() : type;
+ }
+
+ /**
+ * Returns the type for this profile entry.
+ */
+ public ResolvedJavaType getType() {
+ return getItem();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%.6f#%s", probability, item);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder("JavaTypeProfile<nullSeen=").append(getNullSeen()).append(", types=[");
+ for (int j = 0; j < getTypes().length; j++) {
+ if (j != 0) {
+ buf.append(", ");
+ }
+ ProfiledType ptype = getTypes()[j];
+ buf.append(String.format("%.6f:%s", ptype.getProbability(), ptype.getType()));
+ }
+ return buf.append(String.format("], notRecorded:%.6f>", getNotRecordedProbability())).toString();
+ }
+
+ /**
+ * Returns {@code true} if all types seen at this location have been recorded in the profile.
+ */
+ public boolean allTypesRecorded() {
+ return this.getNotRecordedProbability() == 0.0;
+ }
+
+ /**
+ * Returns the single monormorphic type representing this profile or {@code null} if no such
+ * type exists.
+ */
+ public ResolvedJavaType asSingleType() {
+ if (allTypesRecorded() && this.getTypes().length == 1) {
+ return getTypes()[0].getType();
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Marker interface for things that represent a Java value.
+ */
+public interface JavaValue {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+/**
+ * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
+ * low level representation of the value, and a {@link #referenceMask} that describes the location
+ * of object references in the value, and optionally a {@link #derivedReferenceBase}.
+ *
+ * <h2>Constructing {@link LIRKind} instances</h2>
+ *
+ * During LIR generation, every new {@link Value} should get a {@link LIRKind} of the correct
+ * {@link PlatformKind} that also contains the correct reference information. {@linkplain LIRKind
+ * LIRKinds} should be created as follows:
+ *
+ * <p>
+ * If the result value is created from one or more input values, the {@link LIRKind} should be
+ * created with {@link LIRKind#combine}(inputs). If the result has a different {@link PlatformKind}
+ * than the inputs, {@link LIRKind#combine}(inputs).{@link #changeType}(resultKind) should be used.
+ * <p>
+ * If the result is an exact copy of one of the inputs, {@link Value#getLIRKind()} can be used. Note
+ * that this is only correct for move-like operations, like conditional move or compare-and-swap.
+ * For convert operations, {@link LIRKind#combine} should be used.
+ * <p>
+ * If it is known that the result will be a reference (e.g. pointer arithmetic where the end result
+ * is a valid oop), {@link LIRKind#reference} should be used.
+ * <p>
+ * If it is known that the result will neither be a reference nor be derived from a reference,
+ * {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very
+ * likely wrong, and {@link LIRKind#combine} should be used instead.
+ * <p>
+ * If it is known that the result is derived from a reference in a way that the garbage collector
+ * can not track, {@link LIRKind#unknownReference} can be used. In most cases,
+ * {@link LIRKind#combine} should be used instead, since it is able to detect this automatically.
+ */
+public final class LIRKind {
+
+ /**
+ * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map.
+ */
+ public static final LIRKind Illegal = unknownReference(JavaKind.Illegal);
+
+ private final PlatformKind platformKind;
+ private final int referenceMask;
+
+ private AllocatableValue derivedReferenceBase;
+
+ private static final int UNKNOWN_REFERENCE = -1;
+
+ private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
+ assert platformKind != JavaKind.Object : "Kind.Object shouldn't be used in the backend";
+ this.platformKind = platformKind;
+ this.referenceMask = referenceMask;
+ this.derivedReferenceBase = derivedReferenceBase;
+
+ assert derivedReferenceBase == null || !derivedReferenceBase.getLIRKind().isDerivedReference() : "derived reference can't have another derived reference as base";
+ }
+
+ /**
+ * Create a {@link LIRKind} of type {@code platformKind} that contains a primitive value. Should
+ * be only used when it's guaranteed that the value is not even indirectly derived from a
+ * reference. Otherwise, {@link #combine(Value...)} should be used instead.
+ */
+ public static LIRKind value(PlatformKind platformKind) {
+ return new LIRKind(platformKind, 0, null);
+ }
+
+ /**
+ * Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop
+ * reference.
+ */
+ public static LIRKind reference(PlatformKind platformKind) {
+ return derivedReference(platformKind, null);
+ }
+
+ /**
+ * Create a {@link LIRKind} of type {@code platformKind} that contains a derived reference.
+ */
+ public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base) {
+ int length = platformKind.getVectorLength();
+ assert 0 < length && length < 32 : "vector of " + length + " references not supported";
+ return new LIRKind(platformKind, (1 << length) - 1, base);
+ }
+
+ /**
+ * Create a {@link LIRKind} of type {@code platformKind} that contains a value that is derived
+ * from a reference in a non-linear way. Values of this {@link LIRKind} can not be live at
+ * safepoints. In most cases, this should not be called directly. {@link #combine} should be
+ * used instead to automatically propagate this information.
+ */
+ public static LIRKind unknownReference(PlatformKind platformKind) {
+ return new LIRKind(platformKind, UNKNOWN_REFERENCE, null);
+ }
+
+ /**
+ * Create a derived reference.
+ *
+ * @param base An {@link AllocatableValue} containing the base pointer of the derived reference.
+ */
+ public LIRKind makeDerivedReference(AllocatableValue base) {
+ assert !isUnknownReference() && derivedReferenceBase == null;
+ if (Value.ILLEGAL.equals(base)) {
+ return makeUnknownReference();
+ } else {
+ if (isValue()) {
+ return derivedReference(platformKind, base);
+ } else {
+ return new LIRKind(platformKind, referenceMask, base);
+ }
+ }
+ }
+
+ /**
+ * Derive a new type from inputs. The result will have the {@link PlatformKind} of one of the
+ * inputs. If all inputs are values, the result is a value. Otherwise, the result is an unknown
+ * reference.
+ *
+ * This method should be used to construct the result {@link LIRKind} of any operation that
+ * modifies values (e.g. arithmetics).
+ */
+ public static LIRKind combine(Value... inputs) {
+ assert inputs.length > 0;
+ for (Value input : inputs) {
+ LIRKind kind = input.getLIRKind();
+ if (kind.isUnknownReference()) {
+ return kind;
+ } else if (!kind.isValue()) {
+ return kind.makeUnknownReference();
+ }
+ }
+
+ // all inputs are values, just return one of them
+ return inputs[0].getLIRKind();
+ }
+
+ /**
+ * Merge the types of the inputs. The result will have the {@link PlatformKind} of one of the
+ * inputs. If all inputs are values (references), the result is a value (reference). Otherwise,
+ * the result is an unknown reference.
+ *
+ * This method should be used to construct the result {@link LIRKind} of merge operation that
+ * does not modify values (e.g. phis).
+ */
+ public static LIRKind merge(Value... inputs) {
+ assert inputs.length > 0;
+ ArrayList<LIRKind> kinds = new ArrayList<>(inputs.length);
+ for (int i = 0; i < inputs.length; i++) {
+ kinds.add(inputs[i].getLIRKind());
+ }
+ return merge(kinds);
+ }
+
+ /**
+ * Helper method to construct derived reference kinds. Returns the base value of a reference or
+ * derived reference. For values it returns {@code null}, and for unknown references it returns
+ * {@link Value#ILLEGAL}.
+ */
+ public static AllocatableValue derivedBaseFromValue(AllocatableValue value) {
+ LIRKind kind = value.getLIRKind();
+ if (kind.isValue()) {
+ return null;
+ } else if (kind.isDerivedReference()) {
+ return kind.getDerivedReferenceBase();
+ } else if (kind.isUnknownReference()) {
+ return Value.ILLEGAL;
+ } else {
+ // kind is a reference
+ return value;
+ }
+ }
+
+ /**
+ * Helper method to construct derived reference kinds. If one of {@code base1} or {@code base2}
+ * are set, it creates a derived reference using it as the base. If both are set, the result is
+ * an unknown reference.
+ */
+ public static LIRKind combineDerived(LIRKind kind, AllocatableValue base1, AllocatableValue base2) {
+ if (base1 == null && base2 == null) {
+ return kind;
+ } else if (base1 == null) {
+ return kind.makeDerivedReference(base2);
+ } else if (base2 == null) {
+ return kind.makeDerivedReference(base1);
+ } else {
+ return kind.makeUnknownReference();
+ }
+ }
+
+ /**
+ * @see #merge(Value...)
+ */
+ public static LIRKind merge(Iterable<LIRKind> kinds) {
+ LIRKind mergeKind = null;
+
+ for (LIRKind kind : kinds) {
+
+ if (kind.isUnknownReference()) {
+ /**
+ * Kind is an unknown reference, therefore the result can only be also an unknown
+ * reference.
+ */
+ mergeKind = kind;
+ break;
+ }
+ if (mergeKind == null) {
+ mergeKind = kind;
+ continue;
+ }
+
+ if (kind.isValue()) {
+ /* Kind is a value. */
+ if (mergeKind.referenceMask != 0) {
+ /*
+ * Inputs consists of values and references. Make the result an unknown
+ * reference.
+ */
+ mergeKind = mergeKind.makeUnknownReference();
+ break;
+ }
+ /* Check that other inputs are also values. */
+ } else {
+ /* Kind is a reference. */
+ if (mergeKind.referenceMask != kind.referenceMask) {
+ /*
+ * Reference maps do not match so the result can only be an unknown reference.
+ */
+ mergeKind = mergeKind.makeUnknownReference();
+ break;
+ }
+ }
+
+ }
+ assert mergeKind != null && verifyMerge(mergeKind, kinds);
+
+ // all inputs are values or references, just return one of them
+ return mergeKind;
+ }
+
+ private static boolean verifyMerge(LIRKind mergeKind, Iterable<LIRKind> kinds) {
+ for (LIRKind kind : kinds) {
+ assert mergeKind == null || verifyMoveKinds(mergeKind, kind) : String.format("Input kinds do not match %s vs. %s", mergeKind, kind);
+ }
+ return true;
+ }
+
+ /**
+ * Create a new {@link LIRKind} with the same reference information and a new
+ * {@linkplain #getPlatformKind platform kind}. If the new kind is a longer vector than this,
+ * the new elements are marked as untracked values.
+ */
+ public LIRKind changeType(PlatformKind newPlatformKind) {
+ if (newPlatformKind == platformKind) {
+ return this;
+ } else if (isUnknownReference()) {
+ return unknownReference(newPlatformKind);
+ } else if (referenceMask == 0) {
+ // value type
+ return LIRKind.value(newPlatformKind);
+ } else {
+ // reference type
+ int newLength = Math.min(32, newPlatformKind.getVectorLength());
+ int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength));
+ assert newReferenceMask != UNKNOWN_REFERENCE;
+ return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
+ }
+ }
+
+ /**
+ * Create a new {@link LIRKind} with a new {@linkplain #getPlatformKind platform kind}. If the
+ * new kind is longer than this, the reference positions are repeated to fill the vector.
+ */
+ public LIRKind repeat(PlatformKind newPlatformKind) {
+ if (isUnknownReference()) {
+ return unknownReference(newPlatformKind);
+ } else if (referenceMask == 0) {
+ // value type
+ return LIRKind.value(newPlatformKind);
+ } else {
+ // reference type
+ int oldLength = platformKind.getVectorLength();
+ int newLength = newPlatformKind.getVectorLength();
+ assert oldLength <= newLength && newLength < 32 && (newLength % oldLength) == 0;
+
+ // repeat reference mask to fill new kind
+ int newReferenceMask = 0;
+ for (int i = 0; i < newLength; i += platformKind.getVectorLength()) {
+ newReferenceMask |= referenceMask << i;
+ }
+
+ assert newReferenceMask != UNKNOWN_REFERENCE;
+ return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
+ }
+ }
+
+ /**
+ * Create a new {@link LIRKind} with the same type, but marked as containing an
+ * {@link LIRKind#unknownReference}.
+ */
+ public LIRKind makeUnknownReference() {
+ return new LIRKind(platformKind, UNKNOWN_REFERENCE, null);
+ }
+
+ /**
+ * Get the low level type that is used in code generation.
+ */
+ public PlatformKind getPlatformKind() {
+ return platformKind;
+ }
+
+ /**
+ * Check whether this value is a derived reference.
+ */
+ public boolean isDerivedReference() {
+ return getDerivedReferenceBase() != null;
+ }
+
+ /**
+ * Get the base value of a derived reference.
+ */
+ public AllocatableValue getDerivedReferenceBase() {
+ return derivedReferenceBase;
+ }
+
+ /**
+ * Change the base value of a derived reference. This must be called on derived references only.
+ */
+ public void setDerivedReferenceBase(AllocatableValue derivedReferenceBase) {
+ assert isDerivedReference();
+ this.derivedReferenceBase = derivedReferenceBase;
+ }
+
+ /**
+ * Check whether this value is derived from a reference in a non-linear way. If this returns
+ * {@code true}, this value must not be live at safepoints.
+ */
+ public boolean isUnknownReference() {
+ return referenceMask == UNKNOWN_REFERENCE;
+ }
+
+ public int getReferenceCount() {
+ assert !isUnknownReference();
+ return Integer.bitCount(referenceMask);
+ }
+
+ /**
+ * Check whether the {@code idx}th part of this value is a reference that must be tracked at
+ * safepoints.
+ *
+ * @param idx The index into the vector if this is a vector kind. Must be 0 if this is a scalar
+ * kind.
+ */
+ public boolean isReference(int idx) {
+ assert 0 <= idx && idx < platformKind.getVectorLength() : "invalid index " + idx + " in " + this;
+ return !isUnknownReference() && (referenceMask & 1 << idx) != 0;
+ }
+
+ /**
+ * Check whether this kind is a value type that doesn't need to be tracked at safepoints.
+ */
+ public boolean isValue() {
+ return referenceMask == 0;
+ }
+
+ @Override
+ public String toString() {
+ if (isValue()) {
+ return platformKind.name();
+ } else if (isUnknownReference()) {
+ return platformKind.name() + "[*]";
+ } else {
+ StringBuilder ret = new StringBuilder();
+ ret.append(platformKind.name());
+ ret.append('[');
+ for (int i = 0; i < platformKind.getVectorLength(); i++) {
+ if (isReference(i)) {
+ ret.append('.');
+ } else {
+ ret.append(' ');
+ }
+ }
+ ret.append(']');
+ return ret.toString();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((platformKind == null) ? 0 : platformKind.hashCode());
+ result = prime * result + referenceMask;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof LIRKind)) {
+ return false;
+ }
+
+ LIRKind other = (LIRKind) obj;
+ return platformKind == other.platformKind && referenceMask == other.referenceMask;
+ }
+
+ public static boolean verifyMoveKinds(LIRKind dst, LIRKind src) {
+ if (src.equals(dst)) {
+ return true;
+ }
+ /*
+ * TODO(je,rs) What we actually want is toStackKind(src.getPlatformKind()).equals(
+ * dst.getPlatformKind()) but due to the handling of sub-integer at the current point
+ * (phi-)moves from e.g. integer to short can happen. Therefore we compare stack kinds.
+ */
+ if (toStackKind(src.getPlatformKind()).equals(toStackKind(dst.getPlatformKind()))) {
+ return !src.isUnknownReference() || dst.isUnknownReference();
+ }
+ return false;
+ }
+
+ private static PlatformKind toStackKind(PlatformKind platformKind) {
+ if (platformKind instanceof JavaKind) {
+ return ((JavaKind) platformKind).getStackKind();
+ }
+ return platformKind;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTable.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+public interface LineNumberTable {
+
+ int[] getLineNumberEntries();
+
+ int[] getBciEntries();
+
+ int getLineNumber(int bci);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTableImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+public class LineNumberTableImpl implements LineNumberTable {
+
+ private final int[] lineNumbers;
+ private final int[] bci;
+
+ public LineNumberTableImpl(int[] lineNumbers, int[] bci) {
+ this.lineNumbers = lineNumbers;
+ this.bci = bci;
+ }
+
+ @Override
+ public int[] getLineNumberEntries() {
+ return lineNumbers;
+ }
+
+ @Override
+ public int[] getBciEntries() {
+ return bci;
+ }
+
+ @Override
+ public int getLineNumber(@SuppressWarnings("hiding") int bci) {
+ for (int i = 0; i < this.bci.length - 1; i++) {
+ if (this.bci[i] <= bci && bci < this.bci[i + 1]) {
+ return lineNumbers[i];
+ }
+ }
+ return lineNumbers[lineNumbers.length - 1];
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Local.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+public interface Local {
+
+ int getStartBCI();
+
+ int getEndBCI();
+
+ int getSlot();
+
+ String getName();
+
+ JavaType getType();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+public class LocalImpl implements Local {
+
+ private final String name;
+ private final int startBci;
+ private final int endBci;
+ private final int slot;
+ private final JavaType type;
+
+ public LocalImpl(String name, JavaType type, int startBci, int endBci, int slot) {
+ this.name = name;
+ this.startBci = startBci;
+ this.endBci = endBci;
+ this.slot = slot;
+ this.type = type;
+ }
+
+ @Override
+ public int getStartBCI() {
+ return startBci;
+ }
+
+ @Override
+ public int getEndBCI() {
+ return endBci;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public JavaType getType() {
+ return type;
+ }
+
+ @Override
+ public int getSlot() {
+ return slot;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof LocalImpl)) {
+ return false;
+ }
+ LocalImpl that = (LocalImpl) obj;
+ return this.name.equals(that.name) && this.startBci == that.startBci && this.endBci == that.endBci && this.slot == that.slot && this.type.equals(that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "LocalImpl<name=" + name + ", type=" + type + ", startBci=" + startBci + ", endBci=" + endBci + ", slot=" + slot + ">";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTable.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+public interface LocalVariableTable {
+
+ Local[] getLocals();
+
+ Local[] getLocalsAt(int bci);
+
+ Local getLocal(int slot, int bci);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+public class LocalVariableTableImpl implements LocalVariableTable {
+
+ private final Local[] locals;
+
+ public LocalVariableTableImpl(Local[] locals) {
+ this.locals = locals;
+ }
+
+ @Override
+ public Local getLocal(int slot, int bci) {
+ Local result = null;
+ for (Local local : locals) {
+ if (local.getSlot() == slot && local.getStartBCI() <= bci && local.getEndBCI() >= bci) {
+ if (result == null) {
+ result = local;
+ } else {
+ throw new IllegalStateException("Locals overlap!");
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Local[] getLocals() {
+ return locals;
+ }
+
+ @Override
+ public Local[] getLocalsAt(int bci) {
+ List<Local> result = new ArrayList<>();
+ for (Local l : locals) {
+ if (l.getStartBCI() <= bci && bci <= l.getEndBCI()) {
+ result.add(l);
+ }
+ }
+ return result.toArray(new Local[result.size()]);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+
+// JaCoCo Exclude
+
+/**
+ * Marker interface for location identities. A different location identity of two memory accesses
+ * guarantees that the two accesses do not interfere.
+ *
+ * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when
+ * comparing two {@link LocationIdentity} values for equality. Likewise, they must not use
+ * {@link IdentityHashMap}s with {@link LocationIdentity} values as keys.
+ */
+public abstract class LocationIdentity {
+
+ private static final class AnyLocationIdentity extends LocationIdentity {
+ @Override
+ public boolean isImmutable() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "ANY_LOCATION";
+ }
+ }
+
+ public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
+
+ public static LocationIdentity any() {
+ return ANY_LOCATION;
+ }
+
+ /**
+ * Denotes a location is unchanging in all cases. Not that this is different than the Java
+ * notion of final which only requires definite assignment.
+ */
+ public abstract boolean isImmutable();
+
+ public final boolean isMutable() {
+ return !isImmutable();
+ }
+
+ public final boolean isAny() {
+ return this == ANY_LOCATION;
+ }
+
+ public final boolean isSingle() {
+ return this != ANY_LOCATION;
+ }
+
+ public final boolean overlaps(LocationIdentity other) {
+ return isAny() || other.isAny() || this.equals(other);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MemoryAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Provides memory access operations for the target VM.
+ */
+public interface MemoryAccessProvider {
+
+ /**
+ * Reads a value of this kind using a base address and a displacement. No bounds checking or
+ * type checking is performed. Returns {@code null} if the value is not available at this point.
+ *
+ * @param base the base address from which the value is read.
+ * @param displacement the displacement within the object in bytes
+ * @return the read value encapsulated in a {@link JavaConstant} object, or {@code null} if the
+ * value cannot be read.
+ */
+ JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant base, long displacement);
+
+ /**
+ * Reads a primitive value using a base address and a displacement.
+ *
+ * @param kind the {@link JavaKind} of the returned {@link JavaConstant} object
+ * @param base the base address from which the value is read
+ * @param displacement the displacement within the object in bytes
+ * @param bits the number of bits to read from memory
+ * @return the read value encapsulated in a {@link JavaConstant} object of {@link JavaKind} kind
+ */
+ JavaConstant readPrimitiveConstant(JavaKind kind, Constant base, long displacement, int bits);
+
+ /**
+ * Reads a Java {@link Object} value using a base address and a displacement.
+ *
+ * @param base the base address from which the value is read
+ * @param displacement the displacement within the object in bytes
+ * @return the read value encapsulated in a {@link Constant} object
+ */
+ JavaConstant readObjectConstant(Constant base, long displacement);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.*;
+
+/**
+ * Provides access to the metadata of a class typically provided in a class file.
+ */
+public interface MetaAccessProvider {
+
+ /**
+ * Returns the resolved Java type representing a given Java class.
+ *
+ * @param clazz the Java class object
+ * @return the resolved Java type object
+ */
+ ResolvedJavaType lookupJavaType(Class<?> clazz);
+
+ /**
+ * Returns the resolved Java types representing some given Java classes.
+ *
+ * @param classes the Java class objects
+ * @return the resolved Java type objects
+ */
+ default ResolvedJavaType[] lookupJavaTypes(Class<?>[] classes) {
+ ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = lookupJavaType(classes[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Provides the {@link ResolvedJavaMethod} for a {@link Method} or {@link Constructor} obtained
+ * via reflection.
+ */
+ ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod);
+
+ /**
+ * Provides the {@link ResolvedJavaField} for a {@link Field} obtained via reflection.
+ */
+ ResolvedJavaField lookupJavaField(Field reflectionField);
+
+ /**
+ * Returns the resolved Java type of the given {@link JavaConstant} object.
+ *
+ * @return {@code null} if {@code constant.isNull() || !constant.kind.isObject()}
+ */
+ ResolvedJavaType lookupJavaType(JavaConstant constant);
+
+ /**
+ * Returns the number of bytes occupied by this constant value or constant object.
+ *
+ * @param constant the constant whose bytes should be measured
+ * @return the number of bytes occupied by this constant
+ */
+ long getMemorySize(JavaConstant constant);
+
+ /**
+ * Parses a <a
+ * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+ * descriptor</a> into a {@link Signature}. The behavior of this method is undefined if the
+ * method descriptor is not well formed.
+ */
+ Signature parseMethodDescriptor(String methodDescriptor);
+
+ /**
+ * Encodes a deoptimization action and a deoptimization reason in an integer value.
+ *
+ * @param debugId an integer that can be used to track the origin of a deoptimization at
+ * runtime. There is no guarantee that the runtime will use this value. The runtime
+ * may even keep fewer than 32 bits.
+ *
+ * @return the encoded value as an integer
+ */
+ JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
+
+ DeoptimizationReason decodeDeoptReason(JavaConstant constant);
+
+ DeoptimizationAction decodeDeoptAction(JavaConstant constant);
+
+ int decodeDebugId(JavaConstant constant);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients.
+ */
+public class MetaUtil {
+
+ private static class ClassInfo {
+ public long totalSize;
+ public long instanceCount;
+
+ @Override
+ public String toString() {
+ return "totalSize=" + totalSize + ", instanceCount=" + instanceCount;
+ }
+ }
+
+ /**
+ * Returns the number of bytes occupied by this constant value or constant object and
+ * recursively all values reachable from this value.
+ *
+ * @param constant the constant whose bytes should be measured
+ * @param printTopN print total size and instance count of the top n classes is desired
+ * @return the number of bytes occupied by this constant
+ */
+ public static long getMemorySizeRecursive(MetaAccessProvider access, ConstantReflectionProvider constantReflection, JavaConstant constant, PrintStream out, int printTopN) {
+ Set<JavaConstant> marked = new HashSet<>();
+ Deque<JavaConstant> stack = new ArrayDeque<>();
+ if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) {
+ marked.add(constant);
+ }
+ final HashMap<ResolvedJavaType, ClassInfo> histogram = new HashMap<>();
+ stack.push(constant);
+ long sum = 0;
+ while (!stack.isEmpty()) {
+ JavaConstant c = stack.pop();
+ long memorySize = access.getMemorySize(constant);
+ sum += memorySize;
+ if (c.getJavaKind() == JavaKind.Object && c.isNonNull()) {
+ ResolvedJavaType clazz = access.lookupJavaType(c);
+ if (!histogram.containsKey(clazz)) {
+ histogram.put(clazz, new ClassInfo());
+ }
+ ClassInfo info = histogram.get(clazz);
+ info.instanceCount++;
+ info.totalSize += memorySize;
+ ResolvedJavaType type = access.lookupJavaType(c);
+ if (type.isArray()) {
+ if (!type.getComponentType().isPrimitive()) {
+ int length = constantReflection.readArrayLength(c);
+ for (int i = 0; i < length; i++) {
+ JavaConstant value = constantReflection.readArrayElement(c, i);
+ pushConstant(marked, stack, value);
+ }
+ }
+ } else {
+ ResolvedJavaField[] instanceFields = type.getInstanceFields(true);
+ for (ResolvedJavaField f : instanceFields) {
+ if (f.getJavaKind() == JavaKind.Object) {
+ JavaConstant value = constantReflection.readFieldValue(f, c);
+ pushConstant(marked, stack, value);
+ }
+ }
+ }
+ }
+ }
+ ArrayList<ResolvedJavaType> clazzes = new ArrayList<>();
+ clazzes.addAll(histogram.keySet());
+ Collections.sort(clazzes, new Comparator<ResolvedJavaType>() {
+
+ @Override
+ public int compare(ResolvedJavaType o1, ResolvedJavaType o2) {
+ long l1 = histogram.get(o1).totalSize;
+ long l2 = histogram.get(o2).totalSize;
+ if (l1 > l2) {
+ return -1;
+ } else if (l1 == l2) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+
+ int z = 0;
+ for (ResolvedJavaType c : clazzes) {
+ if (z > printTopN) {
+ break;
+ }
+ out.println("Class " + c + ", " + histogram.get(c));
+ ++z;
+ }
+
+ return sum;
+ }
+
+ private static void pushConstant(Set<JavaConstant> marked, Deque<JavaConstant> stack, JavaConstant value) {
+ if (value.isNonNull()) {
+ if (!marked.contains(value)) {
+ marked.add(value);
+ stack.push(value);
+ }
+ }
+ }
+
+ /**
+ * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types.
+ */
+ public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) {
+ ResolvedJavaType[] result = new ResolvedJavaType[types.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = types[i].resolve(accessingClass);
+ }
+ return result;
+ }
+
+ /**
+ * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for
+ * anonymous and local classes.
+ *
+ * @param clazz the class for which the simple name is being requested
+ * @param withEnclosingClass specifies if the returned name should be qualified with the name(s)
+ * of the enclosing class/classes of {@code clazz} (if any). This option is ignored
+ * if {@code clazz} denotes an anonymous or local class.
+ * @return the simple name
+ */
+ public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) {
+ final String simpleName = clazz.getSimpleName();
+ if (simpleName.length() != 0) {
+ if (withEnclosingClass) {
+ String prefix = "";
+ Class<?> enclosingClass = clazz;
+ while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
+ prefix = enclosingClass.getSimpleName() + "." + prefix;
+ }
+ return prefix + simpleName;
+ }
+ return simpleName;
+ }
+ // Must be an anonymous or local class
+ final String name = clazz.getName();
+ int index = name.indexOf('$');
+ if (index == -1) {
+ return name;
+ }
+ index = name.lastIndexOf('.', index);
+ if (index == -1) {
+ return name;
+ }
+ return name.substring(index + 1);
+ }
+
+ static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
+ switch (name.charAt(0)) {
+ case 'L': {
+ String result = name.substring(1, name.length() - 1).replace('/', '.');
+ if (!qualified) {
+ final int lastDot = result.lastIndexOf('.');
+ if (lastDot != -1) {
+ result = result.substring(lastDot + 1);
+ }
+ }
+ return result;
+ }
+ case '[':
+ return classForNameCompatible ? name.replace('/', '.') : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
+ default:
+ if (name.length() != 1) {
+ throw new IllegalArgumentException("Illegal internal name: " + name);
+ }
+ return JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)).getJavaName();
+ }
+ }
+
+ /**
+ * Turns an class name in internal format into a resolved Java type.
+ */
+ public static ResolvedJavaType classForName(String internal, MetaAccessProvider metaAccess, ClassLoader cl) {
+ JavaKind k = JavaKind.fromTypeString(internal);
+ try {
+ String n = internalNameToJava(internal, true, true);
+ return metaAccess.lookupJavaType(k.isPrimitive() ? k.toJavaClass() : Class.forName(n, true, cl));
+ } catch (ClassNotFoundException cnfe) {
+ throw new IllegalArgumentException("could not instantiate class described by " + internal, cnfe);
+ }
+ }
+
+ /**
+ * Convenient shortcut for calling
+ * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a
+ * {@link StringBuilder} instance and convert the result to a string.
+ */
+ public static String toLocation(ResolvedJavaMethod method, int bci) {
+ return appendLocation(new StringBuilder(), method, bci).toString();
+ }
+
+ /**
+ * Appends a string representation of a location specified by a given method and bci to a given
+ * {@link StringBuilder}. If a stack trace element with a non-null file name and non-negative
+ * line number is {@linkplain ResolvedJavaMethod#asStackTraceElement(int) available} for the
+ * given method, then the string returned is the {@link StackTraceElement#toString()} value of
+ * the stack trace element, suffixed by the bci location. For example:
+ *
+ * <pre>
+ * java.lang.String.valueOf(String.java:2930) [bci: 12]
+ * </pre>
+ *
+ * Otherwise, the string returned is the value of applying {@link JavaMethod#format(String)}
+ * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location. For example:
+ *
+ * <pre>
+ * java.lang.String.valueOf(int) [bci: 12]
+ * </pre>
+ *
+ * @param sb
+ * @param method
+ * @param bci
+ */
+ public static StringBuilder appendLocation(StringBuilder sb, ResolvedJavaMethod method, int bci) {
+ if (method != null) {
+ StackTraceElement ste = method.asStackTraceElement(bci);
+ if (ste.getFileName() != null && ste.getLineNumber() > 0) {
+ sb.append(ste);
+ } else {
+ sb.append(method.format("%H.%n(%p)"));
+ }
+ } else {
+ sb.append("Null method");
+ }
+ return sb.append(" [bci: ").append(bci).append(']');
+ }
+
+ static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile, int bci, String type, String sep) {
+ if (profile != null) {
+ AbstractProfiledItem<?>[] pitems = profile.getItems();
+ if (pitems != null) {
+ buf.append(String.format("%s@%d:", type, bci));
+ for (int j = 0; j < pitems.length; j++) {
+ AbstractProfiledItem<?> pitem = pitems[j];
+ buf.append(String.format(" %.6f (%s)%s", pitem.getProbability(), pitem.getItem(), sep));
+ }
+ if (profile.getNotRecordedProbability() != 0) {
+ buf.append(String.format(" %.6f <other %s>%s", profile.getNotRecordedProbability(), type, sep));
+ } else {
+ buf.append(String.format(" <no other %s>%s", type, sep));
+ }
+ }
+ }
+ }
+
+ /**
+ * Converts a Java source-language class name into the internal form.
+ *
+ * @param className the class name
+ * @return the internal name form of the class name
+ */
+ public static String toInternalName(String className) {
+ if (className.startsWith("[")) {
+ /* Already in the correct array style. */
+ return className.replace('.', '/');
+ }
+
+ StringBuilder result = new StringBuilder();
+ String base = className;
+ while (base.endsWith("[]")) {
+ result.append("[");
+ base = base.substring(0, base.length() - 2);
+ }
+
+ switch (base) {
+ case "boolean":
+ result.append("Z");
+ break;
+ case "byte":
+ result.append("B");
+ break;
+ case "short":
+ result.append("S");
+ break;
+ case "char":
+ result.append("C");
+ break;
+ case "int":
+ result.append("I");
+ break;
+ case "float":
+ result.append("F");
+ break;
+ case "long":
+ result.append("J");
+ break;
+ case "double":
+ result.append("D");
+ break;
+ case "void":
+ result.append("V");
+ break;
+ default:
+ result.append("L").append(base.replace('.', '/')).append(";");
+ break;
+ }
+ return result.toString();
+ }
+
+ /**
+ * Prepends the String {@code indentation} to every line in String {@code lines}, including a
+ * possibly non-empty line following the final newline.
+ */
+ public static String indent(String lines, String indentation) {
+ if (lines.length() == 0) {
+ return lines;
+ }
+ final String newLine = "\n";
+ if (lines.endsWith(newLine)) {
+ return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine;
+ }
+ return indentation + lines.replace(newLine, newLine + indentation);
+ }
+
+ /**
+ * Gets a string representation of an object based soley on its class and its
+ * {@linkplain System#identityHashCode(Object) identity hash code}. This avoids and calls to
+ * virtual methods on the object such as {@link Object#hashCode()}.
+ */
+ public static String identityHashCodeString(Object obj) {
+ if (obj == null) {
+ return "null";
+ }
+ return obj.getClass().getName() + "@" + System.identityHashCode(obj);
+ }
+
+ /**
+ * Used to lookup constants from {@link Modifier} that are not public (VARARGS, SYNTHETIC etc.).
+ */
+ static int getNonPublicModifierStaticField(String name) {
+ try {
+ Field field = Modifier.class.getDeclaredField(name);
+ field.setAccessible(true);
+ return field.getInt(null);
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+ throw new InternalError(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.invoke.*;
+
+/**
+ * Interface to access the internals of the {@link MethodHandle} implementation of the VM. An
+ * implementation of this interface is usually required to access non-public classes, methods, and
+ * fields of {@link MethodHandle}, i.e., data that is not standardized by the Java specification.
+ */
+public interface MethodHandleAccessProvider {
+
+ /**
+ * Identification for methods defined on the class {@link MethodHandle} that are processed by
+ * the {@link MethodHandleAccessProvider}.
+ */
+ public enum IntrinsicMethod {
+ /** The method {@code MethodHandle.invokeBasic}. */
+ INVOKE_BASIC,
+ /** The method {@code MethodHandle.linkToStatic}. */
+ LINK_TO_STATIC,
+ /** The method {@code MethodHandle.linkToSpecial}. */
+ LINK_TO_SPECIAL,
+ /** The method {@code MethodHandle.linkToVirtual}. */
+ LINK_TO_VIRTUAL,
+ /** The method {@code MethodHandle.linkToInterface}. */
+ LINK_TO_INTERFACE
+ }
+
+ /**
+ * Returns the method handle method intrinsic identifier for the provided method, or
+ * {@code null} if the method is not an intrinsic processed by this interface.
+ */
+ IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method);
+
+ /**
+ * Resolves the invocation target for an invocation of {@link IntrinsicMethod#INVOKE_BASIC
+ * MethodHandle.invokeBasic} with the given constant receiver {@link MethodHandle}. Returns
+ * {@code null} if the invocation target is not available at this time.
+ * <p>
+ * The first invocations of a method handle can use an interpreter to lookup the actual invoked
+ * method; frequently executed method handles can use Java bytecode generation to avoid the
+ * interpreter overhead. If the parameter forceBytecodeGeneration is set to true, the VM should
+ * try to generate bytecodes before this method returns.
+ */
+ ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration);
+
+ /**
+ * Resolves the invocation target for an invocation of a {@code MethodHandle.linkTo*} method
+ * with the given constant member name. The member name is the last parameter of the
+ * {@code linkTo*} method. Returns {@code null} if the invocation target is not available at
+ * this time.
+ */
+ ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.meta;
+
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+
+/**
+ * A Java element (i.e., a class, interface, field or method) that is described by a set of Java
+ * language {@linkplain #getModifiers() modifiers}.
+ */
+public interface ModifiersProvider {
+ int BRIDGE = MetaUtil.getNonPublicModifierStaticField("BRIDGE");
+ int VARARGS = MetaUtil.getNonPublicModifierStaticField("VARARGS");
+ int SYNTHETIC = MetaUtil.getNonPublicModifierStaticField("SYNTHETIC");
+ int ANNOTATION = MetaUtil.getNonPublicModifierStaticField("ANNOTATION");
+ int ENUM = MetaUtil.getNonPublicModifierStaticField("ENUM");
+ int MANDATED = MetaUtil.getNonPublicModifierStaticField("MANDATED");
+
+ /**
+ * Returns the Java Virtual Machine modifiers for this element. Note that this can differ from
+ * standard Java Reflection modifiers. For example at the JVM level, classes (
+ * {@link ResolvedJavaType}) can not be private or protected.
+ */
+ int getModifiers();
+
+ /**
+ * @see Modifier#isInterface(int)
+ */
+ default boolean isInterface() {
+ return Modifier.isInterface(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isSynchronized(int)
+ */
+ default boolean isSynchronized() {
+ return Modifier.isSynchronized(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isStatic(int)
+ */
+ default boolean isStatic() {
+ return Modifier.isStatic(getModifiers());
+ }
+
+ /**
+ * The setting of the final modifier bit for types is somewhat confusing, so don't export
+ * isFinal by default. Subclasses like {@link ResolvedJavaField} and {@link ResolvedJavaMethod}
+ * can export it as isFinal, but {@link ResolvedJavaType} can provide a more sensible equivalent
+ * like {@link ResolvedJavaType#isLeaf}.
+ *
+ * @see Modifier#isFinal(int)
+ */
+ default boolean isFinalFlagSet() {
+ return Modifier.isFinal(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isPublic(int)
+ */
+ default boolean isPublic() {
+ return Modifier.isPublic(getModifiers());
+ }
+
+ /**
+ * Determines if this element is neither {@linkplain #isPublic() public},
+ * {@linkplain #isProtected() protected} nor {@linkplain #isPrivate() private}.
+ */
+ default boolean isPackagePrivate() {
+ return ((PUBLIC | PROTECTED | PRIVATE) & getModifiers()) == 0;
+ }
+
+ /**
+ * @see Modifier#isPrivate(int)
+ */
+ default boolean isPrivate() {
+ return Modifier.isPrivate(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isProtected(int)
+ */
+ default boolean isProtected() {
+ return Modifier.isProtected(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isTransient(int)
+ */
+ default boolean isTransient() {
+ return Modifier.isTransient(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isStrict(int)
+ */
+ default boolean isStrict() {
+ return Modifier.isStrict(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isVolatile(int)
+ */
+ default boolean isVolatile() {
+ return Modifier.isVolatile(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isNative(int)
+ */
+ default boolean isNative() {
+ return Modifier.isNative(getModifiers());
+ }
+
+ /**
+ * @see Modifier#isAbstract(int)
+ */
+ default boolean isAbstract() {
+ return Modifier.isAbstract(getModifiers());
+ }
+
+ /**
+ * Checks that the method is concrete and not abstract.
+ *
+ * @return whether the method is a concrete method
+ */
+ default boolean isConcrete() {
+ return !isAbstract();
+ }
+
+ static int jvmClassModifiers() {
+ // no SUPER
+ return PUBLIC | FINAL | INTERFACE | ABSTRACT | ANNOTATION | ENUM | SYNTHETIC;
+ }
+
+ static int jvmMethodModifiers() {
+ return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC;
+ }
+
+ static int jvmFieldModifiers() {
+ return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/NullConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * The implementation type of the {@link JavaConstant#NULL_POINTER null constant}.
+ */
+final class NullConstant implements JavaConstant {
+
+ protected NullConstant() {
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return JavaKind.Object;
+ }
+
+ @Override
+ public boolean isNull() {
+ return true;
+ }
+
+ @Override
+ public boolean isDefaultForKind() {
+ return true;
+ }
+
+ @Override
+ public Object asBoxedPrimitive() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int asInt() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public boolean asBoolean() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public long asLong() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public float asFloat() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public double asDouble() {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public String toString() {
+ return JavaConstant.toString(this);
+ }
+
+ @Override
+ public String toValueString() {
+ return "null";
+ }
+
+ @Override
+ public int hashCode() {
+ return 13;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof NullConstant;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a platform-specific low-level type for values.
+ */
+public interface PlatformKind {
+
+ String name();
+
+ JavaConstant getDefaultValue();
+
+ public interface Key {
+
+ }
+
+ public class EnumKey<E extends Enum<E>> implements Key {
+ private final Enum<E> e;
+
+ public EnumKey(Enum<E> e) {
+ this.e = e;
+ }
+
+ @Override
+ public int hashCode() {
+ return e.ordinal() ^ e.name().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof EnumKey) {
+ EnumKey<?> that = (EnumKey<?>) obj;
+ return this.e == that.e;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Gets a value associated with this object that can be used as a stable key in a map. The
+ * {@link Object#hashCode()} implementation of the returned value should be stable between VM
+ * executions.
+ */
+ Key getKey();
+
+ /**
+ * Get the size in bytes of this {@link PlatformKind}.
+ */
+ int getSizeInBytes();
+
+ /**
+ * Returns how many primitive values fit in this {@link PlatformKind}. For scalar types this is
+ * one, for SIMD types it may be higher.
+ */
+ int getVectorLength();
+
+ /**
+ * Gets a single type char that identifies this type for use in debug output.
+ */
+ char getTypeChar();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.nio.*;
+
+/**
+ * Represents a primitive constant value, such as an integer or floating point number, within the
+ * compiler and across the compiler/runtime interface.
+ */
+public class PrimitiveConstant implements JavaConstant, SerializableConstant {
+
+ private final JavaKind kind;
+
+ /**
+ * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
+ * this value is the result of {@link Float#floatToRawIntBits(float)} and
+ * {@link Double#doubleToRawLongBits(double)} respectively.
+ */
+ private final long primitive;
+
+ protected PrimitiveConstant(JavaKind kind, long primitive) {
+ this.primitive = primitive;
+ this.kind = kind;
+
+ assert kind.isPrimitive() || kind == JavaKind.Illegal;
+ }
+
+ @Override
+ public JavaKind getJavaKind() {
+ return kind;
+ }
+
+ @Override
+ public boolean isNull() {
+ return false;
+ }
+
+ @Override
+ public boolean isDefaultForKind() {
+ return primitive == 0;
+ }
+
+ @Override
+ public boolean asBoolean() {
+ assert getJavaKind() == JavaKind.Boolean;
+ return primitive != 0L;
+ }
+
+ @Override
+ public int asInt() {
+ assert getJavaKind().getStackKind() == JavaKind.Int : getJavaKind().getStackKind();
+ return (int) primitive;
+ }
+
+ @Override
+ public long asLong() {
+ assert getJavaKind().isNumericInteger();
+ return primitive;
+ }
+
+ @Override
+ public float asFloat() {
+ assert getJavaKind() == JavaKind.Float;
+ return Float.intBitsToFloat((int) primitive);
+ }
+
+ @Override
+ public double asDouble() {
+ assert getJavaKind() == JavaKind.Double;
+ return Double.longBitsToDouble(primitive);
+ }
+
+ @Override
+ public Object asBoxedPrimitive() {
+ switch (getJavaKind()) {
+ case Byte:
+ return Byte.valueOf((byte) primitive);
+ case Boolean:
+ return Boolean.valueOf(asBoolean());
+ case Short:
+ return Short.valueOf((short) primitive);
+ case Char:
+ return Character.valueOf((char) primitive);
+ case Int:
+ return Integer.valueOf(asInt());
+ case Long:
+ return Long.valueOf(asLong());
+ case Float:
+ return Float.valueOf(asFloat());
+ case Double:
+ return Double.valueOf(asDouble());
+ default:
+ throw new IllegalArgumentException("unexpected kind " + getJavaKind());
+ }
+ }
+
+ @Override
+ public int getSerializedSize() {
+ return getJavaKind().getByteCount();
+ }
+
+ @Override
+ public void serialize(ByteBuffer buffer) {
+ switch (getJavaKind()) {
+ case Byte:
+ case Boolean:
+ buffer.put((byte) primitive);
+ break;
+ case Short:
+ buffer.putShort((short) primitive);
+ break;
+ case Char:
+ buffer.putChar((char) primitive);
+ break;
+ case Int:
+ buffer.putInt(asInt());
+ break;
+ case Long:
+ buffer.putLong(asLong());
+ break;
+ case Float:
+ buffer.putFloat(asFloat());
+ break;
+ case Double:
+ buffer.putDouble(asDouble());
+ break;
+ default:
+ throw new IllegalArgumentException("unexpected kind " + getJavaKind());
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (primitive ^ (primitive >>> 32)) * (getJavaKind().ordinal() + 31);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PrimitiveConstant)) {
+ return false;
+ }
+ PrimitiveConstant other = (PrimitiveConstant) o;
+ return this.kind.equals(other.kind) && this.primitive == other.primitive;
+ }
+
+ @Override
+ public String toString() {
+ if (getJavaKind() == JavaKind.Illegal) {
+ return "illegal";
+ } else {
+ return getJavaKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Provides access to the profiling information of one specific method. Every accessor method
+ * returns the information that is available at the time of invocation. If a method is invoked
+ * multiple times, it may return significantly different results for every invocation as the
+ * profiling information may be changed by other Java threads at any time.
+ */
+public interface ProfilingInfo {
+
+ /**
+ * Returns the length of the bytecodes associated with this profile.
+ */
+ int getCodeSize();
+
+ /**
+ * Returns an estimate of how often the branch at the given byte code was taken.
+ *
+ * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if
+ * this information is not available.
+ */
+ double getBranchTakenProbability(int bci);
+
+ /**
+ * Returns an estimate of how often the switch cases are taken at the given BCI. The default
+ * case is stored as the last entry.
+ *
+ * @return A double value that contains the estimated probabilities, with 0.0 meaning never and
+ * 1.0 meaning always, or -1 if this information is not available.
+ */
+ double[] getSwitchProbabilities(int bci);
+
+ /**
+ * Returns the TypeProfile for the given BCI.
+ *
+ * @return Returns a JavaTypeProfile object, or null if not available.
+ */
+ JavaTypeProfile getTypeProfile(int bci);
+
+ /**
+ * Returns the MethodProfile for the given BCI.
+ *
+ * @return Returns a JavaMethodProfile object, or null if not available.
+ */
+ JavaMethodProfile getMethodProfile(int bci);
+
+ /**
+ * Returns information if the given BCI did ever throw an exception.
+ *
+ * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once,
+ * {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN}
+ * if this information was not recorded.
+ */
+ TriState getExceptionSeen(int bci);
+
+ /**
+ * Returns information if null was ever seen for the given BCI. This information is collected
+ * for the aastore, checkcast and instanceof bytecodes.
+ *
+ * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if
+ * null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded.
+ */
+ TriState getNullSeen(int bci);
+
+ /**
+ * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts
+ * to each other, as the returned value highly depends on the time of invocation.
+ *
+ * @return the estimated execution count or -1 if not available.
+ */
+ int getExecutionCount(int bci);
+
+ /**
+ * Returns how frequently a method was deoptimized for the given deoptimization reason. This
+ * only indicates how often the method did fall back to the interpreter for the execution and
+ * does not indicate how often it was recompiled.
+ *
+ * @param reason the reason for which the number of deoptimizations should be queried
+ * @return the number of times the compiled method deoptimized for the given reason.
+ */
+ int getDeoptimizationCount(DeoptimizationReason reason);
+
+ /**
+ * Records the size of the compiler intermediate representation (IR) associated with this
+ * method.
+ *
+ * @param irType the IR type for which the size is being recorded
+ * @param irSize the IR size to be recorded. The unit depends on the IR.
+ * @return whether recording this information for {@code irType} is supported
+ */
+ boolean setCompilerIRSize(Class<?> irType, int irSize);
+
+ /**
+ * Gets the size of the compiler intermediate representation (IR) associated with this method
+ * last recorded by {@link #setCompilerIRSize(Class, int)}.
+ *
+ * @param irType the IR type for which the size is being requested
+ * @return the requested IR size or -1 if it is unavailable for {@code irType}
+ */
+ int getCompilerIRSize(Class<?> irType);
+
+ /**
+ * Returns true if the profiling information can be assumed as sufficiently accurate.
+ *
+ * @return true if the profiling information was recorded often enough mature enough, false
+ * otherwise.
+ */
+ boolean isMature();
+
+ /**
+ * Force data to be treated as mature if possible.
+ */
+ void setMature();
+
+ /**
+ * Formats this profiling information to a string.
+ *
+ * @param method an optional method that augments the profile string returned
+ * @param sep the separator to use for each separate profile record
+ */
+ default String toString(ResolvedJavaMethod method, String sep) {
+ StringBuilder buf = new StringBuilder(100);
+ if (method != null) {
+ buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep));
+ }
+ for (int i = 0; i < getCodeSize(); i++) {
+ if (getExecutionCount(i) != -1) {
+ buf.append(String.format("executionCount@%d: %d%s", i, getExecutionCount(i), sep));
+ }
+
+ if (getBranchTakenProbability(i) != -1) {
+ buf.append(String.format("branchProbability@%d: %.6f%s", i, getBranchTakenProbability(i), sep));
+ }
+
+ double[] switchProbabilities = getSwitchProbabilities(i);
+ if (switchProbabilities != null) {
+ buf.append(String.format("switchProbabilities@%d:", i));
+ for (int j = 0; j < switchProbabilities.length; j++) {
+ buf.append(String.format(" %.6f", switchProbabilities[j]));
+ }
+ buf.append(sep);
+ }
+
+ if (getExceptionSeen(i) != TriState.UNKNOWN) {
+ buf.append(String.format("exceptionSeen@%d: %s%s", i, getExceptionSeen(i).name(), sep));
+ }
+
+ if (getNullSeen(i) != TriState.UNKNOWN) {
+ buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep));
+ }
+
+ JavaTypeProfile typeProfile = getTypeProfile(i);
+ MetaUtil.appendProfile(buf, typeProfile, i, "types", sep);
+
+ JavaMethodProfile methodProfile = getMethodProfile(i);
+ MetaUtil.appendProfile(buf, methodProfile, i, "methods", sep);
+ }
+
+ boolean firstDeoptReason = true;
+ for (DeoptimizationReason reason : DeoptimizationReason.values()) {
+ int count = getDeoptimizationCount(reason);
+ if (count > 0) {
+ if (firstDeoptReason) {
+ buf.append("deoptimization history").append(sep);
+ firstDeoptReason = false;
+ }
+ buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
+ }
+ }
+ if (buf.length() == 0) {
+ return "";
+ }
+ String s = buf.toString();
+ return s.substring(0, s.length() - sep.length());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/RawConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+public class RawConstant extends PrimitiveConstant {
+
+ public RawConstant(long rawValue) {
+ super(JavaKind.Int, rawValue);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+/**
+ * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved
+ * through {@link ConstantPool constant pools}.
+ */
+public interface ResolvedJavaField extends JavaField, ModifiersProvider {
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM
+ * specification will be included in the returned mask.
+ */
+ int getModifiers();
+
+ default boolean isFinal() {
+ return ModifiersProvider.super.isFinalFlagSet();
+ }
+
+ /**
+ * Determines if this field was injected by the VM. Such a field, for example, is not derived
+ * from a class file.
+ */
+ boolean isInternal();
+
+ /**
+ * Determines if this field is a synthetic field as defined by the Java Language Specification.
+ */
+ boolean isSynthetic();
+
+ /**
+ * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
+ * this field.
+ */
+ ResolvedJavaType getDeclaringClass();
+
+ /**
+ * Returns all annotations of this field. If no annotations are present, an array of length 0 is
+ * returned.
+ */
+ Annotation[] getAnnotations();
+
+ /**
+ * Returns the annotation for the specified type of this field, if such an annotation is
+ * present.
+ *
+ * @param annotationClass the Class object corresponding to the annotation type
+ * @return this element's annotation for the specified annotation type if present on this field,
+ * else {@code null}
+ */
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+
+ /**
+ * Returns an object representing the unique location identity of this resolved Java field.
+ *
+ * @return the location identity of the field
+ */
+ LocationIdentity getLocationIdentity();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.annotation.*;
+import java.lang.invoke.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Represents a resolved Java method. Methods, like fields and types, are resolved through
+ * {@link ConstantPool constant pools}.
+ */
+public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider {
+
+ /**
+ * Returns the bytecode of this method, if the method has code. The returned byte array does not
+ * contain breakpoints or non-Java bytecodes. This may return null if the
+ * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
+ *
+ * The contained constant pool indices may not be the ones found in the original class file but
+ * they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
+ *
+ * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
+ * code is not ready.
+ */
+ byte[] getCode();
+
+ /**
+ * Returns the size of the bytecode of this method, if the method has code. This is equivalent
+ * to {@link #getCode()}. {@code length} if the method has code.
+ *
+ * @return the size of the bytecode in bytes, or 0 if no bytecode is available
+ */
+ int getCodeSize();
+
+ /**
+ * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
+ * this method.
+ */
+ ResolvedJavaType getDeclaringClass();
+
+ /**
+ * Returns the maximum number of locals used in this method's bytecodes.
+ */
+ int getMaxLocals();
+
+ /**
+ * Returns the maximum number of stack slots used in this method's bytecodes.
+ */
+ int getMaxStackSize();
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM
+ * specification will be included in the returned mask.
+ */
+ int getModifiers();
+
+ default boolean isFinal() {
+ return ModifiersProvider.super.isFinalFlagSet();
+ }
+
+ /**
+ * Determines if this method is a synthetic method as defined by the Java Language
+ * Specification.
+ */
+ default boolean isSynthetic() {
+ return (SYNTHETIC & getModifiers()) == SYNTHETIC;
+ }
+
+ /**
+ * Checks that the method is a <a
+ * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">varargs</a>
+ * method.
+ *
+ * @return whether the method is a varargs method
+ */
+ default boolean isVarArgs() {
+ return (VARARGS & getModifiers()) == VARARGS;
+ }
+
+ /**
+ * Checks that the method is a <a
+ * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">bridge</a>
+ * method.
+ *
+ * @return whether the method is a bridge method
+ */
+ default boolean isBridge() {
+ return (BRIDGE & getModifiers()) == BRIDGE;
+ }
+
+ /**
+ * Returns {@code true} if this method is a default method; returns {@code false} otherwise.
+ *
+ * A default method is a public non-abstract instance method, that is, a non-static method with
+ * a body, declared in an interface type.
+ *
+ * @return true if and only if this method is a default method as defined by the Java Language
+ * Specification.
+ */
+ boolean isDefault();
+
+ /**
+ * Checks whether this method is a class initializer.
+ *
+ * @return {@code true} if the method is a class initializer
+ */
+ boolean isClassInitializer();
+
+ /**
+ * Checks whether this method is a constructor.
+ *
+ * @return {@code true} if the method is a constructor
+ */
+ boolean isConstructor();
+
+ /**
+ * Checks whether this method can be statically bound (usually, that means it is final or
+ * private or static, but not abstract, or the declaring class is final).
+ *
+ * @return {@code true} if this method can be statically bound
+ */
+ boolean canBeStaticallyBound();
+
+ /**
+ * Returns the list of exception handlers for this method.
+ */
+ ExceptionHandler[] getExceptionHandlers();
+
+ /**
+ * Returns a stack trace element for this method and a given bytecode index.
+ */
+ StackTraceElement asStackTraceElement(int bci);
+
+ /**
+ * Returns an object that provides access to the profiling information recorded for this method.
+ */
+ default ProfilingInfo getProfilingInfo() {
+ return getProfilingInfo(true, true);
+ }
+
+ /**
+ * Returns an object that provides access to the profiling information recorded for this method.
+ *
+ * @param includeNormal if true,
+ * {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
+ * deoptimization counts} will include deoptimization that happened during execution
+ * of standard non-osr methods.
+ * @param includeOSR if true,
+ * {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
+ * deoptimization counts} will include deoptimization that happened during execution
+ * of on-stack-replacement methods.
+ */
+ ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR);
+
+ /**
+ * Invalidates the profiling information and restarts profiling upon the next invocation.
+ */
+ void reprofile();
+
+ /**
+ * Returns the constant pool of this method.
+ */
+ ConstantPool getConstantPool();
+
+ /**
+ * Returns all annotations of this method. If no annotations are present, an array of length 0
+ * is returned.
+ */
+ Annotation[] getAnnotations();
+
+ /**
+ * Returns the annotation for the specified type of this method, if such an annotation is
+ * present.
+ *
+ * @param annotationClass the Class object corresponding to the annotation type
+ * @return this element's annotation for the specified annotation type if present on this
+ * method, else {@code null}
+ */
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+
+ /**
+ * Returns an array of arrays that represent the annotations on the formal parameters, in
+ * declaration order, of this method.
+ *
+ * @see Method#getParameterAnnotations()
+ */
+ Annotation[][] getParameterAnnotations();
+
+ /**
+ * Returns an array of {@link Type} objects that represent the formal parameter types, in
+ * declaration order, of this method.
+ *
+ * @see Method#getGenericParameterTypes()
+ */
+ Type[] getGenericParameterTypes();
+
+ /**
+ * Returns {@code true} if this method is not excluded from inlining and has associated Java
+ * bytecodes (@see {@link ResolvedJavaMethod#hasBytecodes()}).
+ */
+ boolean canBeInlined();
+
+ /**
+ * Returns {@code true} if the inlining of this method should be forced.
+ */
+ boolean shouldBeInlined();
+
+ /**
+ * Returns the LineNumberTable of this method or null if this method does not have a line
+ * numbers table.
+ */
+ LineNumberTable getLineNumberTable();
+
+ /**
+ * Returns the local variable table of this method or null if this method does not have a local
+ * variable table.
+ */
+ LocalVariableTable getLocalVariableTable();
+
+ /**
+ * Invokes the underlying method represented by this object, on the specified object with the
+ * specified parameters. This method is similar to a reflective method invocation by
+ * {@link Method#invoke}.
+ *
+ * @param receiver The receiver for the invocation, or {@code null} if it is a static method.
+ * @param arguments The arguments for the invocation.
+ * @return The value returned by the method invocation, or {@code null} if the return type is
+ * {@code void}.
+ */
+ JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments);
+
+ /**
+ * Gets the encoding of (that is, a constant representing the value of) this method.
+ *
+ * @return a constant representing a reference to this method
+ */
+ Constant getEncoding();
+
+ /**
+ * Checks if this method is present in the virtual table for subtypes of the specified
+ * {@linkplain ResolvedJavaType type}.
+ *
+ * @return true is this method is present in the virtual table for subtypes of this type.
+ */
+ boolean isInVirtualMethodTable(ResolvedJavaType resolved);
+
+ /**
+ * Gets the annotation of a particular type for a formal parameter of this method.
+ *
+ * @param annotationClass the Class object corresponding to the annotation type
+ * @param parameterIndex the index of a formal parameter of {@code method}
+ * @return the annotation of type {@code annotationClass} for the formal parameter present, else
+ * null
+ * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal
+ * parameter
+ */
+ default <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex) {
+ if (parameterIndex >= 0) {
+ Annotation[][] parameterAnnotations = getParameterAnnotations();
+ for (Annotation a : parameterAnnotations[parameterIndex]) {
+ if (a.annotationType() == annotationClass) {
+ return annotationClass.cast(a);
+ }
+ }
+ }
+ return null;
+ }
+
+ default JavaType[] toParameterTypes() {
+ JavaType receiver = isStatic() || isConstructor() ? null : getDeclaringClass();
+ return getSignature().toParameterTypes(receiver);
+ }
+
+ /**
+ * Gets the annotations of a particular type for the formal parameters of this method.
+ *
+ * @param annotationClass the Class object corresponding to the annotation type
+ * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
+ * present
+ */
+ @SuppressWarnings("unchecked")
+ default <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass) {
+ Annotation[][] parameterAnnotations = getParameterAnnotations();
+ T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
+ for (int i = 0; i < parameterAnnotations.length; i++) {
+ for (Annotation a : parameterAnnotations[i]) {
+ if (a.annotationType() == annotationClass) {
+ result[i] = annotationClass.cast(a);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks whether the method has bytecodes associated with it. Methods without bytecodes are
+ * either abstract or native methods.
+ *
+ * @return whether the definition of this method is Java bytecodes
+ */
+ default boolean hasBytecodes() {
+ return isConcrete() && !isNative();
+ }
+
+ /**
+ * Checks whether the method has a receiver parameter - i.e., whether it is not static.
+ *
+ * @return whether the method has a receiver parameter
+ */
+ default boolean hasReceiver() {
+ return !isStatic();
+ }
+
+ /**
+ * Determines if this method is {@link java.lang.Object#Object()}.
+ */
+ default boolean isJavaLangObjectInit() {
+ return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
+ }
+
+ SpeculationLog getSpeculationLog();
+
+ /**
+ * Determines if the method identified by its holder and name is a <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">signature
+ * polymorphic</a> method.
+ */
+ static boolean isSignaturePolymorphic(JavaType holder, String name, MetaAccessProvider metaAccess) {
+ if (!holder.getName().equals("Ljava/lang/invoke/MethodHandle;")) {
+ return false;
+ }
+ ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
+ Signature signature = metaAccess.parseMethodDescriptor("([Ljava/lang/Object;)Ljava/lang/Object;");
+ ResolvedJavaMethod method = methodHandleType.findMethod(name, signature);
+ if (method == null) {
+ return false;
+ }
+ return method.isNative() && method.isVarArgs();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.annotation.*;
+import java.net.*;
+
+import jdk.vm.ci.meta.Assumptions.*;
+
+/**
+ * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays
+ * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools}
+ * .
+ */
+public interface ResolvedJavaType extends JavaType, ModifiersProvider {
+ /**
+ * Gets the runtime representation of the Java class object of this type.
+ */
+ JavaConstant getJavaClass();
+
+ /**
+ * Gets the runtime representation of the "hub" of this type--that is, the closest part of the
+ * type representation which is typically stored in the object header.
+ */
+ Constant getObjectHub();
+
+ /**
+ * Checks whether this type has a finalizer method.
+ *
+ * @return {@code true} if this class has a finalizer
+ */
+ boolean hasFinalizer();
+
+ /**
+ * Checks whether this type has any finalizable subclasses so far. Any decisions based on this
+ * information require the registration of a dependency, since this information may change.
+ *
+ * @return {@code true} if this class has any subclasses with finalizers
+ */
+ AssumptionResult<Boolean> hasFinalizableSubclass();
+
+ /**
+ * Checks whether this type is an interface.
+ *
+ * @return {@code true} if this type is an interface
+ */
+ boolean isInterface();
+
+ /**
+ * Checks whether this type is an instance class.
+ *
+ * @return {@code true} if this type is an instance class
+ */
+ boolean isInstanceClass();
+
+ /**
+ * Checks whether this type is an array class.
+ *
+ * @return {@code true} if this type is an array class
+ */
+ boolean isArray();
+
+ /**
+ * Checks whether this type is primitive.
+ *
+ * @return {@code true} if this type is primitive
+ */
+ boolean isPrimitive();
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Only the flags specified in the JVM specification will be included in the returned mask. This
+ * method is identical to {@link Class#getModifiers()} in terms of the value return for this
+ * type.
+ */
+ int getModifiers();
+
+ /*
+ * The setting of the final bit for types is a bit confusing since arrays are marked as final.
+ * This method provides a semantically equivalent test that appropriate for types.
+ */
+ default boolean isLeaf() {
+ return getElementalType().isFinalFlagSet();
+ }
+
+ /**
+ * Checks whether this type is initialized. If a type is initialized it implies that it was
+ * {@link #isLinked() linked} and that the static initializer has run.
+ *
+ * @return {@code true} if this type is initialized
+ */
+ boolean isInitialized();
+
+ /**
+ * Initializes this type.
+ */
+ void initialize();
+
+ /**
+ * Checks whether this type is linked and verified. When a type is linked the static initializer
+ * has not necessarily run. An {@link #isInitialized() initialized} type is always linked.
+ *
+ * @return {@code true} if this type is linked
+ */
+ boolean isLinked();
+
+ /**
+ * Determines if this type is either the same as, or is a superclass or superinterface of, the
+ * type represented by the specified parameter. This method is identical to
+ * {@link Class#isAssignableFrom(Class)} in terms of the value return for this type.
+ */
+ boolean isAssignableFrom(ResolvedJavaType other);
+
+ /**
+ * Returns true if this type is exactly the type {@link java.lang.Object}.
+ */
+ default boolean isJavaLangObject() {
+ // Removed assertion due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=434442
+ return getSuperclass() == null && !isInterface() && getJavaKind() == JavaKind.Object;
+ }
+
+ /**
+ * Checks whether the specified object is an instance of this type.
+ *
+ * @param obj the object to test
+ * @return {@code true} if the object is an instance of this type
+ */
+ boolean isInstance(JavaConstant obj);
+
+ /**
+ * Returns this type if it is an exact type otherwise returns null. This type is exact if it is
+ * void, primitive, final, or an array of a final or primitive type.
+ *
+ * @return this type if it is exact; {@code null} otherwise
+ */
+ ResolvedJavaType asExactType();
+
+ /**
+ * Gets the super class of this type. If this type represents either the {@code Object} class,
+ * an interface, a primitive type, or void, then null is returned. If this object represents an
+ * array class then the type object representing the {@code Object} class is returned.
+ */
+ ResolvedJavaType getSuperclass();
+
+ /**
+ * Gets the interfaces implemented or extended by this type. This method is analogous to
+ * {@link Class#getInterfaces()} and as such, only returns the interfaces directly implemented
+ * or extended by this type.
+ */
+ ResolvedJavaType[] getInterfaces();
+
+ /**
+ * Gets the single implementor of this type. Calling this method on a non-interface type causes
+ * an exception.
+ * <p>
+ * If the compiler uses the result of this method for its compilation, the usage must be guarded
+ * because the verifier can not guarantee that the assigned type really implements this
+ * interface. Additionally, class loading can invalidate the result of this method.
+ *
+ * @return {@code null} if there is no implementor, the implementor if there is only one, or
+ * {@code this} if there are more than one.
+ */
+ ResolvedJavaType getSingleImplementor();
+
+ /**
+ * Walks the class hierarchy upwards and returns the least common class that is a superclass of
+ * both the current and the given type.
+ *
+ * @return the least common type that is a super type of both the current and the given type, or
+ * {@code null} if primitive types are involved.
+ */
+ ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType);
+
+ /**
+ * Attempts to get a leaf concrete subclass of this type.
+ * <p>
+ * For an {@linkplain #isArray() array} type A, the leaf concrete subclass is A if the
+ * {@linkplain #getElementalType() elemental} type of A is final (which includes primitive
+ * types). Otherwise {@code null} is returned for A.
+ * <p>
+ * For a non-array type T, the result is the leaf concrete type in the current hierarchy of T.
+ * <p>
+ * A runtime may decide not to manage or walk a large hierarchy and so the result is
+ * conservative. That is, a non-null result is guaranteed to be the leaf concrete class in T's
+ * hierarchy <b>at the current point in time</b> but a null result does not necessarily imply
+ * that there is no leaf concrete class in T's hierarchy.
+ * <p>
+ * If the compiler uses the result of this method for its compilation, it must register the
+ * {@link AssumptionResult} in its {@link Assumptions} because dynamic class loading can
+ * invalidate the result of this method.
+ *
+ * @return an {@link AssumptionResult} containing the leaf concrete subclass for this type as
+ * described above
+ */
+ AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
+
+ ResolvedJavaType getComponentType();
+
+ default ResolvedJavaType getElementalType() {
+ ResolvedJavaType t = this;
+ while (t.isArray()) {
+ t = t.getComponentType();
+ }
+ return t;
+ }
+
+ ResolvedJavaType getArrayClass();
+
+ /**
+ * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
+ * This resolution process only searches "up" the class hierarchy of this type.
+ *
+ * @param method the method to select the implementation of
+ * @param callerType the caller or context type used to perform access checks
+ * @return the link-time resolved method (might be abstract) or {@code null} if it can not be
+ * linked
+ */
+ ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType);
+
+ /**
+ * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
+ * This resolution process only searches "up" the class hierarchy of this type. A broader search
+ * that also walks "down" the hierarchy is implemented by
+ * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}.
+ *
+ * @param method the method to select the implementation of
+ * @param callerType the caller or context type used to perform access checks
+ * @return the concrete method that would be selected at runtime, or {@code null} if there is no
+ * concrete implementation of {@code method} in this type or any of its superclasses
+ */
+ ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType);
+
+ /**
+ * Given a {@link ResolvedJavaMethod} A, returns a concrete {@link ResolvedJavaMethod} B that is
+ * the only possible unique target for a virtual call on A(). Returns {@code null} if either no
+ * such concrete method or more than one such method exists. Returns the method A if A is a
+ * concrete method that is not overridden.
+ * <p>
+ * If the compiler uses the result of this method for its compilation, it must register an
+ * assumption because dynamic class loading can invalidate the result of this method.
+ *
+ * @param method the method A for which a unique concrete target is searched
+ * @return the unique concrete target or {@code null} if no such target exists or assumptions
+ * are not supported by this runtime
+ */
+ AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
+
+ /**
+ * Returns the instance fields of this class, including
+ * {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
+ * for array and primitive types. The order of fields returned by this method is stable. That
+ * is, for a single JVM execution the same order is returned each time this method is called. It
+ * is also the "natural" order, which means that the JVM would expect the fields in this order
+ * if no specific order is given.
+ *
+ * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
+ * type are included in the result
+ * @return an array of instance fields
+ */
+ ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses);
+
+ /**
+ * Returns the static fields of this class, including
+ * {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
+ * for array and primitive types. The order of fields returned by this method is stable. That
+ * is, for a single JVM execution the same order is returned each time this method is called.
+ */
+ ResolvedJavaField[] getStaticFields();
+
+ /**
+ * Returns all annotations of this class. If no annotations are present, an array of length 0 is
+ * returned.
+ */
+ Annotation[] getAnnotations();
+
+ /**
+ * Returns the annotation for the specified type of this class, if such an annotation is
+ * present.
+ *
+ * @param annotationClass the Class object corresponding to the annotation type
+ * @return this element's annotation for the specified annotation type if present on this class,
+ * else {@code null}
+ */
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+
+ /**
+ * Returns the instance field of this class (or one of its super classes) at the given offset,
+ * or {@code null} if there is no such field.
+ *
+ * @param offset the offset of the field to look for
+ * @return the field with the given offset, or {@code null} if there is no such field.
+ */
+ ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind);
+
+ /**
+ * Returns name of source file of this type.
+ */
+ String getSourceFileName();
+
+ /**
+ * Returns the class file path - if available - of this type, or {@code null}.
+ */
+ URL getClassFilePath();
+
+ /**
+ * Returns {@code true} if the type is a local type.
+ */
+ boolean isLocal();
+
+ /**
+ * Returns {@code true} if the type is a member type.
+ */
+ boolean isMember();
+
+ /**
+ * Returns the enclosing type of this type, if it exists, or {@code null}.
+ */
+ ResolvedJavaType getEnclosingType();
+
+ /**
+ * Returns an array reflecting all the constructors declared by this type. This method is
+ * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
+ */
+ ResolvedJavaMethod[] getDeclaredConstructors();
+
+ /**
+ * Returns an array reflecting all the methods declared by this type. This method is similar to
+ * {@link Class#getDeclaredMethods()} in terms of returned methods.
+ */
+ ResolvedJavaMethod[] getDeclaredMethods();
+
+ /**
+ * Returns the {@code <clinit>} method for this class if there is one.
+ */
+ ResolvedJavaMethod getClassInitializer();
+
+ /**
+ * Returns true if this type represents an interface and it should be trusted even in places
+ * where the JVM verifier would not give any guarantees other than {@link Object}.
+ */
+ boolean isTrustedInterfaceType();
+
+ default ResolvedJavaMethod findMethod(String name, Signature signature) {
+ for (ResolvedJavaMethod method : getDeclaredMethods()) {
+ if (method.getName().equals(name) && method.getSignature().equals(signature)) {
+ return method;
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.nio.*;
+
+/**
+ * Represents a compile-time constant that can be converted to a byte array.
+ */
+public interface SerializableConstant extends Constant {
+
+ /**
+ * Return the size in bytes of the serialized representation of this constant.
+ */
+ int getSerializedSize();
+
+ /**
+ * Serialize the constant into the ByteBuffer. There must be at least
+ * {@link #getSerializedSize()} bytes available capacity in the buffer.
+ */
+ void serialize(ByteBuffer buffer);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Signature.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a method signature provided by the runtime.
+ *
+ * @see <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">Method
+ * Descriptors</a>
+ */
+public interface Signature {
+
+ /**
+ * Returns the number of parameters in this signature, adding 1 for a receiver if requested.
+ *
+ * @param receiver true if 1 is to be added to the result for a receiver
+ * @return the number of parameters; + 1 iff {@code receiver == true}
+ */
+ int getParameterCount(boolean receiver);
+
+ /**
+ * Gets the parameter type at the specified position.
+ *
+ * @param index the index into the parameters, with {@code 0} indicating the first parameter
+ * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+ * for resolving the type. If {@code null}, then the type returned is either
+ * unresolved or a resolved type whose resolution is context free (e.g., a primitive
+ * type or a type in a java.* package).
+ * @return the {@code index}'th parameter type
+ * @throws LinkageError if {@code accessingClass != null} and resolution fails
+ *
+ */
+ JavaType getParameterType(int index, ResolvedJavaType accessingClass);
+
+ /**
+ * Gets the parameter kind at the specified position. This is the same as calling
+ * {@link #getParameterType}. {@link JavaType#getJavaKind getJavaKind}.
+ *
+ * @param index the index into the parameters, with {@code 0} indicating the first parameter
+ * @return the kind of the parameter at the specified position
+ */
+ default JavaKind getParameterKind(int index) {
+ return getParameterType(index, null).getJavaKind();
+ }
+
+ /**
+ * Gets the return type of this signature.
+ *
+ * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+ * for resolving the type. If {@code null}, then the type returned is either
+ * unresolved or a resolved type whose resolution is context free (e.g., a primitive
+ * type or a type in a java.* package).
+ * @return the return type
+ * @throws LinkageError if {@code accessingClass != null} and resolution fails
+ */
+ JavaType getReturnType(ResolvedJavaType accessingClass);
+
+ /**
+ * Gets the return kind of this signature. This is the same as calling {@link #getReturnType}.
+ * {@link JavaType#getJavaKind getJavaKind}.
+ */
+ default JavaKind getReturnKind() {
+ return getReturnType(null).getJavaKind();
+ }
+
+ /**
+ * Gets the <a
+ * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+ * descriptor</a> corresponding to this signature. For example:
+ *
+ * <pre>
+ * (ILjava/lang/String;D)V
+ * </pre>
+ *
+ * @return the signature as a string
+ */
+ default String toMethodDescriptor() {
+ StringBuilder sb = new StringBuilder("(");
+ for (int i = 0; i < getParameterCount(false); ++i) {
+ sb.append(getParameterType(i, null).getName());
+ }
+ sb.append(')').append(getReturnType(null).getName());
+ return sb.toString();
+ }
+
+ default JavaType[] toParameterTypes(JavaType receiverType) {
+ int args = getParameterCount(false);
+ JavaType[] result;
+ int i = 0;
+ if (receiverType != null) {
+ result = new JavaType[args + 1];
+ result[0] = receiverType;
+ i = 1;
+ } else {
+ result = new JavaType[args];
+ }
+ for (int j = 0; j < args; j++) {
+ result[i + j] = getParameterType(j, null);
+ }
+ return result;
+ }
+
+ default JavaKind[] toParameterKinds(boolean receiver) {
+ int args = getParameterCount(false);
+ JavaKind[] result;
+ int i = 0;
+ if (receiver) {
+ result = new JavaKind[args + 1];
+ result[0] = JavaKind.Object;
+ i = 1;
+ } else {
+ result = new JavaKind[args];
+ }
+ for (int j = 0; j < args; j++) {
+ result[i + j] = getParameterKind(j);
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Manages a list of unique deoptimization reasons.
+ *
+ */
+public abstract class SpeculationLog {
+ private volatile Object lastFailed;
+ private volatile Collection<Object> speculations;
+ private Set<Object> failedSpeculations;
+
+ public synchronized void collectFailedSpeculations() {
+ if (lastFailed != null) {
+ if (failedSpeculations == null) {
+ failedSpeculations = new HashSet<>(2);
+ }
+ failedSpeculations.add(lastFailed);
+ lastFailed = null;
+ speculations = null;
+ }
+ }
+
+ public boolean maySpeculate(Object reason) {
+ if (failedSpeculations != null && failedSpeculations.contains(reason)) {
+ return false;
+ }
+ return true;
+ }
+
+ protected void addSpeculation(Object reason) {
+ assert maySpeculate(reason);
+ if (speculations == null) {
+ synchronized (this) {
+ if (speculations == null) {
+ speculations = new ConcurrentLinkedQueue<>();
+ }
+ }
+ }
+ speculations.add(reason);
+ }
+
+ public abstract JavaConstant speculate(Object reason);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/TriState.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a logic value that can be either {@link #TRUE}, {@link #FALSE}, or {@link #UNKNOWN}.
+ */
+public enum TriState {
+ TRUE,
+ FALSE,
+ UNKNOWN;
+
+ public static TriState get(boolean value) {
+ return value ? TRUE : FALSE;
+ }
+
+ /**
+ * This is optimistic about {@link #UNKNOWN} (it prefers known values over {@link #UNKNOWN}) and
+ * pesimistic about known (it perfers {@link #TRUE} over {@link #FALSE}).
+ */
+ public static TriState merge(TriState a, TriState b) {
+ if (a == TRUE || b == TRUE) {
+ return TRUE;
+ }
+ if (a == FALSE || b == FALSE) {
+ return FALSE;
+ }
+ assert a == UNKNOWN && b == UNKNOWN;
+ return UNKNOWN;
+ }
+
+ public boolean isTrue() {
+ return this == TRUE;
+ }
+
+ public boolean isFalse() {
+ return this == FALSE;
+ }
+
+ public boolean isUnknown() {
+ return this == UNKNOWN;
+ }
+
+ public boolean isKnown() {
+ return this != UNKNOWN;
+ }
+
+ public boolean toBoolean() {
+ if (isTrue()) {
+ return true;
+ } else if (isFalse()) {
+ return false;
+ } else {
+ throw new IllegalStateException("Cannot convert to boolean, TriState is in an unknown state");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/TrustedInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Interfaces extending this interface should be trusted by the compiler. See
+ * {@link ResolvedJavaType#isTrustedInterfaceType()}.
+ *
+ */
+public interface TrustedInterface {
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package jdk.vm.ci.meta;
+
+public interface VMConstant extends Constant {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Value.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Abstract base class for values.
+ */
+public abstract class Value {
+
+ public static final Value[] NO_VALUES = new Value[0];
+
+ public static final AllocatableValue ILLEGAL = new IllegalValue();
+
+ private static final class IllegalValue extends AllocatableValue {
+ private IllegalValue() {
+ super(LIRKind.Illegal);
+ }
+
+ @Override
+ public String toString() {
+ return "-";
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // Due to de-serialization this object may exist multiple times. So we compare classes
+ // instead of the individual objects. (This anonymous class has always the same meaning)
+ return other instanceof IllegalValue;
+ }
+ }
+
+ private final LIRKind lirKind;
+
+ /**
+ * Initializes a new value of the specified kind.
+ *
+ * @param lirKind the kind
+ */
+ protected Value(LIRKind lirKind) {
+ this.lirKind = lirKind;
+ }
+
+ /**
+ * Returns a String representation of the kind, which should be the end of all
+ * {@link #toString()} implementation of subclasses.
+ */
+ protected final String getKindSuffix() {
+ return "|" + getPlatformKind().getTypeChar();
+ }
+
+ public final LIRKind getLIRKind() {
+ return lirKind;
+ }
+
+ /**
+ * Returns the platform specific kind used to store this value.
+ */
+ public final PlatformKind getPlatformKind() {
+ return lirKind.getPlatformKind();
+ }
+
+ @Override
+ public int hashCode() {
+ return 41 + lirKind.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Value) {
+ Value that = (Value) obj;
+ return lirKind.equals(that.lirKind);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if this value is identical to {@code other}.
+ *
+ * Warning: Use with caution! Usually equivalence {@link #equals(Object)} is sufficient and
+ * should be used.
+ */
+ public final boolean identityEquals(Value other) {
+ return this == other;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/package-info.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009, 2011, 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.
+ */
+
+/**
+ * Package that defines the interface between a runtime and a Java application that wants to access meta information. The runtime
+ * provides an implementation of the {@link jdk.vm.ci.meta.MetaAccessProvider} interface.
+ */
+package jdk.vm.ci.meta;
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/META-INF/services/javax.annotation.processing.Processor Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+jdk.vm.ci.options.processor.OptionProcessor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options.processor;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import jdk.vm.ci.options.*;
+
+import javax.tools.*;
+
+/**
+ * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
+ * implementation is generated for each top level class containing at least one such field. The name
+ * of the generated class for top level class {@code com.foo.Bar} is
+ * {@code com.foo.Bar_OptionDescriptors}.
+ */
+@SupportedAnnotationTypes({"jdk.vm.ci.options.Option"})
+public class OptionProcessor extends AbstractProcessor {
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ private final Set<Element> processed = new HashSet<>();
+
+ private void processElement(Element element, OptionsInfo info) {
+
+ if (!element.getModifiers().contains(Modifier.STATIC)) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+ return;
+ }
+
+ Option annotation = element.getAnnotation(Option.class);
+ assert annotation != null;
+ assert element instanceof VariableElement;
+ assert element.getKind() == ElementKind.FIELD;
+ VariableElement field = (VariableElement) element;
+ String fieldName = field.getSimpleName().toString();
+
+ Elements elements = processingEnv.getElementUtils();
+ Types types = processingEnv.getTypeUtils();
+
+ TypeMirror fieldType = field.asType();
+ if (fieldType.getKind() != TypeKind.DECLARED) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionValue.class.getName(), element);
+ return;
+ }
+ DeclaredType declaredFieldType = (DeclaredType) fieldType;
+
+ TypeMirror optionValueType = elements.getTypeElement(OptionValue.class.getName()).asType();
+ if (!types.isSubtype(fieldType, types.erasure(optionValueType))) {
+ String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionValueType);
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+ return;
+ }
+
+ if (!field.getModifiers().contains(Modifier.STATIC)) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+ return;
+ }
+
+ String help = annotation.help();
+ if (help.length() != 0) {
+ char firstChar = help.charAt(0);
+ if (!Character.isUpperCase(firstChar)) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Option help text must start with upper case letter", element);
+ return;
+ }
+ }
+
+ String optionName = annotation.name();
+ if (optionName.equals("")) {
+ optionName = fieldName;
+ }
+
+ DeclaredType declaredOptionValueType = declaredFieldType;
+ while (!types.isSameType(types.erasure(declaredOptionValueType), types.erasure(optionValueType))) {
+ List<? extends TypeMirror> directSupertypes = types.directSupertypes(declaredFieldType);
+ assert!directSupertypes.isEmpty();
+ declaredOptionValueType = (DeclaredType) directSupertypes.get(0);
+ }
+
+ assert!declaredOptionValueType.getTypeArguments().isEmpty();
+ String optionType = declaredOptionValueType.getTypeArguments().get(0).toString();
+ if (optionType.startsWith("java.lang.")) {
+ optionType = optionType.substring("java.lang.".length());
+ }
+
+ Element enclosing = element.getEnclosingElement();
+ String declaringClass = "";
+ String separator = "";
+ Set<Element> originatingElementsList = info.originatingElements;
+ originatingElementsList.add(field);
+ while (enclosing != null) {
+ if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
+ if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
+ String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing);
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+ return;
+ }
+ originatingElementsList.add(enclosing);
+ declaringClass = enclosing.getSimpleName() + separator + declaringClass;
+ separator = ".";
+ } else {
+ assert enclosing.getKind() == ElementKind.PACKAGE;
+ }
+ enclosing = enclosing.getEnclosingElement();
+ }
+
+ info.options.add(new OptionInfo(optionName, help, optionType, declaringClass, field));
+ }
+
+ private void createFiles(OptionsInfo info) {
+ String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
+ Name topDeclaringClass = info.topDeclaringType.getSimpleName();
+ Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
+
+ createOptionsDescriptorsFile(info, pkg, topDeclaringClass, originatingElements);
+ }
+
+ private void createOptionsDescriptorsFile(OptionsInfo info, String pkg, Name topDeclaringClass, Element[] originatingElements) {
+ String optionsClassName = topDeclaringClass + "_" + OptionDescriptors.class.getSimpleName();
+
+ Filer filer = processingEnv.getFiler();
+ try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
+
+ out.println("// CheckStyle: stop header check");
+ out.println("// CheckStyle: stop line length check");
+ out.println("// GENERATED CONTENT - DO NOT EDIT");
+ out.println("// Source: " + topDeclaringClass + ".java");
+ out.println("package " + pkg + ";");
+ out.println("");
+ out.println("import java.util.*;");
+ out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
+ out.println("");
+ out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
+
+ String desc = OptionDescriptor.class.getSimpleName();
+
+ boolean needPrivateFieldAccessor = false;
+ int i = 0;
+ Collections.sort(info.options);
+
+ out.println(" @Override");
+ out.println(" public OptionDescriptor get(String value) {");
+ out.println(" // CheckStyle: stop line length check");
+ if (info.options.size() == 1) {
+ out.println(" if (value.equals(\"" + info.options.get(0).name + "\")) {");
+ } else {
+ out.println(" switch (value) {");
+ }
+ for (OptionInfo option : info.options) {
+ String name = option.name;
+ String optionValue;
+ if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+ needPrivateFieldAccessor = true;
+ optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+ } else {
+ optionValue = option.declaringClass + "." + option.field.getSimpleName();
+ }
+ String type = option.type;
+ String help = option.help;
+ String declaringClass = option.declaringClass;
+ Name fieldName = option.field.getSimpleName();
+ if (info.options.size() == 1) {
+ out.printf(" return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
+ } else {
+ out.printf(" case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName,
+ optionValue);
+ }
+ }
+ out.println(" }");
+ out.println(" // CheckStyle: resume line length check");
+ out.println(" return null;");
+ out.println(" }");
+ out.println();
+ out.println(" @Override");
+ out.println(" public Iterator<" + desc + "> iterator() {");
+ out.println(" // CheckStyle: stop line length check");
+ out.println(" List<" + desc + "> options = Arrays.asList(");
+ for (OptionInfo option : info.options) {
+ String optionValue;
+ if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+ needPrivateFieldAccessor = true;
+ optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+ } else {
+ optionValue = option.declaringClass + "." + option.field.getSimpleName();
+ }
+ String name = option.name;
+ String type = option.type;
+ String help = option.help;
+ String declaringClass = option.declaringClass;
+ Name fieldName = option.field.getSimpleName();
+ String comma = i == info.options.size() - 1 ? "" : ",";
+ out.printf(" %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
+ i++;
+ }
+ out.println(" );");
+ out.println(" // CheckStyle: resume line length check");
+ out.println(" return options.iterator();");
+ out.println(" }");
+ if (needPrivateFieldAccessor) {
+ out.println(" private static " + OptionValue.class.getSimpleName() + "<?> field(Class<?> declaringClass, String fieldName) {");
+ out.println(" try {");
+ out.println(" java.lang.reflect.Field field = declaringClass.getDeclaredField(fieldName);");
+ out.println(" field.setAccessible(true);");
+ out.println(" return (" + OptionValue.class.getSimpleName() + "<?>) field.get(null);");
+ out.println(" } catch (Exception e) {");
+ out.println(" throw (InternalError) new InternalError().initCause(e);");
+ out.println(" }");
+ out.println(" }");
+ }
+ out.println("}");
+ }
+
+ try {
+ createOptionsFile(pkg, topDeclaringClass.toString(), originatingElements);
+ } catch (IOException e) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
+ }
+ }
+
+ private void createOptionsFile(String pkg, String relativeName, Element... originatingElements) throws IOException {
+ String filename = "META-INF/jvmci.options/" + pkg + "." + relativeName;
+ FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
+ writer.close();
+ }
+
+ protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
+ try {
+ // Ensure Unix line endings to comply with code style guide checked by Checkstyle
+ JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
+ return new PrintWriter(sourceFile.openWriter()) {
+
+ @Override
+ public void println() {
+ print("\n");
+ }
+ };
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static class OptionInfo implements Comparable<OptionInfo> {
+
+ final String name;
+ final String help;
+ final String type;
+ final String declaringClass;
+ final VariableElement field;
+
+ public OptionInfo(String name, String help, String type, String declaringClass, VariableElement field) {
+ this.name = name;
+ this.help = help;
+ this.type = type;
+ this.declaringClass = declaringClass;
+ this.field = field;
+ }
+
+ @Override
+ public int compareTo(OptionInfo other) {
+ return name.compareTo(other.name);
+ }
+
+ @Override
+ public String toString() {
+ return declaringClass + "." + field;
+ }
+ }
+
+ static class OptionsInfo {
+
+ final Element topDeclaringType;
+ final List<OptionInfo> options = new ArrayList<>();
+ final Set<Element> originatingElements = new HashSet<>();
+
+ public OptionsInfo(Element topDeclaringType) {
+ this.topDeclaringType = topDeclaringType;
+ }
+ }
+
+ private static Element topDeclaringType(Element element) {
+ Element enclosing = element.getEnclosingElement();
+ if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) {
+ assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
+ return element;
+ }
+ return topDeclaringType(enclosing);
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return true;
+ }
+
+ Map<Element, OptionsInfo> map = new HashMap<>();
+ for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) {
+ if (!processed.contains(element)) {
+ processed.add(element);
+ Element topDeclaringType = topDeclaringType(element);
+ OptionsInfo options = map.get(topDeclaringType);
+ if (options == null) {
+ options = new OptionsInfo(topDeclaringType);
+ map.put(topDeclaringType, options);
+ }
+ processElement(element, options);
+ }
+ }
+
+ boolean ok = true;
+ Map<String, OptionInfo> uniqueness = new HashMap<>();
+ for (OptionsInfo info : map.values()) {
+ for (OptionInfo option : info.options) {
+ OptionInfo conflict = uniqueness.put(option.name, option);
+ if (conflict != null) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Duplicate option names for " + option + " and " + conflict, option.field);
+ ok = false;
+ }
+ }
+ }
+
+ if (ok) {
+ for (OptionsInfo info : map.values()) {
+ createFiles(info);
+ }
+ }
+
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.options;
+
+import java.io.*;
+import java.util.function.*;
+
+import jdk.vm.ci.options.OptionValue.*;
+
+/**
+ * A cached value that needs to be recomputed when an option changes.
+ */
+public class DerivedOptionValue<T> {
+
+ public interface OptionSupplier<T> extends Supplier<T>, Serializable {
+ }
+
+ private final T initialValue;
+ private final OptionSupplier<T> supplier;
+
+ public DerivedOptionValue(OptionSupplier<T> supplier) {
+ this.supplier = supplier;
+ assert OptionValue.getOverrideScope() == null : "derived option value should be initialized outside any override scope";
+ this.initialValue = createValue();
+ }
+
+ public T getValue() {
+ OverrideScope overrideScope = OptionValue.getOverrideScope();
+ if (overrideScope != null) {
+ return overrideScope.getDerived(this);
+ } else {
+ return initialValue;
+ }
+ }
+
+ T createValue() {
+ return supplier.get();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.options;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.*;
+
+import jdk.vm.ci.options.OptionsParser.*;
+
+/**
+ * Access to the {@link OptionDescriptors} declared by
+ * {@code META-INF/services/jdk.vm.ci.options.OptionDescriptors} files in {@code
+ * <jre>/lib/jvmci/*.jar}.
+ */
+class JVMCIJarsOptionDescriptorsProvider implements OptionDescriptorsProvider {
+
+ static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName();
+
+ private final Iterator<File> jars;
+ private final List<OptionDescriptors> optionsDescriptorsList;
+
+ JVMCIJarsOptionDescriptorsProvider() {
+ List<File> jarsList = findJVMCIJars();
+ this.jars = jarsList.iterator();
+ this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3);
+ }
+
+ /**
+ * Finds the list of JVMCI jars.
+ */
+ private static List<File> findJVMCIJars() {
+ File javaHome = new File(System.getProperty("java.home"));
+ File lib = new File(javaHome, "lib");
+ File jvmci = new File(lib, "jvmci");
+
+ List<File> jarFiles = new ArrayList<>();
+ if (jvmci.exists()) {
+ for (String fileName : jvmci.list()) {
+ if (fileName.endsWith(".jar")) {
+ File file = new File(jvmci, fileName);
+ if (file.isDirectory()) {
+ continue;
+ }
+ jarFiles.add(file);
+ }
+ }
+ }
+ return jarFiles;
+ }
+
+ public OptionDescriptor get(String name) {
+ // Look up loaded option descriptors first
+ for (OptionDescriptors optionDescriptors : optionsDescriptorsList) {
+ OptionDescriptor desc = optionDescriptors.get(name);
+ if (desc != null) {
+ return desc;
+ }
+ }
+ while (jars.hasNext()) {
+ File path = jars.next();
+ try (JarFile jar = new JarFile(path)) {
+ ZipEntry entry = jar.getEntry(OptionDescriptorsServiceFile);
+ if (entry != null) {
+ BufferedReader br = new BufferedReader(new InputStreamReader(jar.getInputStream(entry)));
+ String line = null;
+ OptionDescriptor desc = null;
+ while ((line = br.readLine()) != null) {
+ OptionDescriptors options;
+ try {
+ options = (OptionDescriptors) Class.forName(line).newInstance();
+ optionsDescriptorsList.add(options);
+ if (desc == null) {
+ desc = options.get(name);
+ }
+ } catch (Exception e) {
+ throw new InternalError("Error instantiating class " + line + " read from " + path, e);
+ }
+ }
+ if (desc != null) {
+ return desc;
+ }
+ }
+ } catch (IOException e) {
+ throw new InternalError("Error reading " + path, e);
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, 2015, 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.
+ */
+package jdk.vm.ci.options;
+
+/**
+ * A nested Boolean {@link OptionValue} that can be overridden by a {@link #masterOption master
+ * option}.
+ * <p>
+ * <li>If the option is present on the command line the specified value is used.
+ * <li>Otherwise {@link #getValue()} depends on the {@link #masterOption} and evaluates as follows:
+ * <ul>
+ * <li>If {@link #masterOption} is set, this value equals to {@link #initialValue}.
+ * <li>Otherwise, if {@link #masterOption} is {@code false}, this option is {@code false}.
+ */
+public class NestedBooleanOptionValue extends OptionValue<Boolean> {
+ private final OptionValue<Boolean> masterOption;
+ private final Boolean initialValue;
+
+ public NestedBooleanOptionValue(OptionValue<Boolean> masterOption, Boolean initialValue) {
+ super(null);
+ this.masterOption = masterOption;
+ this.initialValue = initialValue;
+ }
+
+ public OptionValue<Boolean> getMasterOption() {
+ return masterOption;
+ }
+
+ @Override
+ public Boolean getValue() {
+ Boolean v = super.getValue();
+ if (v == null) {
+ return initialValue && masterOption.getValue();
+ }
+ return v;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options;
+
+import java.lang.annotation.*;
+
+/**
+ * Describes the attributes of an option whose {@link OptionValue value} is in a static field
+ * annotated by this annotation type.
+ *
+ * @see OptionDescriptor
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.FIELD)
+public @interface Option {
+
+ /**
+ * Gets a help message for the option. New lines can be embedded in the message with
+ * {@code "%n"}.
+ */
+ String help();
+
+ /**
+ * The name of the option. By default, the name of the annotated field should be used.
+ */
+ String name() default "";
+
+ /**
+ * Specifies the type of the option.
+ */
+ OptionType type() default OptionType.Debug;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionDescriptor.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options;
+
+/**
+ * Describes the attributes of a static field {@linkplain Option option} and provides access to its
+ * {@linkplain OptionValue value}.
+ */
+public final class OptionDescriptor {
+
+ protected final String name;
+ protected final Class<?> type;
+ protected final String help;
+ protected final OptionValue<?> option;
+ protected final Class<?> declaringClass;
+ protected final String fieldName;
+
+ public static OptionDescriptor create(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+ OptionDescriptor result = option.getDescriptor();
+ if (result == null) {
+ result = new OptionDescriptor(name, type, help, declaringClass, fieldName, option);
+ option.setDescriptor(result);
+ }
+ assert result.name.equals(name) && result.type == type && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.option == option;
+ return result;
+ }
+
+ private OptionDescriptor(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+ this.name = name;
+ this.type = type;
+ this.help = help;
+ this.option = option;
+ this.declaringClass = declaringClass;
+ this.fieldName = fieldName;
+ assert !type.isPrimitive() : "must used boxed type instead of " + type;
+ }
+
+ /**
+ * Gets the type of values stored in the option. This will be the boxed type for a primitive
+ * option.
+ */
+ public Class<?> getType() {
+ return type;
+ }
+
+ /**
+ * Gets a descriptive help message for the option.
+ */
+ public String getHelp() {
+ return help;
+ }
+
+ /**
+ * Gets the name of the option. It's up to the client of this object how to use the name to get
+ * a user specified value for the option from the environment.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the boxed option value.
+ */
+ public OptionValue<?> getOptionValue() {
+ return option;
+ }
+
+ public Class<?> getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ /**
+ * Gets a description of the location where this option is stored.
+ */
+ public String getLocation() {
+ return getDeclaringClass().getName() + "." + getFieldName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionDescriptors.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options;
+
+/**
+ * An interface to a set of {@link OptionDescriptor}s.
+ */
+public interface OptionDescriptors extends Iterable<OptionDescriptor> {
+ /**
+ * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
+ * descriptor set doesn't contain a matching option.
+ */
+ OptionDescriptor get(String value);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.options;
+
+/**
+ * Classifies JVMCI options in several categories depending on who this option is relevant for.
+ *
+ */
+public enum OptionType {
+ /**
+ * An option common for users to apply.
+ */
+ User,
+
+ /**
+ * An option only relevant in corner cases and for fine-tuning.
+ */
+ Expert,
+
+ /**
+ * An option only relevant when debugging the compiler.
+ */
+ Debug
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * An option value.
+ */
+public class OptionValue<T> {
+ /**
+ * Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of
+ * {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the
+ * object returned by this method.
+ * <p>
+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+ * used:
+ *
+ * <pre>
+ * try (OverrideScope s = OptionValue.override(myOption, myValue) {
+ * // code that depends on myOption == myValue
+ * }
+ * </pre>
+ */
+ public static OverrideScope override(OptionValue<?> option, Object value) {
+ OverrideScope current = getOverrideScope();
+ if (current == null) {
+ if (!value.equals(option.getValue())) {
+ return new SingleOverrideScope(option, value);
+ }
+ Map<OptionValue<?>, Object> overrides = Collections.emptyMap();
+ return new MultipleOverridesScope(current, overrides);
+ }
+ return new MultipleOverridesScope(current, option, value);
+ }
+
+ /**
+ * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
+ * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
+ * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
+ * this method.
+ * <p>
+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+ * used:
+ *
+ * <pre>
+ * Map<OptionValue, Object> overrides = new HashMap<>();
+ * overrides.put(myOption1, myValue1);
+ * overrides.put(myOption2, myValue2);
+ * try (OverrideScope s = OptionValue.override(overrides) {
+ * // code that depends on myOption == myValue
+ * }
+ * </pre>
+ */
+ public static OverrideScope override(Map<OptionValue<?>, Object> overrides) {
+ OverrideScope current = getOverrideScope();
+ if (current == null && overrides.size() == 1) {
+ Entry<OptionValue<?>, Object> single = overrides.entrySet().iterator().next();
+ OptionValue<?> option = single.getKey();
+ Object overrideValue = single.getValue();
+ if (!overrideValue.equals(option.getValue())) {
+ return new SingleOverrideScope(option, overrideValue);
+ }
+ }
+ return new MultipleOverridesScope(current, overrides);
+ }
+
+ /**
+ * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
+ * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
+ * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
+ * this method.
+ * <p>
+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+ * used:
+ *
+ * <pre>
+ * try (OverrideScope s = OptionValue.override(myOption1, myValue1, myOption2, myValue2) {
+ * // code that depends on myOption == myValue
+ * }
+ * </pre>
+ *
+ * @param overrides overrides in the form {@code [option1, override1, option2, override2, ...]}
+ */
+ public static OverrideScope override(Object... overrides) {
+ OverrideScope current = getOverrideScope();
+ if (current == null && overrides.length == 2) {
+ OptionValue<?> option = (OptionValue<?>) overrides[0];
+ Object overrideValue = overrides[1];
+ if (!overrideValue.equals(option.getValue())) {
+ return new SingleOverrideScope(option, overrideValue);
+ }
+ }
+ Map<OptionValue<?>, Object> map = Collections.emptyMap();
+ for (int i = 0; i < overrides.length; i += 2) {
+ OptionValue<?> option = (OptionValue<?>) overrides[i];
+ Object overrideValue = overrides[i + 1];
+ if (!overrideValue.equals(option.getValue())) {
+ if (map.isEmpty()) {
+ map = new HashMap<>();
+ }
+ map.put(option, overrideValue);
+ }
+ }
+ return new MultipleOverridesScope(current, map);
+ }
+
+ private static final ThreadLocal<OverrideScope> overrideScopeTL = new ThreadLocal<>();
+
+ protected static OverrideScope getOverrideScope() {
+ return overrideScopeTL.get();
+ }
+
+ protected static void setOverrideScope(OverrideScope overrideScope) {
+ overrideScopeTL.set(overrideScope);
+ }
+
+ private T defaultValue;
+
+ /**
+ * The raw option value.
+ */
+ protected T value;
+
+ private OptionDescriptor descriptor;
+
+ private long reads;
+ private OptionValue<?> next;
+ private static OptionValue<?> head;
+
+ private static final boolean ShowReadsHistogram = Boolean.getBoolean("jvmci.showOptionValueReadsHistogram");
+
+ private static void addToHistogram(OptionValue<?> option) {
+ if (ShowReadsHistogram) {
+ synchronized (OptionValue.class) {
+ option.next = head;
+ head = option;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public OptionValue(T value) {
+ this.defaultValue = value;
+ this.value = (T) DEFAULT;
+ addToHistogram(this);
+ }
+
+ private static final Object DEFAULT = "DEFAULT";
+ private static final Object UNINITIALIZED = "UNINITIALIZED";
+
+ /**
+ * Creates an uninitialized option value for a subclass that initializes itself
+ * {@link #defaultValue() lazily}.
+ */
+ @SuppressWarnings("unchecked")
+ protected OptionValue() {
+ this.defaultValue = (T) UNINITIALIZED;
+ this.value = (T) DEFAULT;
+ addToHistogram(this);
+ }
+
+ /**
+ * Lazy initialization of default value.
+ */
+ protected T defaultValue() {
+ throw new InternalError("Option without a default value value must override defaultValue()");
+ }
+
+ /**
+ * Sets the descriptor for this option.
+ */
+ public void setDescriptor(OptionDescriptor descriptor) {
+ assert this.descriptor == null : "Overwriting existing descriptor";
+ this.descriptor = descriptor;
+ }
+
+ /**
+ * Returns the descriptor for this option, if it has been set by
+ * {@link #setDescriptor(OptionDescriptor)}.
+ */
+ public OptionDescriptor getDescriptor() {
+ return descriptor;
+ }
+
+ /**
+ * Gets the name of this option. The name for an option value with a null
+ * {@linkplain #setDescriptor(OptionDescriptor) descriptor} is the value of
+ * {@link Object#toString()}.
+ */
+ public String getName() {
+ return descriptor == null ? super.toString() : (descriptor.getDeclaringClass().getName() + "." + descriptor.getName());
+ }
+
+ @Override
+ public String toString() {
+ return getName() + "=" + getValue();
+ }
+
+ /**
+ * The initial value specified in source code. The returned value is not affected by calls to
+ * {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not
+ * affected by options set on the command line.
+ */
+ public T getDefaultValue() {
+ if (defaultValue == UNINITIALIZED) {
+ defaultValue = defaultValue();
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Returns true if the option has the same value that was set in the source code.
+ */
+ public boolean hasDefaultValue() {
+ if (!(this instanceof StableOptionValue)) {
+ getValue(); // ensure initialized
+ }
+ return value == DEFAULT || Objects.equals(value, getDefaultValue());
+ }
+
+ /**
+ * Gets the value of this option.
+ */
+ public T getValue() {
+ if (ShowReadsHistogram) {
+ reads++;
+ }
+ if (!(this instanceof StableOptionValue)) {
+ OverrideScope overrideScope = getOverrideScope();
+ if (overrideScope != null) {
+ T override = overrideScope.getOverride(this);
+ if (override != null) {
+ return override;
+ }
+ }
+ }
+ if (value != DEFAULT) {
+ return value;
+ } else {
+ return getDefaultValue();
+ }
+ }
+
+ /**
+ * Gets the values of this option including overridden values.
+ *
+ * @param c the collection to which the values are added. If null, one is allocated.
+ * @return the collection to which the values were added in order from most overridden to
+ * current value
+ */
+ @SuppressWarnings("unchecked")
+ public Collection<T> getValues(Collection<T> c) {
+ Collection<T> values = c == null ? new ArrayList<>() : c;
+ if (!(this instanceof StableOptionValue)) {
+ OverrideScope overrideScope = getOverrideScope();
+ if (overrideScope != null) {
+ overrideScope.getOverrides(this, (Collection<Object>) values);
+ }
+ }
+ if (value != DEFAULT) {
+ values.add(value);
+ } else {
+ values.add(getDefaultValue());
+ }
+ return values;
+ }
+
+ /**
+ * Sets the value of this option.
+ */
+ @SuppressWarnings("unchecked")
+ public void setValue(Object v) {
+ this.value = (T) v;
+ }
+
+ /**
+ * An object whose {@link #close()} method reverts the option value overriding initiated by
+ * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
+ */
+ public abstract static class OverrideScope implements AutoCloseable {
+
+ private Map<DerivedOptionValue<?>, Object> derivedCache = null;
+
+ public <T> T getDerived(DerivedOptionValue<T> key) {
+ if (derivedCache == null) {
+ derivedCache = new HashMap<>();
+ }
+ @SuppressWarnings("unchecked")
+ T ret = (T) derivedCache.get(key);
+ if (ret == null) {
+ ret = key.createValue();
+ derivedCache.put(key, ret);
+ }
+ return ret;
+ }
+
+ abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
+
+ abstract <T> T getOverride(OptionValue<T> option);
+
+ abstract void getOverrides(OptionValue<?> option, Collection<Object> c);
+
+ public abstract void close();
+ }
+
+ static class SingleOverrideScope extends OverrideScope {
+
+ private final OptionValue<?> option;
+ private final Object value;
+
+ public SingleOverrideScope(OptionValue<?> option, Object value) {
+ if (option instanceof StableOptionValue) {
+ throw new IllegalArgumentException("Cannot override stable option " + option);
+ }
+ this.option = option;
+ this.value = value;
+ setOverrideScope(this);
+ }
+
+ @Override
+ void addToInherited(Map<OptionValue<?>, Object> inherited) {
+ inherited.put(option, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ <T> T getOverride(OptionValue<T> key) {
+ if (key == this.option) {
+ return (T) value;
+ }
+ return null;
+ }
+
+ @Override
+ void getOverrides(OptionValue<?> key, Collection<Object> c) {
+ if (key == this.option) {
+ c.add(value);
+ }
+ }
+
+ @Override
+ public void close() {
+ setOverrideScope(null);
+ }
+ }
+
+ static class MultipleOverridesScope extends OverrideScope {
+ final OverrideScope parent;
+ final Map<OptionValue<?>, Object> overrides;
+
+ public MultipleOverridesScope(OverrideScope parent, OptionValue<?> option, Object value) {
+ this.parent = parent;
+ this.overrides = new HashMap<>();
+ if (parent != null) {
+ parent.addToInherited(overrides);
+ }
+ if (option instanceof StableOptionValue) {
+ throw new IllegalArgumentException("Cannot override stable option " + option);
+ }
+ if (!value.equals(option.getValue())) {
+ this.overrides.put(option, value);
+ }
+ if (!overrides.isEmpty()) {
+ setOverrideScope(this);
+ }
+ }
+
+ MultipleOverridesScope(OverrideScope parent, Map<OptionValue<?>, Object> overrides) {
+ this.parent = parent;
+ if (overrides.isEmpty() && parent == null) {
+ this.overrides = Collections.emptyMap();
+ return;
+ }
+ this.overrides = new HashMap<>();
+ if (parent != null) {
+ parent.addToInherited(this.overrides);
+ }
+ for (Map.Entry<OptionValue<?>, Object> e : overrides.entrySet()) {
+ OptionValue<?> option = e.getKey();
+ if (option instanceof StableOptionValue) {
+ throw new IllegalArgumentException("Cannot override stable option " + option);
+ }
+ if (!e.getValue().equals(option.getValue())) {
+ this.overrides.put(option, e.getValue());
+ }
+ }
+ if (!this.overrides.isEmpty()) {
+ setOverrideScope(this);
+ }
+ }
+
+ @Override
+ void addToInherited(Map<OptionValue<?>, Object> inherited) {
+ if (parent != null) {
+ parent.addToInherited(inherited);
+ }
+ inherited.putAll(overrides);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ <T> T getOverride(OptionValue<T> option) {
+ return (T) overrides.get(option);
+ }
+
+ @Override
+ void getOverrides(OptionValue<?> option, Collection<Object> c) {
+ Object v = overrides.get(option);
+ if (v != null) {
+ c.add(v);
+ }
+ if (parent != null) {
+ parent.getOverrides(option, c);
+ }
+ }
+
+ @Override
+ public void close() {
+ if (!overrides.isEmpty()) {
+ setOverrideScope(parent);
+ }
+ }
+ }
+
+ static {
+ if (ShowReadsHistogram) {
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ ArrayList<OptionValue<?>> options = new ArrayList<>();
+ for (OptionValue<?> option = head; option != null; option = option.next) {
+ options.add(option);
+ }
+ Collections.sort(options, new Comparator<OptionValue<?>>() {
+
+ public int compare(OptionValue<?> o1, OptionValue<?> o2) {
+ if (o1.reads < o2.reads) {
+ return -1;
+ } else if (o1.reads > o2.reads) {
+ return 1;
+ } else {
+ return o1.getName().compareTo(o2.getName());
+ }
+ }
+ });
+ PrintStream out = System.out;
+ out.println("=== OptionValue reads histogram ===");
+ for (OptionValue<?> option : options) {
+ out.println(option.reads + "\t" + option);
+ }
+ }
+ });
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.options;
+
+import java.util.*;
+
+/**
+ * Helper class used to load option descriptors. Only to be used in the slow-path.
+ */
+public class OptionsLoader {
+ public static final SortedMap<String, OptionDescriptor> options = new TreeMap<>();
+
+ /**
+ * Initializes {@link #options} from {@link Options} services.
+ */
+ static {
+ for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, OptionsLoader.class.getClassLoader())) {
+ for (OptionDescriptor desc : opts) {
+ String name = desc.getName();
+ OptionDescriptor existing = options.put(name, desc);
+ assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.options;
+
+import static jdk.vm.ci.inittimer.InitTimer.*;
+
+import java.io.*;
+import java.util.*;
+
+import jdk.vm.ci.inittimer.*;
+
+/**
+ * This class contains methods for parsing JVMCI options and matching them against a set of
+ * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded from JVMCI jars, either
+ * {@linkplain JVMCIJarsOptionDescriptorsProvider directly} or via a {@link ServiceLoader}.
+ */
+public class OptionsParser {
+
+ private static final OptionValue<Boolean> PrintFlags = new OptionValue<>(false);
+
+ /**
+ * A service for looking up {@link OptionDescriptor}s.
+ */
+ public interface OptionDescriptorsProvider {
+ /**
+ * Gets the {@link OptionDescriptor} matching a given option {@linkplain Option#name() name}
+ * or null if no option of that name is provided by this object.
+ */
+ OptionDescriptor get(String name);
+ }
+
+ public interface OptionConsumer {
+ void set(OptionDescriptor desc, Object value);
+ }
+
+ /**
+ * Parses the options in {@code <jre>/lib/jvmci/options} if {@code parseOptionsFile == true} and
+ * the file exists followed by the JVMCI options in {@code options} if {@code options != null}.
+ *
+ * Called from VM. This method has an object return type to allow it to be called with a VM
+ * utility function used to call other static initialization methods.
+ *
+ * @param options JVMCI options as serialized (name, value) pairs
+ * @param parseOptionsFile specifies whether to look for and parse
+ * {@code <jre>/lib/jvmci/options}
+ */
+ @SuppressWarnings("try")
+ public static Boolean parseOptionsFromVM(String[] options, boolean parseOptionsFile) {
+ try (InitTimer t = timer("ParseOptions")) {
+ JVMCIJarsOptionDescriptorsProvider odp = new JVMCIJarsOptionDescriptorsProvider();
+
+ if (parseOptionsFile) {
+ File javaHome = new File(System.getProperty("java.home"));
+ File lib = new File(javaHome, "lib");
+ File jvmci = new File(lib, "jvmci");
+ File jvmciOptions = new File(jvmci, "options");
+ if (jvmciOptions.exists()) {
+ try (BufferedReader br = new BufferedReader(new FileReader(jvmciOptions))) {
+ String optionSetting = null;
+ int lineNo = 1;
+ while ((optionSetting = br.readLine()) != null) {
+ if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') {
+ try {
+ parseOptionSetting(optionSetting, null, odp);
+ } catch (Throwable e) {
+ throw new InternalError("Error parsing " + jvmciOptions + ", line " + lineNo, e);
+ }
+ }
+ lineNo++;
+ }
+ } catch (IOException e) {
+ throw new InternalError("Error reading " + jvmciOptions, e);
+ }
+ }
+ }
+
+ if (options != null) {
+ assert options.length % 2 == 0;
+ for (int i = 0; i < options.length / 2; i++) {
+ String name = options[i * 2];
+ String value = options[i * 2 + 1];
+ parseOption(OptionsLoader.options, name, value, null, odp);
+ }
+ }
+ }
+ return Boolean.TRUE;
+ }
+
+ /**
+ * Parses a given option setting.
+ *
+ * @param optionSetting a string matching the pattern {@code <name>=<value>}
+ * @param setter the object to notify of the parsed option and value
+ */
+ public static void parseOptionSetting(String optionSetting, OptionConsumer setter, OptionDescriptorsProvider odp) {
+ int eqIndex = optionSetting.indexOf('=');
+ if (eqIndex == -1) {
+ throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + optionSetting);
+ }
+ String name = optionSetting.substring(0, eqIndex);
+ String value = optionSetting.substring(eqIndex + 1);
+ parseOption(OptionsLoader.options, name, value, setter, odp);
+ }
+
+ /**
+ * Parses a given option name and value.
+ *
+ * @param options
+ * @param name the option name
+ * @param valueString the option value as a string
+ * @param setter the object to notify of the parsed option and value
+ * @param odp
+ *
+ * @throws IllegalArgumentException if there's a problem parsing {@code option}
+ */
+ public static void parseOption(SortedMap<String, OptionDescriptor> options, String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp) {
+ OptionDescriptor desc = options.get(name);
+ if (desc == null && odp != null) {
+ desc = odp.get(name);
+ }
+ if (desc == null && name.equals("PrintFlags")) {
+ desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags);
+ }
+ if (desc == null) {
+ List<OptionDescriptor> matches = fuzzyMatch(options, name);
+ Formatter msg = new Formatter();
+ msg.format("Could not find option %s", name);
+ if (!matches.isEmpty()) {
+ msg.format("%nDid you mean one of the following?");
+ for (OptionDescriptor match : matches) {
+ msg.format("%n %s=<value>", match.getName());
+ }
+ }
+ throw new IllegalArgumentException(msg.toString());
+ }
+
+ Class<?> optionType = desc.getType();
+ Object value;
+ if (optionType == Boolean.class) {
+ if ("true".equals(valueString)) {
+ value = Boolean.TRUE;
+ } else if ("false".equals(valueString)) {
+ value = Boolean.FALSE;
+ } else {
+ throw new IllegalArgumentException("Boolean option '" + name + "' must have value \"true\" or \"false\", not \"" + valueString + "\"");
+ }
+ } else if (optionType == Float.class) {
+ value = Float.parseFloat(valueString);
+ } else if (optionType == Double.class) {
+ value = Double.parseDouble(valueString);
+ } else if (optionType == Integer.class) {
+ value = Integer.valueOf((int) parseLong(valueString));
+ } else if (optionType == Long.class) {
+ value = Long.valueOf(parseLong(valueString));
+ } else if (optionType == String.class) {
+ value = valueString;
+ } else {
+ throw new IllegalArgumentException("Wrong value for option '" + name + "'");
+ }
+ if (setter == null) {
+ desc.getOptionValue().setValue(value);
+ } else {
+ setter.set(desc, value);
+ }
+
+ if (PrintFlags.getValue()) {
+ printFlags(options, "JVMCI", System.out);
+ System.exit(0);
+ }
+ }
+
+ private static long parseLong(String v) {
+ String valueString = v.toLowerCase();
+ long scale = 1;
+ if (valueString.endsWith("k")) {
+ scale = 1024L;
+ } else if (valueString.endsWith("m")) {
+ scale = 1024L * 1024L;
+ } else if (valueString.endsWith("g")) {
+ scale = 1024L * 1024L * 1024L;
+ } else if (valueString.endsWith("t")) {
+ scale = 1024L * 1024L * 1024L * 1024L;
+ }
+
+ if (scale != 1) {
+ /* Remove trailing scale character. */
+ valueString = valueString.substring(0, valueString.length() - 1);
+ }
+
+ return Long.parseLong(valueString) * scale;
+ }
+
+ /**
+ * Wraps some given text to one or more lines of a given maximum width.
+ *
+ * @param text text to wrap
+ * @param width maximum width of an output line, exception for words in {@code text} longer than
+ * this value
+ * @return {@code text} broken into lines
+ */
+ private static List<String> wrap(String text, int width) {
+ List<String> lines = Collections.singletonList(text);
+ if (text.length() > width) {
+ String[] chunks = text.split("\\s+");
+ lines = new ArrayList<>();
+ StringBuilder line = new StringBuilder();
+ for (String chunk : chunks) {
+ if (line.length() + chunk.length() > width) {
+ lines.add(line.toString());
+ line.setLength(0);
+ }
+ if (line.length() != 0) {
+ line.append(' ');
+ }
+ String[] embeddedLines = chunk.split("%n", -2);
+ if (embeddedLines.length == 1) {
+ line.append(chunk);
+ } else {
+ for (int i = 0; i < embeddedLines.length; i++) {
+ line.append(embeddedLines[i]);
+ if (i < embeddedLines.length - 1) {
+ lines.add(line.toString());
+ line.setLength(0);
+ }
+ }
+ }
+ }
+ if (line.length() != 0) {
+ lines.add(line.toString());
+ }
+ }
+ return lines;
+ }
+
+ public static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out) {
+ out.println("[List of " + prefix + " options]");
+ for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
+ e.getKey();
+ OptionDescriptor desc = e.getValue();
+ Object value = desc.getOptionValue().getValue();
+ List<String> helpLines = wrap(desc.getHelp(), 70);
+ out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+ for (int i = 1; i < helpLines.size(); i++) {
+ out.println(String.format("%67s %s", " ", helpLines.get(i)));
+ }
+ }
+ }
+
+ /**
+ * Compute string similarity based on Dice's coefficient.
+ *
+ * Ported from str_similar() in globals.cpp.
+ */
+ static float stringSimiliarity(String str1, String str2) {
+ int hit = 0;
+ for (int i = 0; i < str1.length() - 1; ++i) {
+ for (int j = 0; j < str2.length() - 1; ++j) {
+ if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
+ ++hit;
+ break;
+ }
+ }
+ }
+ return 2.0f * hit / (str1.length() + str2.length());
+ }
+
+ private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
+
+ /**
+ * Returns the set of options that fuzzy match a given option name.
+ */
+ private static List<OptionDescriptor> fuzzyMatch(SortedMap<String, OptionDescriptor> options, String optionName) {
+ List<OptionDescriptor> matches = new ArrayList<>();
+ for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
+ float score = stringSimiliarity(e.getKey(), optionName);
+ if (score >= FUZZY_MATCH_THRESHOLD) {
+ matches.add(e.getValue());
+ }
+ }
+ return matches;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/StableOptionValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.options;
+
+/**
+ * An option that always returns the same {@linkplain #getValue() value}.
+ */
+public class StableOptionValue<T> extends OptionValue<T> {
+
+ /**
+ * Creates a stable option value.
+ */
+ public StableOptionValue(T value) {
+ super(value);
+ }
+
+ /**
+ * Used to assert the invariant for stability. Without using locks, this check is not safe
+ * against races and so it's only an assertion.
+ */
+ private boolean getValueCalled;
+
+ /**
+ * Creates an uninitialized stable option value for a subclass that initializes itself
+ * {@link #defaultValue() lazily}.
+ */
+ public StableOptionValue() {
+ }
+
+ /**
+ * Gets the value of this option.
+ */
+ @Override
+ public final T getValue() {
+ T result = super.getValue();
+ assert initGetValueCalled();
+ return result;
+ }
+
+ private boolean initGetValueCalled() {
+ getValueCalled = true;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This must only be called if {@link #getValue()} has never been called.
+ */
+ @Override
+ public final void setValue(Object v) {
+ assert !getValueCalled;
+ super.setValue(v);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.runtime;
+
+import java.util.*;
+
+public class JVMCI {
+
+ private static final JVMCIRuntime runtime;
+
+ private static native JVMCIRuntime initializeRuntime();
+
+ public static void initialize() {
+ // force static initializer
+ }
+
+ /**
+ * Gets the singleton {@link JVMCIRuntime} instance available to the application.
+ *
+ * @throws UnsupportedOperationException if JVMCI is not supported
+ */
+ public static JVMCIRuntime getRuntime() {
+ if (runtime == null) {
+ String javaHome = System.getProperty("java.home");
+ String vmName = System.getProperty("java.vm.name");
+ Formatter errorMessage = new Formatter();
+ errorMessage.format("The VM does not support the JVMCI API.%n");
+ errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+ errorMessage.format("Currently used VM configuration is: %s", vmName);
+ throw new UnsupportedOperationException(errorMessage.toString());
+ }
+ return runtime;
+ }
+
+ static {
+ JVMCIRuntime rt = null;
+ try {
+ rt = initializeRuntime();
+ } catch (UnsatisfiedLinkError e) {
+ }
+ runtime = rt;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * A JVMCI backend encapsulates the capabilities needed by a Java based compiler for compiling and
+ * installing code for a single compute unit within a JVM. In a JVM with support for heterogeneous
+ * computing, more than one backend may be exposed.
+ */
+public class JVMCIBackend {
+
+ private final MetaAccessProvider metaAccess;
+ private final CodeCacheProvider codeCache;
+ private final ConstantReflectionProvider constantReflection;
+
+ public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
+ this.metaAccess = metaAccess;
+ this.codeCache = codeCache;
+ this.constantReflection = constantReflection;
+ }
+
+ public MetaAccessProvider getMetaAccess() {
+ return metaAccess;
+ }
+
+ public CodeCacheProvider getCodeCache() {
+ return codeCache;
+ }
+
+ public ConstantReflectionProvider getConstantReflection() {
+ return constantReflection;
+ }
+
+ public TargetDescription getTarget() {
+ return codeCache.getTarget();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.*;
+
+/**
+ * Interface for accessing the {@link JVMCI} APIs supported by the runtime.
+ */
+public interface JVMCIRuntime {
+
+ /**
+ * Gets the host JVMCI backend.
+ */
+ JVMCIBackend getHostJVMCIBackend();
+
+ /**
+ * Gets the backend for a given architecture.
+ *
+ * @param arch a specific architecture class
+ */
+ <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/META-INF/services/javax.annotation.processing.Processor Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+jdk.vm.ci.service.processor.ServiceProviderProcessor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.service.processor;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.Diagnostic.Kind;
+
+import jdk.vm.ci.service.*;
+
+import javax.tools.*;
+
+@SupportedAnnotationTypes("jdk.vm.ci.service.ServiceProvider")
+public class ServiceProviderProcessor extends AbstractProcessor {
+
+ private final Set<TypeElement> processed = new HashSet<>();
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) {
+ if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) {
+ String msg = String.format("Service provider class %s must implement service interface %s", serviceProvider.getSimpleName(), serviceInterface);
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
+ return false;
+ }
+
+ return true;
+ }
+
+ private void processElement(TypeElement serviceProvider) {
+ if (processed.contains(serviceProvider)) {
+ return;
+ }
+
+ processed.add(serviceProvider);
+ ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class);
+ if (annotation != null) {
+ try {
+ annotation.value();
+ } catch (MirroredTypeException ex) {
+ TypeMirror serviceInterface = ex.getTypeMirror();
+ if (verifyAnnotation(serviceInterface, serviceProvider)) {
+ String interfaceName = ex.getTypeMirror().toString();
+ createProviderFile(serviceProvider, interfaceName);
+ }
+ }
+ }
+ }
+
+ private void createProviderFile(TypeElement serviceProvider, String interfaceName) {
+ if (serviceProvider.getNestingKind().isNested()) {
+ // This is a simplifying constraint that means we don't have to
+ // processed the qualified name to insert '$' characters at
+ // the relevant positions.
+ String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName());
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
+ return;
+ }
+
+ String filename = "META-INF/jvmci.providers/" + serviceProvider.getQualifiedName();
+ try {
+ FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, serviceProvider);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
+ writer.println(interfaceName);
+ writer.close();
+ } catch (IOException e) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), serviceProvider);
+ }
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return true;
+ }
+
+ for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
+ assert element.getKind().isClass();
+ processElement((TypeElement) element);
+ }
+
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+ Checkstyle-Configuration: Checks
+ Description: none
+-->
+<module name="Checker">
+ <property name="severity" value="error"/>
+ <module name="TreeWalker">
+ <property name="tabWidth" value="4"/>
+ <module name="FileContentsHolder"/>
+ <module name="JavadocStyle">
+ <property name="checkHtml" value="false"/>
+ </module>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName">
+ <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+ </module>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="TypeName">
+ <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+ </module>
+ <module name="RedundantImport"/>
+ <module name="LineLength">
+ <property name="max" value="250"/>
+ </module>
+ <module name="MethodParamPad"/>
+ <module name="NoWhitespaceAfter">
+ <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+ </module>
+ <module name="NoWhitespaceBefore">
+ <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+ </module>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad">
+ <property name="tokens" value="RPAREN,TYPECAST"/>
+ </module>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround">
+ <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+ </module>
+ <module name="RedundantModifier"/>
+ <module name="AvoidNestedBlocks">
+ <property name="allowInSwitchCase" value="true"/>
+ </module>
+ <module name="EmptyBlock">
+ <property name="option" value="text"/>
+ <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+ </module>
+ <module name="LeftCurly"/>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+ <module name="EmptyStatement"/>
+ <module name="HiddenField">
+ <property name="severity" value="ignore"/>
+ <property name="ignoreConstructorParameter" value="true"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="FinalClass"/>
+ <module name="HideUtilityClassConstructor">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ArrayTypeStyle"/>
+ <module name="UpperEll"/>
+ <module name="FallThrough"/>
+ <module name="FinalLocalVariable">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="StringLiteralEquality">
+ <property name="severity" value="error"/>
+ </module>
+ <module name="SuperFinalize"/>
+ <module name="UnnecessaryParentheses">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="Indentation">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="StaticVariableName">
+ <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+ </module>
+ <module name="EmptyForInitializerPad"/>
+ <module name="EmptyForIteratorPad"/>
+ <module name="ModifierOrder"/>
+ <module name="DefaultComesLast"/>
+ <module name="InnerAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ModifiedControlVariable"/>
+ <module name="MutableException">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ParameterAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="format" value="\s$"/>
+ <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+ <property name="format" value=" ,"/>
+ <property name="message" value="illegal space before a comma"/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="[^\x00-\x7F]"/>
+ <property name="message" value="Only use ASCII characters."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+ <property name="message" value="Don't use old synchronized collection classes"/>
+ </module>
+ </module>
+ <module name="RegexpHeader">
+ <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="FileTabCharacter">
+ <property name="severity" value="error"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="NewlineAtEndOfFile">
+ <property name="lineSeparator" value="lf"/>
+ </module>
+ <module name="Translation"/>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+ <property name="checkFormat" value="ConstantNameCheck"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+ <property name="checkFormat" value="MethodName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+ <property name="checkFormat" value="ParameterAssignment"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+ <property name="checkFormat" value="FinalLocalVariable"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop"/>
+ <property name="onCommentFormat" value="Checkstyle: resume"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+ <property name="checkFormat" value="InnerAssignment"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+ <property name="checkFormat" value="MemberName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+ </module>
+ <module name="RegexpMultiline">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+ <property name="format" value="\r\n"/>
+ <property name="message" value="illegal Windows line ending"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+ <property name="checkFormat" value=".*Header"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+ <property name="checkFormat" value="LineLength"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: start generated"/>
+ <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+ <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
+ </module>
+</module>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.service;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotates a service provider than can be loaded via {@linkplain Services#load(Class)} or
+ * {@link Services#loadSingle(Class, boolean)}.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface ServiceProvider {
+
+ Class<?> value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+package jdk.vm.ci.service;
+
+import java.util.*;
+
+/**
+ * A mechanism for accessing service providers via JVMCI.
+ */
+public final class Services {
+
+ private Services() {
+ }
+
+ /**
+ * Gets an {@link Iterable} of the JVMCI providers available for a given service.
+ */
+ public static <S> Iterable<S> load(Class<S> service) {
+ return ServiceLoader.load(service);
+ }
+
+ /**
+ * Gets the JVMCI provider for a given service for which at most one provider must be available.
+ *
+ * @param service the service whose provider is being requested
+ * @param required specifies if an {@link InternalError} should be thrown if no provider of
+ * {@code service} is available
+ */
+ public static <S> S loadSingle(Class<S> service, boolean required) {
+ Iterable<S> providers = ServiceLoader.load(service);
+ S singleProvider = null;
+ try {
+ for (Iterator<S> it = providers.iterator(); it.hasNext();) {
+ singleProvider = it.next();
+ if (it.hasNext()) {
+ throw new InternalError(String.format("Multiple %s providers found", service.getName()));
+ }
+ }
+ } catch (ServiceConfigurationError e) {
+ // If the service is required we will bail out below.
+ }
+ if (singleProvider == null && required) {
+ String javaHome = System.getProperty("java.home");
+ String vmName = System.getProperty("java.vm.name");
+ Formatter errorMessage = new Formatter();
+ errorMessage.format("The VM does not expose required service %s.%n", service.getName());
+ errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+ errorMessage.format("Currently used VM configuration is: %s", vmName);
+ throw new UnsupportedOperationException(errorMessage.toString());
+ }
+ return singleProvider;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+package jdk.vm.ci.sparc;
+
+import static java.nio.ByteOrder.*;
+import static jdk.vm.ci.code.MemoryBarriers.*;
+
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the SPARC architecture.
+ */
+public class SPARC extends Architecture {
+
+ public static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+ // General purpose registers
+ public static final Register r0 = new Register(0, 0, "g0", CPU);
+ public static final Register r1 = new Register(1, 1, "g1", CPU);
+ public static final Register r2 = new Register(2, 2, "g2", CPU);
+ public static final Register r3 = new Register(3, 3, "g3", CPU);
+ public static final Register r4 = new Register(4, 4, "g4", CPU);
+ public static final Register r5 = new Register(5, 5, "g5", CPU);
+ public static final Register r6 = new Register(6, 6, "g6", CPU);
+ public static final Register r7 = new Register(7, 7, "g7", CPU);
+
+ public static final Register r8 = new Register(8, 8, "o0", CPU);
+ public static final Register r9 = new Register(9, 9, "o1", CPU);
+ public static final Register r10 = new Register(10, 10, "o2", CPU);
+ public static final Register r11 = new Register(11, 11, "o3", CPU);
+ public static final Register r12 = new Register(12, 12, "o4", CPU);
+ public static final Register r13 = new Register(13, 13, "o5", CPU);
+ public static final Register r14 = new Register(14, 14, "o6", CPU);
+ public static final Register r15 = new Register(15, 15, "o7", CPU);
+
+ public static final Register r16 = new Register(16, 16, "l0", CPU);
+ public static final Register r17 = new Register(17, 17, "l1", CPU);
+ public static final Register r18 = new Register(18, 18, "l2", CPU);
+ public static final Register r19 = new Register(19, 19, "l3", CPU);
+ public static final Register r20 = new Register(20, 20, "l4", CPU);
+ public static final Register r21 = new Register(21, 21, "l5", CPU);
+ public static final Register r22 = new Register(22, 22, "l6", CPU);
+ public static final Register r23 = new Register(23, 23, "l7", CPU);
+
+ public static final Register r24 = new Register(24, 24, "i0", CPU);
+ public static final Register r25 = new Register(25, 25, "i1", CPU);
+ public static final Register r26 = new Register(26, 26, "i2", CPU);
+ public static final Register r27 = new Register(27, 27, "i3", CPU);
+ public static final Register r28 = new Register(28, 28, "i4", CPU);
+ public static final Register r29 = new Register(29, 29, "i5", CPU);
+ public static final Register r30 = new Register(30, 30, "i6", CPU);
+ public static final Register r31 = new Register(31, 31, "i7", CPU);
+
+ public static final Register g0 = r0;
+ public static final Register g1 = r1;
+ public static final Register g2 = r2;
+ public static final Register g3 = r3;
+ public static final Register g4 = r4;
+ public static final Register g5 = r5;
+ public static final Register g6 = r6;
+ public static final Register g7 = r7;
+
+ public static final Register o0 = r8;
+ public static final Register o1 = r9;
+ public static final Register o2 = r10;
+ public static final Register o3 = r11;
+ public static final Register o4 = r12;
+ public static final Register o5 = r13;
+ public static final Register o6 = r14;
+ public static final Register o7 = r15;
+
+ public static final Register l0 = r16;
+ public static final Register l1 = r17;
+ public static final Register l2 = r18;
+ public static final Register l3 = r19;
+ public static final Register l4 = r20;
+ public static final Register l5 = r21;
+ public static final Register l6 = r22;
+ public static final Register l7 = r23;
+
+ public static final Register i0 = r24;
+ public static final Register i1 = r25;
+ public static final Register i2 = r26;
+ public static final Register i3 = r27;
+ public static final Register i4 = r28;
+ public static final Register i5 = r29;
+ public static final Register i6 = r30;
+ public static final Register i7 = r31;
+
+ public static final Register sp = o6;
+ public static final Register fp = i6;
+
+ // @formatter:off
+ public static final Register[] cpuRegisters = {
+ r0, r1, r2, r3, r4, r5, r6, r7,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ r16, r17, r18, r19, r20, r21, r22, r23,
+ r24, r25, r26, r27, r28, r29, r30, r31
+ };
+ // @formatter:on
+
+ public static final RegisterCategory FPUs = new RegisterCategory("FPUs", cpuRegisters.length);
+ public static final RegisterCategory FPUd = new RegisterCategory("FPUd", cpuRegisters.length + 32);
+
+ // Floating point registers
+ public static final Register f0 = new Register(32, 0, "f0", FPUs);
+ public static final Register f1 = new Register(33, 1, "f1", FPUs);
+ public static final Register f2 = new Register(34, 2, "f2", FPUs);
+ public static final Register f3 = new Register(35, 3, "f3", FPUs);
+ public static final Register f4 = new Register(36, 4, "f4", FPUs);
+ public static final Register f5 = new Register(37, 5, "f5", FPUs);
+ public static final Register f6 = new Register(38, 6, "f6", FPUs);
+ public static final Register f7 = new Register(39, 7, "f7", FPUs);
+
+ public static final Register f8 = new Register(40, 8, "f8", FPUs);
+ public static final Register f9 = new Register(41, 9, "f9", FPUs);
+ public static final Register f10 = new Register(42, 10, "f10", FPUs);
+ public static final Register f11 = new Register(43, 11, "f11", FPUs);
+ public static final Register f12 = new Register(44, 12, "f12", FPUs);
+ public static final Register f13 = new Register(45, 13, "f13", FPUs);
+ public static final Register f14 = new Register(46, 14, "f14", FPUs);
+ public static final Register f15 = new Register(47, 15, "f15", FPUs);
+
+ public static final Register f16 = new Register(48, 16, "f16", FPUs);
+ public static final Register f17 = new Register(49, 17, "f17", FPUs);
+ public static final Register f18 = new Register(50, 18, "f18", FPUs);
+ public static final Register f19 = new Register(51, 19, "f19", FPUs);
+ public static final Register f20 = new Register(52, 20, "f20", FPUs);
+ public static final Register f21 = new Register(53, 21, "f21", FPUs);
+ public static final Register f22 = new Register(54, 22, "f22", FPUs);
+ public static final Register f23 = new Register(55, 23, "f23", FPUs);
+
+ public static final Register f24 = new Register(56, 24, "f24", FPUs);
+ public static final Register f25 = new Register(57, 25, "f25", FPUs);
+ public static final Register f26 = new Register(58, 26, "f26", FPUs);
+ public static final Register f27 = new Register(59, 27, "f27", FPUs);
+ public static final Register f28 = new Register(60, 28, "f28", FPUs);
+ public static final Register f29 = new Register(61, 29, "f29", FPUs);
+ public static final Register f30 = new Register(62, 30, "f30", FPUs);
+ public static final Register f31 = new Register(63, 31, "f31", FPUs);
+
+ public static final Register d0 = new Register(32, getDoubleEncoding(0), "d0", FPUs);
+ public static final Register d2 = new Register(34, getDoubleEncoding(2), "d2", FPUs);
+ public static final Register d4 = new Register(36, getDoubleEncoding(4), "d4", FPUs);
+ public static final Register d6 = new Register(38, getDoubleEncoding(6), "d6", FPUs);
+ public static final Register d8 = new Register(40, getDoubleEncoding(8), "d8", FPUs);
+ public static final Register d10 = new Register(42, getDoubleEncoding(10), "d10", FPUs);
+ public static final Register d12 = new Register(44, getDoubleEncoding(12), "d12", FPUs);
+ public static final Register d14 = new Register(46, getDoubleEncoding(14), "d14", FPUs);
+
+ public static final Register d16 = new Register(48, getDoubleEncoding(16), "d16", FPUs);
+ public static final Register d18 = new Register(50, getDoubleEncoding(18), "d18", FPUs);
+ public static final Register d20 = new Register(52, getDoubleEncoding(20), "d20", FPUs);
+ public static final Register d22 = new Register(54, getDoubleEncoding(22), "d22", FPUs);
+ public static final Register d24 = new Register(56, getDoubleEncoding(24), "d24", FPUs);
+ public static final Register d26 = new Register(58, getDoubleEncoding(26), "d26", FPUs);
+ public static final Register d28 = new Register(60, getDoubleEncoding(28), "d28", FPUs);
+ public static final Register d30 = new Register(62, getDoubleEncoding(28), "d28", FPUs);
+
+ public static final Register d32 = new Register(64, getDoubleEncoding(32), "d32", FPUd);
+ public static final Register d34 = new Register(65, getDoubleEncoding(34), "d34", FPUd);
+ public static final Register d36 = new Register(66, getDoubleEncoding(36), "d36", FPUd);
+ public static final Register d38 = new Register(67, getDoubleEncoding(38), "d38", FPUd);
+ public static final Register d40 = new Register(68, getDoubleEncoding(40), "d40", FPUd);
+ public static final Register d42 = new Register(69, getDoubleEncoding(42), "d42", FPUd);
+ public static final Register d44 = new Register(70, getDoubleEncoding(44), "d44", FPUd);
+ public static final Register d46 = new Register(71, getDoubleEncoding(46), "d46", FPUd);
+
+ public static final Register d48 = new Register(72, getDoubleEncoding(48), "d48", FPUd);
+ public static final Register d50 = new Register(73, getDoubleEncoding(50), "d50", FPUd);
+ public static final Register d52 = new Register(74, getDoubleEncoding(52), "d52", FPUd);
+ public static final Register d54 = new Register(75, getDoubleEncoding(54), "d54", FPUd);
+ public static final Register d56 = new Register(76, getDoubleEncoding(56), "d56", FPUd);
+ public static final Register d58 = new Register(77, getDoubleEncoding(58), "d58", FPUd);
+ public static final Register d60 = new Register(78, getDoubleEncoding(60), "d60", FPUd);
+ public static final Register d62 = new Register(79, getDoubleEncoding(62), "d62", FPUd);
+
+ // @formatter:off
+ public static final Register[] fpuRegisters = {
+ f0, f1, f2, f3, f4, f5, f6, f7,
+ f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23,
+ f24, f25, f26, f27, f28, f29, f30, f31,
+ d32, d34, d36, d38, d40, d42, d44, d46,
+ d48, d50, d52, d54, d56, d58, d60, d62
+ };
+ // @formatter:on
+
+ // @formatter:off
+ public static final Register[] allRegisters = {
+ // CPU
+ r0, r1, r2, r3, r4, r5, r6, r7,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ r16, r17, r18, r19, r20, r21, r22, r23,
+ r24, r25, r26, r27, r28, r29, r30, r31,
+ // FPU
+ f0, f1, f2, f3, f4, f5, f6, f7,
+ f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23,
+ f24, f25, f26, f27, f28, f29, f30, f31,
+ d32, d34, d36, d38, d40, d42, d44, d46,
+ d48, d50, d52, d54, d56, d58, d60, d62
+ };
+ // @formatter:on
+
+ /**
+ * Stack bias for stack and frame pointer loads.
+ */
+ public static final int STACK_BIAS = 0x7ff;
+ /**
+ * In fact there are 64 single floating point registers, 32 of them could be accessed. TODO:
+ * Improve handling of these float registers
+ */
+ public static final int FLOAT_REGISTER_COUNT = 64;
+
+ /**
+ * Alignment for valid memory access.
+ */
+ public static final int MEMORY_ACCESS_ALIGN = 4;
+
+ public static final int INSTRUCTION_SIZE = 4;
+
+ /**
+ * Size to keep free for flushing the register-window to stack.
+ */
+ public static final int REGISTER_SAFE_AREA_SIZE = 128;
+
+ public final Set<CPUFeature> features;
+
+ public SPARC(Set<CPUFeature> features) {
+ super("SPARC", JavaKind.Long, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, r31.encoding + FLOAT_REGISTER_COUNT + 1, 8);
+ this.features = features;
+ }
+
+ @Override
+ public boolean canStoreValue(RegisterCategory category, PlatformKind lirKind) {
+ if (!(lirKind instanceof JavaKind)) {
+ return false;
+ }
+
+ JavaKind kind = (JavaKind) lirKind;
+ if (category.equals(CPU)) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ case Int:
+ case Long:
+ return true;
+ }
+ } else if (category.equals(FPUs) && kind.equals(JavaKind.Float)) {
+ return true;
+ } else if (category.equals(FPUd) && kind.equals(JavaKind.Double)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public PlatformKind getLargestStorableKind(RegisterCategory category) {
+ if (category.equals(CPU)) {
+ return JavaKind.Long;
+ } else if (category.equals(FPUd)) {
+ return JavaKind.Double;
+ } else if (category.equals(FPUs)) {
+ return JavaKind.Float;
+ } else {
+ return JavaKind.Illegal;
+ }
+ }
+
+ @Override
+ public PlatformKind getPlatformKind(JavaKind javaKind) {
+ if (javaKind.isObject()) {
+ return JavaKind.Long;
+ } else {
+ return javaKind;
+ }
+ }
+
+ public static int spillSlotSize(TargetDescription td, PlatformKind kind) {
+ return Math.max(td.getSizeInBytes(kind), MEMORY_ACCESS_ALIGN);
+ }
+
+ public static int getDoubleEncoding(int reg) {
+ assert reg < 64 && ((reg & 1) == 0);
+ // ignore v8 assertion for now
+ return (reg & 0x1e) | ((reg & 0x20) >> 5);
+ }
+
+ public static boolean isCPURegister(Register r) {
+ return r.getRegisterCategory().equals(CPU);
+ }
+
+ public static boolean isCPURegister(Register... regs) {
+ for (Register reg : regs) {
+ if (!isCPURegister(reg)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isGlobalRegister(Register r) {
+ return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
+ }
+
+ public static boolean isSingleFloatRegister(Register r) {
+ return r.name.startsWith("f");
+ }
+
+ public static boolean isDoubleFloatRegister(Register r) {
+ return r.name.startsWith("d");
+ }
+
+ public Set<CPUFeature> getFeatures() {
+ return features;
+ }
+
+ public boolean hasFeature(CPUFeature feature) {
+ return features.contains(feature);
+ }
+
+ public enum CPUFeature {
+ VIS1,
+ VIS2,
+ VIS3,
+ CBCOND,
+ BLOCK_ZEROING
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/aix/vm/vmStructs_aix.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef OS_AIX_VM_VMSTRUCTS_AIX_HPP
+#define OS_AIX_VM_VMSTRUCTS_AIX_HPP
+
+// These are the OS-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
+
+#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+
+#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
+
+#endif // OS_AIX_VM_VMSTRUCTS_AIX_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/bsd/vm/vmStructs_bsd.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef OS_BSD_VM_VMSTRUCTS_BSD_HPP
+#define OS_BSD_VM_VMSTRUCTS_BSD_HPP
+
+#include <dlfcn.h>
+
+// These are the OS-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
+
+#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+
+#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) \
+ declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT)
+
+#endif // OS_BSD_VM_VMSTRUCTS_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/linux/vm/vmStructs_linux.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef OS_LINUX_VM_VMSTRUCTS_LINUX_HPP
+#define OS_LINUX_VM_VMSTRUCTS_LINUX_HPP
+
+#include <dlfcn.h>
+
+// These are the OS-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
+
+#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+
+#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) \
+ declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT)
+
+#endif // OS_LINUX_VM_VMSTRUCTS_LINUX_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/solaris/vm/vmStructs_solaris.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef OS_SOLARIS_VM_VMSTRUCTS_SOLARIS_HPP
+#define OS_SOLARIS_VM_VMSTRUCTS_SOLARIS_HPP
+
+// These are the OS-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
+ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
+
+#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+ declare_unsigned_integer_type(OSThread::thread_id_t)
+
+#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
+
+#endif // OS_SOLARIS_VM_VMSTRUCTS_SOLARIS_HPP
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -2272,12 +2272,17 @@
#ifdef _M_AMD64
PCONTEXT ctx = exceptionInfo->ContextRecord;
address pc = (address)ctx->Rip;
- assert(pc[0] == 0xF7, "not an idiv opcode");
- assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");
- assert(ctx->Rax == min_jint, "unexpected idiv exception");
- // set correct result values and continue after idiv instruction
- ctx->Rip = (DWORD)pc + 2; // idiv reg, reg is 2 bytes
- ctx->Rax = (DWORD)min_jint; // result
+ assert(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && pc[1] == 0xF7 || pc[0] == 0xF7, "not an idiv opcode");
+ assert(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && (pc[2] & ~0x7) == 0xF8 || (pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");
+ if (pc[0] == 0xF7) {
+ // set correct result values and continue after idiv instruction
+ ctx->Rip = (DWORD64)pc + 2; // idiv reg, reg is 2 bytes
+ } else {
+ ctx->Rip = (DWORD64)pc + 3; // REX idiv reg, reg is 3 bytes
+ }
+ // Do not set ctx->Rax as it already contains the correct value (either 32 or 64 bit, depending on the operation)
+ // this is the case because the exception only happens for -MinValue/-1 and -MinValue is always in rax because of the
+ // idiv opcode (0xF7).
ctx->Rdx = (DWORD)0; // remainder
// Continue the execution
#else
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/vm/vmStructs_windows.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef OS_WINDOWS_VM_VMSTRUCTS_WINDOWS_HPP
+#define OS_WINDOWS_VM_VMSTRUCTS_WINDOWS_HPP
+
+// These are the OS-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
+
+#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+
+#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
+
+#endif // OS_WINDOWS_VM_VMSTRUCTS_WINDOWS_HPP
--- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -66,8 +66,8 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
- // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ // C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
// nothing else to try if the frame isn't good
@@ -77,7 +77,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
}
*fr_addr = ret_frame;
return true;
--- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -67,8 +67,8 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
- // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ // C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
// nothing else to try if the frame isn't good
@@ -78,7 +78,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
}
*fr_addr = ret_frame;
return true;
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -24,6 +24,7 @@
// no precompiled headers
#include "asm/macroAssembler.hpp"
+#include "macroAssembler_sparc.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -30,29 +30,11 @@
// referenced by vmStructs.cpp.
#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
- \
- /******************************/ \
- /* Threads (NOTE: incomplete) */ \
- /******************************/ \
- \
- nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \
- nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
+ nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*)
-#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
- \
- /**********************/ \
- /* Solaris Thread IDs */ \
- /**********************/ \
- \
- declare_unsigned_integer_type(OSThread::thread_id_t)
-
+#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
- \
- /************************/ \
- /* JavaThread constants */ \
- /************************/ \
- \
declare_constant(JavaFrameAnchor::flushed)
#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
--- a/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -29,21 +29,9 @@
// constants required by the Serviceability Agent. This file is
// referenced by vmStructs.cpp.
-#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
- \
- /******************************/ \
- /* Threads (NOTE: incomplete) */ \
- /******************************/ \
- \
- nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
+#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
-#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
- \
- /**********************/ \
- /* Solaris Thread IDs */ \
- /**********************/ \
- \
- declare_unsigned_integer_type(OSThread::thread_id_t)
+#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
--- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -74,8 +74,8 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
- // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ // C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
// nothing else to try if the frame isn't good
@@ -85,7 +85,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
}
*fr_addr = ret_frame;
return true;
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -602,21 +602,19 @@
return (csize_t) align_size_up(total, HeapWordSize);
}
-csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const {
- address buf = NULL;
+csize_t CodeBuffer::copy_relocations_to(address buf, csize_t buf_limit, bool only_inst) const {
csize_t buf_offset = 0;
- csize_t buf_limit = 0;
- if (dest != NULL) {
- buf = (address)dest->relocation_begin();
- buf_limit = (address)dest->relocation_end() - buf;
- assert((uintptr_t)buf % HeapWordSize == 0, "buf must be fully aligned");
- assert(buf_limit % HeapWordSize == 0, "buf must be evenly sized");
- }
- // if dest == NULL, this is just the sizing pass
-
csize_t code_end_so_far = 0;
csize_t code_point_so_far = 0;
+
+ assert((uintptr_t)buf % HeapWordSize == 0, "buf must be fully aligned");
+ assert(buf_limit % HeapWordSize == 0, "buf must be evenly sized");
+
for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) {
+ if (only_inst && (n != (int)SECT_INSTS)) {
+ // Need only relocation info for code.
+ continue;
+ }
// pull relocs out of each section
const CodeSection* cs = code_section(n);
assert(!(cs->is_empty() && cs->locs_count() > 0), "sanity");
@@ -683,7 +681,23 @@
buf_offset += sizeof(relocInfo);
}
- assert(code_end_so_far == total_content_size(), "sanity");
+ assert(only_inst || code_end_so_far == total_content_size(), "sanity");
+
+ return buf_offset;
+}
+
+csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const {
+ address buf = NULL;
+ csize_t buf_offset = 0;
+ csize_t buf_limit = 0;
+
+ if (dest != NULL) {
+ buf = (address)dest->relocation_begin();
+ buf_limit = (address)dest->relocation_end() - buf;
+ }
+ // if dest == NULL, this is just the sizing pass
+ //
+ buf_offset = copy_relocations_to(buf, buf_limit, false);
// Account for index:
if (buf != NULL) {
@@ -1126,7 +1140,8 @@
while (c && c->offset() == offset) {
stream->bol();
stream->print("%s", _prefix);
- stream->print_cr("%s", c->string());
+ // Don't interpret as format strings since it could contain %
+ stream->print_raw_cr(c->string());
c = c->next_comment();
}
}
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -452,7 +452,6 @@
initialize_misc(name);
}
-
// (4) code buffer allocating codeBlob memory for code & relocation
// info. The name must be something informative and code_size must
// include both code and stubs sizes.
@@ -553,6 +552,8 @@
// allocated size of all relocation data, including index, rounded up
csize_t total_relocation_size() const;
+ csize_t copy_relocations_to(address buf, csize_t buf_limit, bool only_inst) const;
+
// allocated size of any and all recorded oops
csize_t total_oop_size() const {
OopRecorder* recorder = oop_recorder();
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -325,7 +325,8 @@
locs_buffer_size / sizeof(relocInfo));
code->initialize_consts_size(Compilation::desired_max_constant_size());
// Call stubs + two deopt handlers (regular and MH) + exception handler
- int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size) +
+ int call_stub_size = LIR_Assembler::call_stub_size;
+ int stub_size = (call_stub_estimate * call_stub_size) +
LIR_Assembler::exception_handler_size +
(2 * LIR_Assembler::deopt_handler_size);
if (stub_size >= code->insts_capacity()) return false;
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -244,7 +244,8 @@
// reexecute allowed only for the topmost frame
bool reexecute = topmost ? should_reexecute() : false;
bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
- recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+ bool rethrow_exception = false;
+ recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), reexecute, rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
}
};
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -405,7 +405,8 @@
if (s == NULL) break;
IRScope* scope = s->scope();
//Always pass false for reexecute since these ScopeDescs are never used for deopt
- debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/);
+ methodHandle null_mh;
+ debug_info->describe_scope(pc_offset, null_mh, scope->method(), s->bci(), false/*reexecute*/);
}
debug_info->end_non_safepoint(pc_offset);
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1755,6 +1755,12 @@
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
return _method_HotSpotIntrinsicCandidate;
+#if INCLUDE_JVMCI
+ case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_vm_ci_hotspot_Stable_signature):
+ if (_location != _in_field) break; // only allow for fields
+ if (!privileged) break; // only allow in privileged code
+ return _field_Stable;
+#endif
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature):
if (_location != _in_field) break; // only allow for fields
if (!privileged) break; // only allow in privileged code
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -53,6 +53,10 @@
#include "runtime/vframe.hpp"
#include "utilities/preserveException.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
+
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \
@@ -1579,7 +1583,7 @@
while (h_throwable.not_null()) {
objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable())));
if (result.is_null()) {
- st->print_cr("%s", no_stack_trace_message());
+ st->print_raw_cr(no_stack_trace_message());
return;
}
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -157,7 +157,12 @@
if (count_offset > 0) {
return java_string->int_field(count_offset);
} else {
- return ((typeArrayOop)java_string->obj_field(value_offset))->length();
+ typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
+ if (value_array == NULL) {
+ return 0;
+ } else {
+ return value_array->length();
+ }
}
}
static int utf8_length(oop java_string);
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -32,6 +32,9 @@
#include "runtime/thread.hpp"
#include "services/threadService.hpp"
#include "utilities/chunkedList.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
@@ -57,6 +60,9 @@
CompileBroker::mark_on_stack();
JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
ThreadService::metadata_do(Metadata::mark_on_stack);
+#if INCLUDE_JVMCI
+ JVMCIRuntime::metadata_do(Metadata::mark_on_stack);
+#endif
}
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -66,6 +66,9 @@
#include "classfile/sharedClassUtil.hpp"
#include "classfile/systemDictionaryShared.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
#if INCLUDE_TRACE
#include "trace/tracing.hpp"
#endif
@@ -228,7 +231,7 @@
// Forwards to resolve_instance_class_or_null
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
- assert(!THREAD->is_Compiler_thread(),
+ assert(THREAD->can_call_java(),
err_msg("can not load classes with compiler thread: class=%s, classloader=%s",
class_name->as_C_string(),
class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string()));
@@ -1917,7 +1920,7 @@
WKID jsr292_group_end = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
initialize_wk_klasses_until(jsr292_group_start, scan, CHECK);
initialize_wk_klasses_through(jsr292_group_end, scan, CHECK);
- initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
+ initialize_wk_klasses_until(NOT_JVMCI(WKID_LIMIT) JVMCI_ONLY(FIRST_JVMCI_WKID), scan, CHECK);
_box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
_box_klasses[T_CHAR] = WK_KLASS(Character_klass);
@@ -2343,7 +2346,7 @@
Handle *method_type_result,
TRAPS) {
methodHandle empty;
- assert(!THREAD->is_Compiler_thread(), "");
+ assert(THREAD->can_call_java() ,"");
Handle method_type =
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));
@@ -2411,7 +2414,7 @@
if (spe != NULL && spe->method_type() != NULL) {
assert(java_lang_invoke_MethodType::is_instance(spe->method_type()), "");
return Handle(THREAD, spe->method_type());
- } else if (THREAD->is_Compiler_thread()) {
+ } else if (!THREAD->can_call_java()) {
warning("SystemDictionary::find_method_handle_type called from compiler thread"); // FIXME
return Handle(); // do not attempt from within compiler, unless it was cached
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -33,6 +33,7 @@
#include "runtime/reflectionUtils.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/hashtable.inline.hpp"
+#include "jvmci/systemDictionary_jvmci.hpp"
// The system dictionary stores all loaded classes and maps:
@@ -192,6 +193,10 @@
do_klass(Short_klass, java_lang_Short, Pre ) \
do_klass(Integer_klass, java_lang_Integer, Pre ) \
do_klass(Long_klass, java_lang_Long, Pre ) \
+ \
+ /* JVMCI classes. These are loaded on-demand. */ \
+ JVMCI_WK_KLASSES_DO(do_klass) \
+
/*end*/
@@ -209,6 +214,11 @@
WKID_LIMIT,
+#if INCLUDE_JVMCI
+ FIRST_JVMCI_WKID = WK_KLASS_ENUM_NAME(HotSpotCompiledCode_klass),
+ LAST_JVMCI_WKID = WK_KLASS_ENUM_NAME(Value_klass),
+#endif
+
FIRST_WKID = NO_WKID + 1
};
@@ -219,6 +229,9 @@
// Options after this point will use resolve_or_null instead.
Opt, // preload tried; NULL if not present
+#if INCLUDE_JVMCI
+ Jvmci, // preload tried; error if not present, use only with JVMCI
+#endif
OPTION_LIMIT,
CEIL_LG_OPTION_LIMIT = 2 // OPTION_LIMIT <= (1<<CEIL_LG_OPTION_LIMIT)
};
@@ -398,6 +411,8 @@
static Klass* check_klass_Pre( Klass* k) { return check_klass(k); }
static Klass* check_klass_Opt( Klass* k) { return k; }
+ JVMCI_ONLY(static Klass* check_klass_Jvmci(Klass* k) { return k; })
+
static bool initialize_wk_klass(WKID id, int init_opt, TRAPS);
static void initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS);
static void initialize_wk_klasses_through(WKID end_id, WKID &start_id, TRAPS) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -28,6 +28,7 @@
#include "oops/symbol.hpp"
#include "memory/iterator.hpp"
#include "trace/traceMacros.hpp"
+#include "jvmci/vmSymbols_jvmci.hpp"
// The class vmSymbols is a name space for fast lookup of
// symbols commonly used in the VM.
@@ -44,7 +45,6 @@
#define VM_SYMBOL_IGNORE(id, name) /*ignored*/
#define VM_ALIAS_IGNORE(id, id2) /*ignored*/
-
// Mapping function names to values. New entries should be added below.
#define VM_SYMBOLS_DO(template, do_alias) \
@@ -300,6 +300,9 @@
template(DEFAULT_CONTEXT_name, "DEFAULT_CONTEXT") \
NOT_LP64( do_alias(intptr_signature, int_signature) ) \
LP64_ONLY( do_alias(intptr_signature, long_signature) ) \
+ \
+ /* Support for JVMCI */ \
+ JVMCI_VM_SYMBOLS_DO(template, do_alias) \
\
/* common method and field names */ \
template(object_initializer_name, "<init>") \
@@ -382,6 +385,7 @@
template(bitCount_name, "bitCount") \
template(profile_name, "profile") \
template(equals_name, "equals") \
+ template(length_name, "length") \
template(target_name, "target") \
template(toString_name, "toString") \
template(values_name, "values") \
@@ -432,6 +436,7 @@
template(void_long_signature, "()J") \
template(void_float_signature, "()F") \
template(void_double_signature, "()D") \
+ template(bool_void_signature, "(Z)V") \
template(int_void_signature, "(I)V") \
template(int_int_signature, "(I)I") \
template(char_char_signature, "(C)C") \
--- a/hotspot/src/share/vm/code/codeBlob.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/codeBlob.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -120,6 +120,7 @@
virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() const { return false; }
+ virtual bool is_compiled_by_jvmci() const { return false; }
// Casting
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
@@ -380,6 +381,12 @@
int _unpack_with_exception_in_tls;
+#if INCLUDE_JVMCI
+ // Offsets when JVMCI calls uncommon_trap.
+ int _uncommon_trap_offset;
+ int _implicit_exception_uncommon_trap_offset;
+#endif
+
// Creation support
DeoptimizationBlob(
CodeBuffer* cb,
@@ -429,6 +436,21 @@
assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");
}
address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; }
+
+#if INCLUDE_JVMCI
+ // Offsets when JVMCI calls uncommon_trap.
+ void set_uncommon_trap_offset(int offset) {
+ _uncommon_trap_offset = offset;
+ assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob");
+ }
+ address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; }
+
+ void set_implicit_exception_uncommon_trap_offset(int offset) {
+ _implicit_exception_uncommon_trap_offset = offset;
+ assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");
+ }
+ address implicit_exception_uncommon_trap() const { return code_begin() + _implicit_exception_uncommon_trap_offset; }
+#endif // INCLUDE_JVMCI
};
--- a/hotspot/src/share/vm/code/compiledIC.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/compiledIC.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -280,11 +280,13 @@
bool is_monomorphic = (cb != NULL && cb->is_nmethod());
// Check that the cached_value is a klass for non-optimized monomorphic calls
// This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used
- // for calling directly to vep without using the inline cache (i.e., cached_value == NULL)
+ // for calling directly to vep without using the inline cache (i.e., cached_value == NULL).
+ // For JVMCI this occurs because CHA is only used to improve inlining so call sites which could be optimized
+ // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites.
#ifdef ASSERT
CodeBlob* caller = CodeCache::find_blob_unsafe(instruction_address());
- bool is_c1_method = caller->is_compiled_by_c1();
- assert( is_c1_method ||
+ bool is_c1_or_jvmci_method = caller->is_compiled_by_c1() || caller->is_compiled_by_jvmci();
+ assert( is_c1_or_jvmci_method ||
!is_monomorphic ||
is_optimized() ||
!caller->is_alive() ||
--- a/hotspot/src/share/vm/code/compiledIC.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/compiledIC.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -306,7 +306,7 @@
friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
// Code
- static address emit_to_interp_stub(CodeBuffer &cbuf);
+ static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL);
static int to_interp_stub_size();
static int reloc_to_interp_stub();
--- a/hotspot/src/share/vm/code/debugInfo.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/debugInfo.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -59,7 +59,7 @@
#ifdef ASSERT
assert(_obj_pool != NULL, "object pool does not exist");
for (int i = _obj_pool->length() - 1; i >= 0; i--) {
- assert(((ObjectValue*) _obj_pool->at(i))->id() != id, "should not be read twice");
+ assert(_obj_pool->at(i)->as_ObjectValue()->id() != id, "should not be read twice");
}
#endif
ObjectValue* result = new ObjectValue(id);
@@ -73,7 +73,7 @@
int id = read_int();
assert(_obj_pool != NULL, "object pool does not exist");
for (int i = _obj_pool->length() - 1; i >= 0; i--) {
- ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
+ ObjectValue* ov = _obj_pool->at(i)->as_ObjectValue();
if (ov->id() == id) {
return ov;
}
--- a/hotspot/src/share/vm/code/debugInfo.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/debugInfo.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -41,6 +41,7 @@
// - ConstantValue describes a constant
class ConstantOopReadValue;
+class ObjectValue;
class ScopeValue: public ResourceObj {
public:
@@ -58,6 +59,11 @@
return (ConstantOopReadValue*) this;
}
+ ObjectValue* as_ObjectValue() {
+ assert(is_object(), "must be");
+ return (ObjectValue*)this;
+ }
+
// Serialization of debugging information
virtual void write_on(DebugInfoWriteStream* stream) = 0;
static ScopeValue* read_from(DebugInfoReadStream* stream);
--- a/hotspot/src/share/vm/code/debugInfoRec.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/debugInfoRec.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,6 +37,9 @@
int _offset; // location in the stream of this scope
int _length; // number of bytes in the stream
int _hash; // hash of stream bytes (for quicker reuse)
+#if INCLUDE_JVMCI
+ DebugInformationRecorder* _DIR;
+#endif
void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() {
assert(ignore == sizeof(DIR_Chunk), "");
@@ -51,6 +54,9 @@
DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) {
_offset = offset;
_length = length;
+#if INCLUDE_JVMCI
+ _DIR = dir;
+#endif
unsigned int hash = 0;
address p = dir->stream()->buffer() + _offset;
for (int i = 0; i < length; i++) {
@@ -77,6 +83,25 @@
}
return NULL;
}
+
+#if INCLUDE_JVMCI
+ static int compare(DIR_Chunk* const & a, DIR_Chunk* const & b) {
+ if (b->_hash > a->_hash) {
+ return 1;
+ }
+ if (b->_hash < a->_hash) {
+ return -1;
+ }
+ if (b->_length > a->_length) {
+ return 1;
+ }
+ if (b->_length < a->_length) {
+ return -1;
+ }
+ address buf = a->_DIR->stream()->buffer();
+ return memcmp(buf + b->_offset, buf + a->_offset, a->_length);
+ }
+#endif
};
static inline bool compute_recording_non_safepoints() {
@@ -113,7 +138,9 @@
_oop_recorder = oop_recorder;
_all_chunks = new GrowableArray<DIR_Chunk*>(300);
+#if !INCLUDE_JVMCI
_shared_chunks = new GrowableArray<DIR_Chunk*>(30);
+#endif
_next_chunk = _next_chunk_limit = NULL;
add_new_pc_offset(PcDesc::lower_offset_limit); // sentinel record
@@ -235,10 +262,13 @@
int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) {
+#if !INCLUDE_JVMCI
// Only pull this trick if non-safepoint recording
// is enabled, for now.
- if (!recording_non_safepoints())
+ if (!recording_non_safepoints()) {
return serialized_null;
+ }
+#endif // INCLUDE_JVMCI
NOT_PRODUCT(++dir_stats.chunks_queried);
int stream_length = stream()->position() - stream_offset;
@@ -247,6 +277,19 @@
DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this);
+#if INCLUDE_JVMCI
+ DIR_Chunk* match = _all_chunks->insert_sorted<DIR_Chunk::compare>(ns);
+ if (match != ns) {
+ // Found an existing chunk
+ NOT_PRODUCT(++dir_stats.chunks_shared);
+ assert(ns+1 == _next_chunk, "");
+ _next_chunk = ns;
+ return match->_offset;
+ } else {
+ // Inserted this chunk, so nothing to do
+ return serialized_null;
+ }
+#else // INCLUDE_JVMCI
// Look in previously shared scopes first:
DIR_Chunk* ms = ns->find_match(_shared_chunks, 0, this);
if (ms != NULL) {
@@ -274,15 +317,18 @@
// No match. Add this guy to the list, in hopes of future shares.
_all_chunks->append(ns);
return serialized_null;
+#endif // INCLUDE_JVMCI
}
// must call add_safepoint before: it sets PcDesc and this routine uses
// the last PcDesc set
void DebugInformationRecorder::describe_scope(int pc_offset,
+ methodHandle methodH,
ciMethod* method,
int bci,
bool reexecute,
+ bool rethrow_exception,
bool is_method_handle_invoke,
bool return_oop,
DebugToken* locals,
@@ -298,6 +344,7 @@
// Record flags into pcDesc.
last_pd->set_should_reexecute(reexecute);
+ last_pd->set_rethrow_exception(rethrow_exception);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
last_pd->set_return_oop(return_oop);
@@ -305,8 +352,16 @@
stream()->write_int(sender_stream_offset);
// serialize scope
- Metadata* method_enc = (method == NULL)? NULL: method->constant_encoding();
- stream()->write_int(oop_recorder()->find_index(method_enc));
+ Metadata* method_enc;
+ if (method != NULL) {
+ method_enc = method->constant_encoding();
+ } else if (methodH.not_null()) {
+ method_enc = methodH();
+ } else {
+ method_enc = NULL;
+ }
+ int method_enc_index = oop_recorder()->find_index(method_enc);
+ stream()->write_int(method_enc_index);
stream()->write_bci(bci);
assert(method == NULL ||
(method->is_native() && bci == 0) ||
@@ -338,7 +393,7 @@
PcDesc* last_pd = &_pcs[_pcs_length-1];
if (objects != NULL) {
for (int i = objects->length() - 1; i >= 0; i--) {
- ((ObjectValue*) objects->at(i))->set_visited(false);
+ objects->at(i)->as_ObjectValue()->set_visited(false);
}
}
int offset = serialize_scope_values(objects);
--- a/hotspot/src/share/vm/code/debugInfoRec.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/debugInfoRec.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -98,9 +98,11 @@
// by add_non_safepoint, and the locals, expressions, and monitors
// must all be null.
void describe_scope(int pc_offset,
+ methodHandle methodH,
ciMethod* method,
int bci,
bool reexecute,
+ bool rethrow_exception = false,
bool is_method_handle_invoke = false,
bool return_oop = false,
DebugToken* locals = NULL,
@@ -143,6 +145,12 @@
bool recording_non_safepoints() { return _recording_non_safepoints; }
+ PcDesc* pcs() const { return _pcs; }
+ int pcs_length() const { return _pcs_length; }
+
+ DebugInfoWriteStream* stream() const { return _stream; }
+
+
private:
friend class ScopeDesc;
friend class vframeStreamCommon;
@@ -155,13 +163,13 @@
DebugInfoWriteStream* _stream;
- DebugInfoWriteStream* stream() const { return _stream; }
-
OopRecorder* _oop_recorder;
// Scopes that have been described so far.
GrowableArray<DIR_Chunk*>* _all_chunks;
+#if !INCLUDE_JVMCI
GrowableArray<DIR_Chunk*>* _shared_chunks;
+#endif
DIR_Chunk* _next_chunk;
DIR_Chunk* _next_chunk_limit;
--- a/hotspot/src/share/vm/code/dependencies.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/dependencies.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -31,6 +31,7 @@
#include "code/dependencies.hpp"
#include "compiler/compileLog.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/objArrayKlass.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/thread.inline.hpp"
@@ -52,6 +53,9 @@
_oop_recorder = env->oop_recorder();
_log = env->log();
_dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
+#if INCLUDE_JVMCI
+ _using_dep_values = false;
+#endif
DEBUG_ONLY(_deps[end_marker] = NULL);
for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
_deps[i] = new(arena) GrowableArray<ciBaseObject*>(arena, 10, 0, 0);
@@ -120,6 +124,66 @@
assert_common_2(call_site_target_value, call_site, method_handle);
}
+#if INCLUDE_JVMCI
+
+Dependencies::Dependencies(Arena* arena, OopRecorder* oop_recorder, CompileLog* log) {
+ _oop_recorder = oop_recorder;
+ _log = log;
+ _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
+ _using_dep_values = true;
+ DEBUG_ONLY(_dep_values[end_marker] = NULL);
+ for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
+ _dep_values[i] = new(arena) GrowableArray<DepValue>(arena, 10, 0, DepValue());
+ }
+ _content_bytes = NULL;
+ _size_in_bytes = (size_t)-1;
+
+ assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT), "sanity");
+}
+
+void Dependencies::assert_evol_method(Method* m) {
+ assert_common_1(evol_method, DepValue(_oop_recorder, m));
+}
+
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
+ check_ctxk(ctxk);
+ assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
+}
+
+void Dependencies::assert_leaf_type(Klass* ctxk) {
+ if (ctxk->oop_is_array()) {
+ // As a special case, support this assertion on an array type,
+ // which reduces to an assertion on its element type.
+ // Note that this cannot be done with assertions that
+ // relate to concreteness or abstractness.
+ BasicType elemt = ArrayKlass::cast(ctxk)->element_type();
+ if (is_java_primitive(elemt)) return; // Ex: int[][]
+ ctxk = ObjArrayKlass::cast(ctxk)->bottom_klass();
+ //if (ctxk->is_final()) return; // Ex: String[][]
+ }
+ check_ctxk(ctxk);
+ assert_common_1(leaf_type, DepValue(_oop_recorder, ctxk));
+}
+
+void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck) {
+ check_ctxk_abstract(ctxk);
+ DepValue ctxk_dv(_oop_recorder, ctxk);
+ DepValue conck_dv(_oop_recorder, conck, &ctxk_dv);
+ assert_common_2(abstract_with_unique_concrete_subtype, ctxk_dv, conck_dv);
+}
+
+void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) {
+ check_ctxk(ctxk);
+ assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
+}
+
+void Dependencies::assert_call_site_target_value(oop call_site, oop method_handle) {
+ assert_common_2(call_site_target_value, DepValue(_oop_recorder, JNIHandles::make_local(call_site)), DepValue(_oop_recorder, JNIHandles::make_local(method_handle)));
+}
+
+#endif // INCLUDE_JVMCI
+
+
// Helper function. If we are adding a new dep. under ctxk2,
// try to find an old dep. under a broader* ctxk1. If there is
//
@@ -230,6 +294,78 @@
deps->append(x2);
}
+#if INCLUDE_JVMCI
+bool Dependencies::maybe_merge_ctxk(GrowableArray<DepValue>* deps,
+ int ctxk_i, DepValue ctxk2_dv) {
+ Klass* ctxk1 = deps->at(ctxk_i).as_klass(_oop_recorder);
+ Klass* ctxk2 = ctxk2_dv.as_klass(_oop_recorder);
+ if (ctxk2->is_subtype_of(ctxk1)) {
+ return true; // success, and no need to change
+ } else if (ctxk1->is_subtype_of(ctxk2)) {
+ // new context class fully subsumes previous one
+ deps->at_put(ctxk_i, ctxk2_dv);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Dependencies::assert_common_1(DepType dept, DepValue x) {
+ assert(dep_args(dept) == 1, "sanity");
+ //log_dependency(dept, x);
+ GrowableArray<DepValue>* deps = _dep_values[dept];
+
+ // see if the same (or a similar) dep is already recorded
+ if (note_dep_seen(dept, x)) {
+ assert(deps->find(x) >= 0, "sanity");
+ } else {
+ deps->append(x);
+ }
+}
+
+void Dependencies::assert_common_2(DepType dept,
+ DepValue x0, DepValue x1) {
+ assert(dep_args(dept) == 2, "sanity");
+ //log_dependency(dept, x0, x1);
+ GrowableArray<DepValue>* deps = _dep_values[dept];
+
+ // see if the same (or a similar) dep is already recorded
+ bool has_ctxk = has_explicit_context_arg(dept);
+ if (has_ctxk) {
+ assert(dep_context_arg(dept) == 0, "sanity");
+ if (note_dep_seen(dept, x1)) {
+ // look in this bucket for redundant assertions
+ const int stride = 2;
+ for (int i = deps->length(); (i -= stride) >= 0; ) {
+ DepValue y1 = deps->at(i+1);
+ if (x1 == y1) { // same subject; check the context
+ if (maybe_merge_ctxk(deps, i+0, x0)) {
+ return;
+ }
+ }
+ }
+ }
+ } else {
+ assert(dep_implicit_context_arg(dept) == 0, "sanity");
+ if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
+ // look in this bucket for redundant assertions
+ const int stride = 2;
+ for (int i = deps->length(); (i -= stride) >= 0; ) {
+ DepValue y0 = deps->at(i+0);
+ DepValue y1 = deps->at(i+1);
+ if (x0 == y0 && x1 == y1) {
+ return;
+ }
+ }
+ }
+ }
+
+ // append the assertion in the correct bucket:
+ deps->append(x0);
+ deps->append(x1);
+}
+#endif // INCLUDE_JVMCI
+
/// Support for encoding dependencies into an nmethod:
void Dependencies::copy_to(nmethod* nm) {
@@ -256,7 +392,40 @@
static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** p2)
{ return sort_dep(p1, p2, 3); }
+#if INCLUDE_JVMCI
+// metadata deps are sorted before object deps
+static int sort_dep_value(Dependencies::DepValue* p1, Dependencies::DepValue* p2, int narg) {
+ for (int i = 0; i < narg; i++) {
+ int diff = p1[i].sort_key() - p2[i].sort_key();
+ if (diff != 0) return diff;
+ }
+ return 0;
+}
+static int sort_dep_value_arg_1(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 1); }
+static int sort_dep_value_arg_2(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 2); }
+static int sort_dep_value_arg_3(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 3); }
+#endif // INCLUDE_JVMCI
+
void Dependencies::sort_all_deps() {
+#if INCLUDE_JVMCI
+ if (_using_dep_values) {
+ for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+ DepType dept = (DepType)deptv;
+ GrowableArray<DepValue>* deps = _dep_values[dept];
+ if (deps->length() <= 1) continue;
+ switch (dep_args(dept)) {
+ case 1: deps->sort(sort_dep_value_arg_1, 1); break;
+ case 2: deps->sort(sort_dep_value_arg_2, 2); break;
+ case 3: deps->sort(sort_dep_value_arg_3, 3); break;
+ default: ShouldNotReachHere();
+ }
+ }
+ return;
+ }
+#endif // INCLUDE_JVMCI
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -272,6 +441,16 @@
size_t Dependencies::estimate_size_in_bytes() {
size_t est_size = 100;
+#if INCLUDE_JVMCI
+ if (_using_dep_values) {
+ for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+ DepType dept = (DepType)deptv;
+ GrowableArray<DepValue>* deps = _dep_values[dept];
+ est_size += deps->length() * 2; // tags and argument(s)
+ }
+ return est_size;
+ }
+#endif // INCLUDE_JVMCI
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -311,6 +490,37 @@
// cast is safe, no deps can overflow INT_MAX
CompressedWriteStream bytes((int)estimate_size_in_bytes());
+#if INCLUDE_JVMCI
+ if (_using_dep_values) {
+ for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+ DepType dept = (DepType)deptv;
+ GrowableArray<DepValue>* deps = _dep_values[dept];
+ if (deps->length() == 0) continue;
+ int stride = dep_args(dept);
+ int ctxkj = dep_context_arg(dept); // -1 if no context arg
+ assert(stride > 0, "sanity");
+ for (int i = 0; i < deps->length(); i += stride) {
+ jbyte code_byte = (jbyte)dept;
+ int skipj = -1;
+ if (ctxkj >= 0 && ctxkj+1 < stride) {
+ Klass* ctxk = deps->at(i+ctxkj+0).as_klass(_oop_recorder);
+ DepValue x = deps->at(i+ctxkj+1); // following argument
+ if (ctxk == ctxk_encoded_as_null(dept, x.as_metadata(_oop_recorder))) {
+ skipj = ctxkj; // we win: maybe one less oop to keep track of
+ code_byte |= default_context_type_bit;
+ }
+ }
+ bytes.write_byte(code_byte);
+ for (int j = 0; j < stride; j++) {
+ if (j == skipj) continue;
+ DepValue v = deps->at(i+j);
+ int idx = v.index();
+ bytes.write_int(idx);
+ }
+ }
+ }
+ } else {
+#endif // INCLUDE_JVMCI
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -344,6 +554,9 @@
}
}
}
+#if INCLUDE_JVMCI
+ }
+#endif
// write a sentinel byte to mark the end
bytes.write_byte(end_marker);
@@ -540,10 +753,10 @@
}
void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args,
- Klass* witness) {
+ Klass* witness, outputStream* st) {
ResourceMark rm;
ttyLocker ttyl; // keep the following output all in one block
- tty->print_cr("%s of type %s",
+ st->print_cr("%s of type %s",
(witness == NULL)? "Dependency": "Failed dependency",
dep_name(dept));
// print arguments
@@ -565,22 +778,22 @@
} else {
what = "object ";
}
- tty->print(" %s = %s", what, (put_star? "*": ""));
+ st->print(" %s = %s", what, (put_star? "*": ""));
if (arg.is_klass()) {
- tty->print("%s", ((Klass*)arg.metadata_value())->external_name());
+ st->print("%s", ((Klass*)arg.metadata_value())->external_name());
} else if (arg.is_method()) {
- ((Method*)arg.metadata_value())->print_value();
+ ((Method*)arg.metadata_value())->print_value_on(st);
} else if (arg.is_oop()) {
- arg.oop_value()->print_value_on(tty);
+ arg.oop_value()->print_value_on(st);
} else {
ShouldNotReachHere(); // Provide impl for this type.
}
- tty->cr();
+ st->cr();
}
if (witness != NULL) {
bool put_star = !Dependencies::is_concrete_klass(witness);
- tty->print_cr(" witness = %s%s",
+ st->print_cr(" witness = %s%s",
(put_star? "*": ""),
witness->external_name());
}
@@ -600,14 +813,19 @@
}
int argslen = args->length();
if (_deps != NULL && _deps->log() != NULL) {
- Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
+ if (ciEnv::current() != NULL) {
+ Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
+ } else {
+ // Treat the CompileLog as an xmlstream instead
+ Dependencies::write_dependency_to((xmlStream*)_deps->log(), type(), args, witness);
+ }
} else {
Dependencies::write_dependency_to(xtty, type(), args, witness);
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
}
-void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
+void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose, outputStream* st) {
ResourceMark rm;
int nargs = argument_count();
GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
@@ -619,12 +837,12 @@
}
}
int argslen = args->length();
- Dependencies::print_dependency(type(), args, witness);
+ Dependencies::print_dependency(type(), args, witness, st);
if (verbose) {
if (_code != NULL) {
- tty->print(" code: ");
- _code->print_value_on(tty);
- tty->cr();
+ st->print(" code: ");
+ _code->print_value_on(st);
+ st->cr();
}
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
--- a/hotspot/src/share/vm/code/dependencies.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/dependencies.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -202,10 +202,59 @@
static void check_valid_dependency_type(DepType dept);
+#if INCLUDE_JVMCI
+ // A Metadata* or object value recorded in an OopRecorder
+ class DepValue VALUE_OBJ_CLASS_SPEC {
+ private:
+ // Unique identifier of the value within the associated OopRecorder that
+ // encodes both the category of the value (0: invalid, positive: metadata, negative: object)
+ // and the index within a category specific array (metadata: index + 1, object: -(index + 1))
+ int _id;
+
+ public:
+ DepValue() : _id(0) {}
+ DepValue(OopRecorder* rec, Metadata* metadata, DepValue* candidate = NULL) {
+ assert(candidate == NULL || candidate->is_metadata(), "oops");
+ if (candidate != NULL && candidate->as_metadata(rec) == metadata) {
+ _id = candidate->_id;
+ } else {
+ _id = rec->find_index(metadata) + 1;
+ }
+ }
+ DepValue(OopRecorder* rec, jobject obj, DepValue* candidate = NULL) {
+ assert(candidate == NULL || candidate->is_object(), "oops");
+ if (candidate != NULL && candidate->as_object(rec) == obj) {
+ _id = candidate->_id;
+ } else {
+ _id = -(rec->find_index(obj) + 1);
+ }
+ }
+
+ // Used to sort values in ascending order of index() with metadata values preceding object values
+ int sort_key() const { return -_id; }
+
+ bool operator == (const DepValue& other) const { return other._id == _id; }
+
+ bool is_valid() const { return _id != 0; }
+ int index() const { assert(is_valid(), "oops"); return _id < 0 ? -(_id + 1) : _id - 1; }
+ bool is_metadata() const { assert(is_valid(), "oops"); return _id > 0; }
+ bool is_object() const { assert(is_valid(), "oops"); return _id < 0; }
+
+ Metadata* as_metadata(OopRecorder* rec) const { assert(is_metadata(), "oops"); return rec->metadata_at(index()); }
+ Klass* as_klass(OopRecorder* rec) const { assert(as_metadata(rec)->is_klass(), "oops"); return (Klass*) as_metadata(rec); }
+ Method* as_method(OopRecorder* rec) const { assert(as_metadata(rec)->is_method(), "oops"); return (Method*) as_metadata(rec); }
+ jobject as_object(OopRecorder* rec) const { assert(is_object(), "oops"); return rec->oop_at(index()); }
+ };
+#endif // INCLUDE_JVMCI
+
private:
// State for writing a new set of dependencies:
GrowableArray<int>* _dep_seen; // (seen[h->ident] & (1<<dept))
GrowableArray<ciBaseObject*>* _deps[TYPE_LIMIT];
+#if INCLUDE_JVMCI
+ bool _using_dep_values;
+ GrowableArray<DepValue>* _dep_values[TYPE_LIMIT];
+#endif
static const char* _dep_name[TYPE_LIMIT];
static int _dep_args[TYPE_LIMIT];
@@ -224,8 +273,25 @@
return (seen & (1<<dept)) != 0;
}
+#if INCLUDE_JVMCI
+ bool note_dep_seen(int dept, DepValue x) {
+ assert(dept < BitsPerInt, "oops");
+ // place metadata deps at even indexes, object deps at odd indexes
+ int x_id = x.is_metadata() ? x.index() * 2 : (x.index() * 2) + 1;
+ assert(_dep_seen != NULL, "deps must be writable");
+ int seen = _dep_seen->at_grow(x_id, 0);
+ _dep_seen->at_put(x_id, seen | (1<<dept));
+ // return true if we've already seen dept/x
+ return (seen & (1<<dept)) != 0;
+ }
+#endif
+
bool maybe_merge_ctxk(GrowableArray<ciBaseObject*>* deps,
int ctxk_i, ciKlass* ctxk);
+#if INCLUDE_JVMCI
+ bool maybe_merge_ctxk(GrowableArray<DepValue>* deps,
+ int ctxk_i, DepValue ctxk);
+#endif
void sort_all_deps();
size_t estimate_size_in_bytes();
@@ -247,6 +313,9 @@
Dependencies(ciEnv* env) {
initialize(env);
}
+#if INCLUDE_JVMCI
+ Dependencies(Arena* arena, OopRecorder* oop_recorder, CompileLog* log);
+#endif
private:
// Check for a valid context type.
@@ -279,6 +348,27 @@
void assert_has_no_finalizable_subclasses(ciKlass* ctxk);
void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle);
+#if INCLUDE_JVMCI
+ private:
+ static void check_ctxk(Klass* ctxk) {
+ assert(ctxk->oop_is_instance(), "java types only");
+ }
+ static void check_ctxk_abstract(Klass* ctxk) {
+ check_ctxk(ctxk);
+ assert(ctxk->is_abstract(), "must be abstract");
+ }
+ void assert_common_1(DepType dept, DepValue x);
+ void assert_common_2(DepType dept, DepValue x0, DepValue x1);
+
+ public:
+ void assert_evol_method(Method* m);
+ void assert_has_no_finalizable_subclasses(Klass* ctxk);
+ void assert_leaf_type(Klass* ctxk);
+ void assert_unique_concrete_method(Klass* ctxk, Method* uniqm);
+ void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck);
+ void assert_call_site_target_value(oop callSite, oop methodHandle);
+#endif // INCLUDE_JVMCI
+
// Define whether a given method or type is concrete.
// These methods define the term "concrete" as used in this module.
// For this module, an "abstract" class is one which is non-concrete.
@@ -422,7 +512,7 @@
static void print_dependency(DepType dept,
GrowableArray<DepArgument>* args,
- Klass* witness = NULL);
+ Klass* witness = NULL, outputStream* st = tty);
private:
// helper for encoding common context types as zero:
@@ -534,7 +624,7 @@
void log_dependency(Klass* witness = NULL);
// Print the current dependency to tty.
- void print_dependency(Klass* witness = NULL, bool verbose = false);
+ void print_dependency(Klass* witness = NULL, bool verbose = false, outputStream* st = tty);
};
friend class Dependencies::DepStream;
--- a/hotspot/src/share/vm/code/exceptionHandlerTable.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/exceptionHandlerTable.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -102,9 +102,12 @@
void ExceptionHandlerTable::copy_to(nmethod* nm) {
assert(size_in_bytes() == nm->handler_table_size(), "size of space allocated in nmethod incorrect");
- memmove(nm->handler_table_begin(), _table, size_in_bytes());
+ copy_bytes_to(nm->handler_table_begin());
}
+void ExceptionHandlerTable::copy_bytes_to(address addr) {
+ memmove(addr, _table, size_in_bytes());
+}
HandlerTableEntry* ExceptionHandlerTable::entry_for(int catch_pco, int handler_bci, int scope_depth) const {
HandlerTableEntry* t = subtable_for(catch_pco);
--- a/hotspot/src/share/vm/code/exceptionHandlerTable.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/exceptionHandlerTable.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -89,11 +89,11 @@
int _size; // the number of allocated entries
ReallocMark _nesting; // assertion check for reallocations
+ public:
// add the entry & grow the table if needed
void add_entry(HandlerTableEntry entry);
HandlerTableEntry* subtable_for(int catch_pco) const;
- public:
// (compile-time) construction within compiler
ExceptionHandlerTable(int initial_size = 8);
@@ -116,6 +116,7 @@
// nmethod support
int size_in_bytes() const { return round_to(_length * sizeof(HandlerTableEntry), oopSize); }
void copy_to(nmethod* nm);
+ void copy_bytes_to(address addr);
// lookup
HandlerTableEntry* entry_for(int catch_pco, int handler_bci, int scope_depth) const;
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -26,6 +26,7 @@
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
+#include "code/nativeInst.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/abstractCompiler.hpp"
@@ -46,9 +47,27 @@
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/xmlstream.hpp"
+#ifdef TARGET_ARCH_x86
+# include "nativeInst_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "nativeInst_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "nativeInst_zero.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "nativeInst_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "nativeInst_ppc.hpp"
+#endif
#ifdef SHARK
#include "shark/sharkCompiler.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@@ -84,6 +103,11 @@
}
return compiler()->is_c1();
}
+bool nmethod::is_compiled_by_jvmci() const {
+ if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing
+ if (is_native_method()) return false;
+ return compiler()->is_jvmci();
+}
bool nmethod::is_compiled_by_c2() const {
if (compiler() == NULL) {
return false;
@@ -108,8 +132,7 @@
#ifndef PRODUCT
// These variables are put into one block to reduce relocations
// and make it simpler to print from the debugger.
-static
-struct nmethod_stats_struct {
+struct java_nmethod_stats_struct {
int nmethod_count;
int total_size;
int relocation_size;
@@ -122,6 +145,7 @@
int handler_table_size;
int nul_chk_table_size;
int oops_size;
+ int metadata_size;
void note_nmethod(nmethod* nm) {
nmethod_count += 1;
@@ -131,39 +155,46 @@
insts_size += nm->insts_size();
stub_size += nm->stub_size();
oops_size += nm->oops_size();
+ metadata_size += nm->metadata_size();
scopes_data_size += nm->scopes_data_size();
scopes_pcs_size += nm->scopes_pcs_size();
dependencies_size += nm->dependencies_size();
handler_table_size += nm->handler_table_size();
nul_chk_table_size += nm->nul_chk_table_size();
}
- void print_nmethod_stats() {
+ void print_nmethod_stats(const char* name) {
if (nmethod_count == 0) return;
- tty->print_cr("Statistics for %d bytecoded nmethods:", nmethod_count);
+ tty->print_cr("Statistics for %d bytecoded nmethods for %s:", nmethod_count, name);
if (total_size != 0) tty->print_cr(" total in heap = %d", total_size);
+ if (nmethod_count != 0) tty->print_cr(" header = %d", nmethod_count * sizeof(nmethod));
if (relocation_size != 0) tty->print_cr(" relocation = %d", relocation_size);
if (consts_size != 0) tty->print_cr(" constants = %d", consts_size);
if (insts_size != 0) tty->print_cr(" main code = %d", insts_size);
if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size);
if (oops_size != 0) tty->print_cr(" oops = %d", oops_size);
+ if (metadata_size != 0) tty->print_cr(" metadata = %d", metadata_size);
if (scopes_data_size != 0) tty->print_cr(" scopes data = %d", scopes_data_size);
if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size);
if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size);
if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size);
if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size);
}
-
+};
+
+struct native_nmethod_stats_struct {
int native_nmethod_count;
int native_total_size;
int native_relocation_size;
int native_insts_size;
int native_oops_size;
+ int native_metadata_size;
void note_native_nmethod(nmethod* nm) {
native_nmethod_count += 1;
native_total_size += nm->size();
native_relocation_size += nm->relocation_size();
native_insts_size += nm->insts_size();
native_oops_size += nm->oops_size();
+ native_metadata_size += nm->metadata_size();
}
void print_native_nmethod_stats() {
if (native_nmethod_count == 0) return;
@@ -172,8 +203,11 @@
if (native_relocation_size != 0) tty->print_cr(" N. relocation = %d", native_relocation_size);
if (native_insts_size != 0) tty->print_cr(" N. main code = %d", native_insts_size);
if (native_oops_size != 0) tty->print_cr(" N. oops = %d", native_oops_size);
+ if (native_metadata_size != 0) tty->print_cr(" N. metadata = %d", native_metadata_size);
}
-
+};
+
+struct pc_nmethod_stats_struct {
int pc_desc_resets; // number of resets (= number of caches)
int pc_desc_queries; // queries to nmethod::find_pc_desc
int pc_desc_approx; // number of those which have approximate true
@@ -194,9 +228,51 @@
pc_desc_repeats, pc_desc_hits,
pc_desc_tests, pc_desc_searches, pc_desc_adds);
}
-} nmethod_stats;
-#endif //PRODUCT
-
+};
+
+#ifdef COMPILER1
+static java_nmethod_stats_struct c1_java_nmethod_stats;
+#endif
+#ifdef COMPILER2
+static java_nmethod_stats_struct c2_java_nmethod_stats;
+#endif
+#if INCLUDE_JVMCI
+static java_nmethod_stats_struct jvmci_java_nmethod_stats;
+#endif
+#ifdef SHARK
+static java_nmethod_stats_struct shark_java_nmethod_stats;
+#endif
+static java_nmethod_stats_struct unknown_java_nmethod_stats;
+
+static native_nmethod_stats_struct native_nmethod_stats;
+static pc_nmethod_stats_struct pc_nmethod_stats;
+
+static void note_java_nmethod(nmethod* nm) {
+#ifdef COMPILER1
+ if (nm->is_compiled_by_c1()) {
+ c1_java_nmethod_stats.note_nmethod(nm);
+ } else
+#endif
+#ifdef COMPILER2
+ if (nm->is_compiled_by_c2()) {
+ c2_java_nmethod_stats.note_nmethod(nm);
+ } else
+#endif
+#if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci()) {
+ jvmci_java_nmethod_stats.note_nmethod(nm);
+ } else
+#endif
+#ifdef SHARK
+ if (nm->is_compiled_by_shark()) {
+ shark_java_nmethod_stats.note_nmethod(nm);
+ } else
+#endif
+ {
+ unknown_java_nmethod_stats.note_nmethod(nm);
+ }
+}
+#endif // !PRODUCT
//---------------------------------------------------------------------------------
@@ -276,7 +352,7 @@
// Helper used by both find_pc_desc methods.
static inline bool match_desc(PcDesc* pc, int pc_offset, bool approximate) {
- NOT_PRODUCT(++nmethod_stats.pc_desc_tests);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_tests);
if (!approximate)
return pc->pc_offset() == pc_offset;
else
@@ -288,7 +364,7 @@
_pc_descs[0] = NULL; // native method; no PcDescs at all
return;
}
- NOT_PRODUCT(++nmethod_stats.pc_desc_resets);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_resets);
// reset the cache by filling it with benign (non-null) values
assert(initial_pc_desc->pc_offset() < 0, "must be sentinel");
for (int i = 0; i < cache_size; i++)
@@ -296,8 +372,8 @@
}
PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) {
- NOT_PRODUCT(++nmethod_stats.pc_desc_queries);
- NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_queries);
+ NOT_PRODUCT(if (approximate) ++pc_nmethod_stats.pc_desc_approx);
// Note: one might think that caching the most recently
// read value separately would be a win, but one would be
@@ -313,7 +389,7 @@
res = _pc_descs[0];
if (res == NULL) return NULL; // native method; no PcDescs at all
if (match_desc(res, pc_offset, approximate)) {
- NOT_PRODUCT(++nmethod_stats.pc_desc_repeats);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_repeats);
return res;
}
@@ -322,7 +398,7 @@
res = _pc_descs[i];
if (res->pc_offset() < 0) break; // optimization: skip empty cache
if (match_desc(res, pc_offset, approximate)) {
- NOT_PRODUCT(++nmethod_stats.pc_desc_hits);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_hits);
return res;
}
}
@@ -332,7 +408,7 @@
}
void PcDescCache::add_pc_desc(PcDesc* pc_desc) {
- NOT_PRODUCT(++nmethod_stats.pc_desc_adds);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_adds);
// Update the LRU cache by shifting pc_desc forward.
for (int i = 0; i < cache_size; i++) {
PcDesc* next = _pc_descs[i];
@@ -459,7 +535,7 @@
_marked_for_deoptimization = 0;
_lock_count = 0;
_stack_traversal_mark = 0;
- _unload_reported = false; // jvmti state
+ _unload_reported = false; // jvmti state
#ifdef ASSERT
_oops_are_stale = false;
@@ -478,6 +554,10 @@
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM;
#endif
+#if INCLUDE_JVMCI
+ _jvmci_installed_code = NULL;
+ _speculation_log = NULL;
+#endif
}
nmethod* nmethod::new_native_nmethod(methodHandle method,
@@ -503,7 +583,7 @@
code_buffer, frame_size,
basic_lock_owner_sp_offset,
basic_lock_sp_offset, oop_maps);
- NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm));
+ NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm));
if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
Disassembler::decode(nm);
}
@@ -531,6 +611,10 @@
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
+#if INCLUDE_JVMCI
+ , Handle installed_code,
+ Handle speculationLog
+#endif
)
{
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
@@ -553,7 +637,12 @@
handler_table,
nul_chk_table,
compiler,
- comp_level);
+ comp_level
+#if INCLUDE_JVMCI
+ , installed_code,
+ speculationLog
+#endif
+ );
if (nm != NULL) {
// To make dependency checking during class loading fast, record
@@ -578,7 +667,7 @@
InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
}
}
- NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
+ NOT_PRODUCT(if (nm != NULL) note_java_nmethod(nm));
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
Disassembler::decode(nm);
}
@@ -593,7 +682,10 @@
return nm;
}
-
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4355) // warning C4355: 'this' : used in base member initializer list
+#endif
// For native wrappers
nmethod::nmethod(
Method* method,
@@ -683,6 +775,10 @@
}
}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw () {
return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level));
}
@@ -703,6 +799,10 @@
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
+#if INCLUDE_JVMCI
+ , Handle installed_code,
+ Handle speculation_log
+#endif
)
: CodeBlob("nmethod", code_buffer, sizeof(nmethod),
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
@@ -727,15 +827,42 @@
_consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts());
_stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs());
+#if INCLUDE_JVMCI
+ _jvmci_installed_code = installed_code();
+ _speculation_log = (instanceOop)speculation_log();
+
+ if (compiler->is_jvmci()) {
+ // JVMCI might not produce any stub sections
+ if (offsets->value(CodeOffsets::Exceptions) != -1) {
+ _exception_offset = code_offset() + offsets->value(CodeOffsets::Exceptions);
+ } else {
+ _exception_offset = -1;
+ }
+ if (offsets->value(CodeOffsets::Deopt) != -1) {
+ _deoptimize_offset = code_offset() + offsets->value(CodeOffsets::Deopt);
+ } else {
+ _deoptimize_offset = -1;
+ }
+ if (offsets->value(CodeOffsets::DeoptMH) != -1) {
+ _deoptimize_mh_offset = code_offset() + offsets->value(CodeOffsets::DeoptMH);
+ } else {
+ _deoptimize_mh_offset = -1;
+ }
+ } else {
+#endif
// Exception handler and deopt handler are in the stub section
assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
assert(offsets->value(CodeOffsets::Deopt ) != -1, "must be set");
+
_exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions);
_deoptimize_offset = _stub_offset + offsets->value(CodeOffsets::Deopt);
if (offsets->value(CodeOffsets::DeoptMH) != -1) {
_deoptimize_mh_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH);
} else {
_deoptimize_mh_offset = -1;
+#if INCLUDE_JVMCI
+ }
+#endif
}
if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
_unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler);
@@ -779,12 +906,12 @@
// we use the information of entry points to find out if a method is
// static or non static
- assert(compiler->is_c2() ||
+ assert(compiler->is_c2() || compiler->is_jvmci() ||
_method->is_static() == (entry_point() == _verified_entry_point),
" entry points must be same for static methods and vice versa");
}
- bool printnmethods = PrintNMethods
+ bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
|| CompilerOracle::should_print(_method)
|| CompilerOracle::has_option_string(_method, "PrintNMethods");
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
@@ -792,7 +919,6 @@
}
}
-
// Print a short set of xml attributes to identify this nmethod. The
// output should be embedded in some other element.
void nmethod::log_identity(xmlStream* log) const {
@@ -833,6 +959,7 @@
LOG_OFFSET(xtty, handler_table);
LOG_OFFSET(xtty, nul_chk_table);
LOG_OFFSET(xtty, oops);
+ LOG_OFFSET(xtty, metadata);
xtty->method(method());
xtty->stamp();
@@ -874,13 +1001,13 @@
oop_maps()->print();
}
}
- if (PrintDebugInfo) {
+ if (PrintDebugInfo || CompilerOracle::has_option_string(_method, "PrintDebugInfo")) {
print_scopes();
}
- if (PrintRelocations) {
+ if (PrintRelocations || CompilerOracle::has_option_string(_method, "PrintRelocations")) {
print_relocations();
}
- if (PrintDependencies) {
+ if (PrintDependencies || CompilerOracle::has_option_string(_method, "PrintDependencies")) {
print_dependencies();
}
if (PrintExceptionHandlers) {
@@ -990,7 +1117,7 @@
PcDesc* pd = pc_desc_at(pc);
guarantee(pd != NULL, "scope must be present");
return new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset(), pd->should_reexecute(),
+ pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
pd->return_oop());
}
@@ -1161,7 +1288,7 @@
}
void nmethod::inc_decompile_count() {
- if (!is_compiled_by_c2()) return;
+ if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return;
// Could be gated by ProfileTraps, but do not bother...
Method* m = method();
if (m == NULL) return;
@@ -1225,6 +1352,7 @@
}
_method = NULL; // Clear the method of this dead nmethod
}
+
// Make the class unloaded - i.e., change state and notify sweeper
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (is_in_use()) {
@@ -1237,6 +1365,18 @@
// Unregister must be done before the state change
Universe::heap()->unregister_nmethod(this);
+#if INCLUDE_JVMCI
+ // The method can only be unloaded after the pointer to the installed code
+ // Java wrapper is no longer alive. Here we need to clear out this weak
+ // reference to the dead object. Nulling out the reference has to happen
+ // after the method is unregistered since the original value may be still
+ // tracked by the rset.
+ if (_jvmci_installed_code != NULL) {
+ InstalledCode::set_address(_jvmci_installed_code, 0);
+ _jvmci_installed_code = NULL;
+ }
+#endif
+
_state = unloaded;
// Log the unloading.
@@ -1400,9 +1540,16 @@
} else {
assert(state == not_entrant, "other cases may need to be handled differently");
}
+#if INCLUDE_JVMCI
+ if (_jvmci_installed_code != NULL) {
+ // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely.
+ InstalledCode::set_address(_jvmci_installed_code, 0);
+ }
+#endif
if (TraceCreateZombies) {
- tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
+ ResourceMark m;
+ tty->print_cr("nmethod <" INTPTR_FORMAT "> %s code made %s", this, this->method() ? this->method()->name_and_sig_as_C_string() : "null", (state == not_entrant) ? "not entrant" : "zombie");
}
NMethodSweeper::report_state_change(this);
@@ -1690,6 +1837,33 @@
}
}
+#if INCLUDE_JVMCI
+ // Follow JVMCI method
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ if (_jvmci_installed_code != NULL) {
+ if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
+ if (!is_alive->do_object_b(_jvmci_installed_code)) {
+ bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
+ _jvmci_installed_code = NULL;
+ bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
+ }
+ } else {
+ if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
+ return;
+ }
+ }
+ }
+
+ if (_speculation_log != NULL) {
+ if (!is_alive->do_object_b(_speculation_log)) {
+ bs->write_ref_nmethod_pre(&_speculation_log, this);
+ _speculation_log = NULL;
+ bs->write_ref_nmethod_post(&_speculation_log, this);
+ }
+ }
+#endif
+
+
// Ensure that all metadata is still alive
verify_metadata_loaders(low_boundary, is_alive);
}
@@ -1772,6 +1946,27 @@
unloading_occurred = true;
}
+#if INCLUDE_JVMCI
+ // Follow JVMCI method
+ if (_jvmci_installed_code != NULL) {
+ if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
+ if (!is_alive->do_object_b(_jvmci_installed_code)) {
+ _jvmci_installed_code = NULL;
+ }
+ } else {
+ if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
+ return false;
+ }
+ }
+ }
+
+ if (_speculation_log != NULL) {
+ if (!is_alive->do_object_b(_speculation_log)) {
+ _speculation_log = NULL;
+ }
+ }
+#endif
+
// Exception cache
clean_exception_cache(is_alive);
@@ -1829,6 +2024,32 @@
return postponed;
}
+#if INCLUDE_JVMCI
+ // Follow JVMCI method
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ if (_jvmci_installed_code != NULL) {
+ if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
+ if (!is_alive->do_object_b(_jvmci_installed_code)) {
+ bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
+ _jvmci_installed_code = NULL;
+ bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
+ }
+ } else {
+ if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
+ is_unloaded = true;
+ }
+ }
+ }
+
+ if (_speculation_log != NULL) {
+ if (!is_alive->do_object_b(_speculation_log)) {
+ bs->write_ref_nmethod_pre(&_speculation_log, this);
+ _speculation_log = NULL;
+ bs->write_ref_nmethod_post(&_speculation_log, this);
+ }
+ }
+#endif
+
// Ensure that all metadata is still alive
verify_metadata_loaders(low_boundary, is_alive);
@@ -2013,6 +2234,15 @@
// (See comment above.)
}
+#if INCLUDE_JVMCI
+ if (_jvmci_installed_code != NULL) {
+ f->do_oop((oop*) &_jvmci_installed_code);
+ }
+ if (_speculation_log != NULL) {
+ f->do_oop((oop*) &_speculation_log);
+ }
+#endif
+
RelocIterator iter(this, low_boundary);
while (iter.next()) {
@@ -2137,7 +2367,7 @@
// called with a frame corresponding to a Java invoke
void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
#ifndef SHARK
- if (!method()->is_native()) {
+ if (method() != NULL && !method()->is_native()) {
SimpleScopeDesc ssd(this, fr.pc());
Bytecode_invoke call(ssd.method(), ssd.bci());
bool has_receiver = call.has_receiver();
@@ -2203,6 +2433,14 @@
memcpy(scopes_data_begin(), buffer, size);
}
+// When using JVMCI the address might be off by the size of a call instruction.
+bool nmethod::is_deopt_entry(address pc) {
+ return pc == deopt_handler_begin()
+#if INCLUDE_JVMCI
+ || pc == (deopt_handler_begin() + NativeCall::instruction_size)
+#endif
+ ;
+}
#ifdef ASSERT
static PcDesc* linear_search(nmethod* nm, int pc_offset, bool approximate) {
@@ -2211,7 +2449,7 @@
lower += 1; // exclude initial sentinel
PcDesc* res = NULL;
for (PcDesc* p = lower; p < upper; p++) {
- NOT_PRODUCT(--nmethod_stats.pc_desc_tests); // don't count this call to match_desc
+ NOT_PRODUCT(--pc_nmethod_stats.pc_desc_tests); // don't count this call to match_desc
if (match_desc(p, pc_offset, approximate)) {
if (res == NULL)
res = p;
@@ -2258,7 +2496,7 @@
// Use the last successful return as a split point.
PcDesc* mid = _pc_desc_cache.last_pc_desc();
- NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
if (mid->pc_offset() < pc_offset) {
lower = mid;
} else {
@@ -2271,7 +2509,7 @@
for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) {
while ((mid = lower + step) < upper) {
assert_LU_OK;
- NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
if (mid->pc_offset() < pc_offset) {
lower = mid;
} else {
@@ -2286,7 +2524,7 @@
while (true) {
assert_LU_OK;
mid = lower + 1;
- NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+ NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
if (mid->pc_offset() < pc_offset) {
lower = mid;
} else {
@@ -2473,7 +2711,6 @@
assert(nm->_lock_count >= 0, "unmatched nmethod lock/unlock");
}
-
// -----------------------------------------------------------------------------
// nmethod::get_deopt_original_pc
//
@@ -2587,7 +2824,7 @@
PcDesc* pd = pc_desc_at(nativeCall_at(call_site)->return_address());
assert(pd != NULL, "PcDesc must exist");
for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset(), pd->should_reexecute(),
+ pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
pd->return_oop());
!sd->is_top(); sd = sd->sender()) {
sd->verify();
@@ -2680,6 +2917,8 @@
tty->print("(c2) ");
} else if (is_compiled_by_shark()) {
tty->print("(shark) ");
+ } else if (is_compiled_by_jvmci()) {
+ tty->print("(JVMCI) ");
} else {
tty->print("(nm) ");
}
@@ -2764,7 +3003,10 @@
continue;
ScopeDesc* sd = scope_desc_at(p->real_pc(this));
- sd->print_on(tty, p);
+ while (sd != NULL) {
+ sd->print_on(tty, p);
+ sd = sd->sender();
+ }
}
}
@@ -2881,7 +3123,7 @@
PcDesc* p = pc_desc_near(begin+1);
if (p != NULL && p->real_pc(this) <= end) {
return new ScopeDesc(this, p->scope_decode_offset(),
- p->obj_decode_offset(), p->should_reexecute(),
+ p->obj_decode_offset(), p->should_reexecute(), p->rethrow_exception(),
p->return_oop());
}
return NULL;
@@ -2890,9 +3132,9 @@
void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) const {
if (block_begin == entry_point()) stream->print_cr("[Entry Point]");
if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]");
- if (block_begin == exception_begin()) stream->print_cr("[Exception Handler]");
+ if (JVMCI_ONLY(_exception_offset >= 0 &&) block_begin == exception_begin()) stream->print_cr("[Exception Handler]");
if (block_begin == stub_begin()) stream->print_cr("[Stub Code]");
- if (block_begin == deopt_handler_begin()) stream->print_cr("[Deopt Handler Code]");
+ if (JVMCI_ONLY(_deoptimize_offset >= 0 &&) block_begin == deopt_handler_begin()) stream->print_cr("[Deopt Handler Code]");
if (has_method_handle_invokes())
if (block_begin == deopt_mh_handler_begin()) stream->print_cr("[Deopt MH Handler Code]");
@@ -3058,6 +3300,7 @@
}
}
}
+ st->print(" {reexecute=%d rethrow=%d return_oop=%d}", sd->should_reexecute(), sd->rethrow_exception(), sd->return_oop());
}
// Print all scopes
@@ -3130,12 +3373,49 @@
void nmethod::print_statistics() {
ttyLocker ttyl;
if (xtty != NULL) xtty->head("statistics type='nmethod'");
- nmethod_stats.print_native_nmethod_stats();
- nmethod_stats.print_nmethod_stats();
+ native_nmethod_stats.print_native_nmethod_stats();
+#ifdef COMPILER1
+ c1_java_nmethod_stats.print_nmethod_stats("C1");
+#endif
+#ifdef COMPILER2
+ c2_java_nmethod_stats.print_nmethod_stats("C2");
+#endif
+#if INCLUDE_JVMCI
+ jvmci_java_nmethod_stats.print_nmethod_stats("JVMCI");
+#endif
+#ifdef SHARK
+ shark_java_nmethod_stats.print_nmethod_stats("Shark");
+#endif
+ unknown_java_nmethod_stats.print_nmethod_stats("Unknown");
DebugInformationRecorder::print_statistics();
- nmethod_stats.print_pc_stats();
+#ifndef PRODUCT
+ pc_nmethod_stats.print_pc_stats();
+#endif
Dependencies::print_statistics();
if (xtty != NULL) xtty->tail("statistics");
}
-#endif // PRODUCT
+#endif // !PRODUCT
+
+#if INCLUDE_JVMCI
+char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
+ if (!this->is_compiled_by_jvmci()) {
+ return NULL;
+ }
+ oop installedCode = this->jvmci_installed_code();
+ if (installedCode != NULL) {
+ oop installedCodeName = NULL;
+ if (installedCode->is_a(InstalledCode::klass())) {
+ installedCodeName = InstalledCode::name(installedCode);
+ }
+ if (installedCodeName != NULL) {
+ return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
+ } else {
+ jio_snprintf(buf, buflen, "null");
+ return buf;
+ }
+ }
+ jio_snprintf(buf, buflen, "noInstalledCode");
+ return buf;
+}
+#endif
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/nmethod.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -126,6 +126,12 @@
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
+#if INCLUDE_JVMCI
+ // Needed to keep nmethods alive that are not the default nmethod for the associated Method.
+ oop _jvmci_installed_code;
+ oop _speculation_log;
+#endif
+
// To support simple linked-list chaining of nmethods:
nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head
@@ -273,7 +279,12 @@
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
- int comp_level);
+ int comp_level
+#if INCLUDE_JVMCI
+ , Handle installed_code,
+ Handle speculation_log
+#endif
+ );
// helper methods
void* operator new(size_t size, int nmethod_size, int comp_level) throw();
@@ -309,7 +320,12 @@
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
- int comp_level);
+ int comp_level
+#if INCLUDE_JVMCI
+ , Handle installed_code = Handle(),
+ Handle speculation_log = Handle()
+#endif
+ );
static nmethod* new_native_nmethod(methodHandle method,
int compile_id,
@@ -332,6 +348,7 @@
bool is_osr_method() const { return _entry_bci != InvocationEntryBci; }
bool is_compiled_by_c1() const;
+ bool is_compiled_by_jvmci() const;
bool is_compiled_by_c2() const;
bool is_compiled_by_shark() const;
@@ -582,6 +599,14 @@
// Evolution support. We make old (discarded) compiled methods point to new Method*s.
void set_method(Method* method) { _method = method; }
+#if INCLUDE_JVMCI
+ oop jvmci_installed_code() { return _jvmci_installed_code ; }
+ char* jvmci_installed_code_name(char* buf, size_t buflen);
+ void set_jvmci_installed_code(oop installed_code) { _jvmci_installed_code = installed_code; }
+ oop speculation_log() { return _speculation_log ; }
+ void set_speculation_log(oop speculation_log) { _speculation_log = speculation_log; }
+#endif
+
// GC support
void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
// The parallel versions are used by G1.
@@ -639,7 +664,7 @@
// Deopt
// Return true is the PC is one would expect if the frame is being deopted.
bool is_deopt_pc (address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
- bool is_deopt_entry (address pc) { return pc == deopt_handler_begin(); }
+ bool is_deopt_entry (address pc);
bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
// Accessor/mutator for the original pc of a frame before a frame was deopted.
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
@@ -690,7 +715,7 @@
// Prints a comment for one native instruction (reloc info, pc desc)
void print_code_comment_on(outputStream* st, int column, address begin, address end);
- static void print_statistics() PRODUCT_RETURN;
+ static void print_statistics() PRODUCT_RETURN;
// Compiler task identification. Note that all OSR methods
// are numbered in an independent sequence if CICountOSR is true,
--- a/hotspot/src/share/vm/code/oopRecorder.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/oopRecorder.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -157,3 +157,48 @@
// Explicitly instantiate these types
template class ValueRecorder<Metadata*>;
template class ValueRecorder<jobject>;
+
+oop ObjectLookup::ObjectEntry::oop_value() const { return JNIHandles::resolve(_value); }
+
+ObjectLookup::ObjectLookup(): _gc_count(Universe::heap()->total_collections()), _values(4) {}
+
+void ObjectLookup::maybe_resort() {
+ // The values are kept sorted by address which may be invalidated
+ // after a GC, so resort if a GC has occurred since last time.
+ if (_gc_count != Universe::heap()->total_collections()) {
+ _gc_count = Universe::heap()->total_collections();
+ _values.sort(sort_by_address);
+ }
+}
+
+int ObjectLookup::sort_by_address(oop a, oop b) {
+ if (b > a) return 1;
+ if (a > b) return -1;
+ return 0;
+}
+
+int ObjectLookup::sort_by_address(ObjectEntry* a, ObjectEntry* b) {
+ return sort_by_address(a->oop_value(), b->oop_value());
+}
+
+int ObjectLookup::sort_oop_by_address(oop const& a, ObjectEntry const& b) {
+ return sort_by_address(a, b.oop_value());
+}
+
+int ObjectLookup::find_index(jobject handle, OopRecorder* oop_recorder) {
+ if (handle == NULL) {
+ return 0;
+ }
+ oop object = JNIHandles::resolve(handle);
+ maybe_resort();
+ bool found;
+ int location = _values.find_sorted<oop, sort_oop_by_address>(object, found);
+ if (!found) {
+ jobject handle = JNIHandles::make_local(object);
+ ObjectEntry r(handle, oop_recorder->allocate_oop_index(handle));
+ _values.insert_before(location, r);
+ return r.index();
+ }
+ return _values.at(location).index();
+}
+
--- a/hotspot/src/share/vm/code/oopRecorder.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/oopRecorder.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -146,18 +146,57 @@
#endif
};
+class OopRecorder;
+
+class ObjectLookup : public ResourceObj {
+ private:
+ class ObjectEntry {
+ private:
+ jobject _value;
+ int _index;
+
+ public:
+ ObjectEntry(jobject value, int index) : _value(value), _index(index) {}
+ ObjectEntry() : _value(NULL), _index(0) {}
+ oop oop_value() const;
+ int index() { return _index; }
+ };
+
+ GrowableArray<ObjectEntry> _values;
+ unsigned int _gc_count;
+
+ // Utility sort functions
+ static int sort_by_address(oop a, oop b);
+ static int sort_by_address(ObjectEntry* a, ObjectEntry* b);
+ static int sort_oop_by_address(oop const& a, ObjectEntry const& b);
+
+ public:
+ ObjectLookup();
+
+ // Resort list if a GC has occurred since the last sort
+ void maybe_resort();
+ int find_index(jobject object, OopRecorder* oop_recorder);
+};
+
class OopRecorder : public ResourceObj {
private:
ValueRecorder<jobject> _oops;
ValueRecorder<Metadata*> _metadata;
+ ObjectLookup* _object_lookup;
public:
- OopRecorder(Arena* arena = NULL): _oops(arena), _metadata(arena) {}
+ OopRecorder(Arena* arena = NULL, bool deduplicate = false): _oops(arena), _metadata(arena) {
+ if (deduplicate) {
+ _object_lookup = new ObjectLookup();
+ } else {
+ _object_lookup = NULL;
+ }
+ }
int allocate_oop_index(jobject h) {
return _oops.allocate_index(h);
}
- int find_index(jobject h) {
- return _oops.find_index(h);
+ virtual int find_index(jobject h) {
+ return _object_lookup != NULL ? _object_lookup->find_index(h, this) : _oops.find_index(h);
}
jobject oop_at(int index) {
return _oops.at(index);
@@ -175,7 +214,7 @@
int allocate_metadata_index(Metadata* oop) {
return _metadata.allocate_index(oop);
}
- int find_index(Metadata* h) {
+ virtual int find_index(Metadata* h) {
return _metadata.find_index(h);
}
Metadata* metadata_at(int index) {
--- a/hotspot/src/share/vm/code/pcDesc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/pcDesc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -42,7 +42,8 @@
enum {
PCDESC_reexecute = 1 << 0,
PCDESC_is_method_handle_invoke = 1 << 1,
- PCDESC_return_oop = 1 << 2
+ PCDESC_return_oop = 1 << 2,
+ PCDESC_rethrow_exception = 1 << 3
};
int _flags;
@@ -71,6 +72,8 @@
};
// Flags
+ bool rethrow_exception() const { return (_flags & PCDESC_rethrow_exception) != 0; }
+ void set_rethrow_exception(bool z) { set_flag(PCDESC_rethrow_exception, z); }
bool should_reexecute() const { return (_flags & PCDESC_reexecute) != 0; }
void set_should_reexecute(bool z) { set_flag(PCDESC_reexecute, z); }
--- a/hotspot/src/share/vm/code/relocInfo.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/relocInfo.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -30,6 +30,7 @@
#include "memory/resourceArea.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "utilities/copy.hpp"
+#include "oops/oop.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@@ -424,6 +425,30 @@
ShouldNotReachHere();
}
+void Relocation::const_set_data_value(address x) {
+#ifdef _LP64
+ if (format() == relocInfo::narrow_oop_in_const) {
+ *(narrowOop*)addr() = oopDesc::encode_heap_oop((oop) x);
+ } else {
+#endif
+ *(address*)addr() = x;
+#ifdef _LP64
+ }
+#endif
+}
+
+void Relocation::const_verify_data_value(address x) {
+#ifdef _LP64
+ if (format() == relocInfo::narrow_oop_in_const) {
+ assert(*(narrowOop*)addr() == oopDesc::encode_heap_oop((oop) x), "must agree");
+ } else {
+#endif
+ assert(*(address*)addr() == x, "must agree");
+#ifdef _LP64
+ }
+#endif
+}
+
RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) {
if (rtype == relocInfo::none) return RelocationHolder::none;
@@ -580,7 +605,8 @@
void static_stub_Relocation::unpack_data() {
address base = binding()->section_start(CodeBuffer::SECT_INSTS);
- _static_call = address_from_scaled_offset(unpack_1_int(), base);
+ jint offset = unpack_1_int();
+ _static_call = address_from_scaled_offset(offset, base);
}
void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) {
@@ -794,7 +820,8 @@
RelocIterator iter(code());
while (iter.next()) {
if (iter.type() == relocInfo::static_stub_type) {
- if (iter.static_stub_reloc()->static_call() == static_call_addr) {
+ static_stub_Relocation* stub_reloc = iter.static_stub_reloc();
+ if (stub_reloc->static_call() == static_call_addr) {
return iter.addr();
}
}
@@ -816,7 +843,8 @@
RelocIterator iter(code());
while (iter.next()) {
if (iter.type() == relocInfo::static_stub_type) {
- if (iter.static_stub_reloc()->static_call() == static_call_addr) {
+ static_stub_Relocation* stub_reloc = iter.static_stub_reloc();
+ if (stub_reloc->static_call() == static_call_addr) {
return iter.addr();
}
}
--- a/hotspot/src/share/vm/code/relocInfo.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/relocInfo.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -210,6 +210,11 @@
// See [About Offsets] below.
// //%note reloc_2
//
+// relocInfo::poll_[return_]type -- a safepoint poll
+// Value: none
+// Instruction types: memory load or test
+// Data: none
+//
// For example:
//
// INSTRUCTIONS RELOC: TYPE PREFIX DATA
@@ -443,6 +448,11 @@
};
public:
enum {
+#ifdef _LP64
+ // for use in format
+ // format_width must be at least 1 on _LP64
+ narrow_oop_in_const = 1,
+#endif
// Conservatively large estimate of maximum length (in shorts)
// of any relocation record.
// Extended format is length prefix, data words, and tag/offset suffix.
@@ -525,19 +535,19 @@
typedef relocInfo::relocType relocType;
private:
- address _limit; // stop producing relocations after this _addr
- relocInfo* _current; // the current relocation information
- relocInfo* _end; // end marker; we're done iterating when _current == _end
- nmethod* _code; // compiled method containing _addr
- address _addr; // instruction to which the relocation applies
- short _databuf; // spare buffer for compressed data
- short* _data; // pointer to the relocation's data
- short _datalen; // number of halfwords in _data
- char _format; // position within the instruction
+ address _limit; // stop producing relocations after this _addr
+ relocInfo* _current; // the current relocation information
+ relocInfo* _end; // end marker; we're done iterating when _current == _end
+ nmethod* _code; // compiled method containing _addr
+ address _addr; // instruction to which the relocation applies
+ short _databuf; // spare buffer for compressed data
+ short* _data; // pointer to the relocation's data
+ short _datalen; // number of halfwords in _data
+ char _format; // position within the instruction
// Base addresses needed to compute targets of section_word_type relocs.
- address _section_start[SECT_LIMIT];
- address _section_end [SECT_LIMIT];
+ address _section_start[SECT_LIMIT];
+ address _section_end [SECT_LIMIT];
void set_has_current(bool b) {
_datalen = !b ? -1 : 0;
@@ -565,7 +575,7 @@
public:
// constructor
- RelocIterator(nmethod* nm, address begin = NULL, address limit = NULL);
+ RelocIterator(nmethod* nm, address begin = NULL, address limit = NULL);
RelocIterator(CodeSection* cb, address begin = NULL, address limit = NULL);
// get next reloc info, return !eos
@@ -762,6 +772,9 @@
}
protected:
+ // platform-independent utility for patching constant section
+ void const_set_data_value (address x);
+ void const_verify_data_value (address x);
// platform-dependent utilities for decoding and patching instructions
void pd_set_data_value (address x, intptr_t off, bool verify_only = false); // a set or mem-ref
void pd_verify_data_value (address x, intptr_t off) { pd_set_data_value(x, off, true); }
@@ -872,13 +885,13 @@
void set_value(address x) { set_value(x, offset()); }
void set_value(address x, intptr_t o) {
if (addr_in_const())
- *(address*)addr() = x;
+ const_set_data_value(x);
else
pd_set_data_value(x, o);
}
void verify_value(address x) {
if (addr_in_const())
- assert(*(address*)addr() == x, "must agree");
+ const_verify_data_value(x);
else
pd_verify_data_value(x, offset());
}
@@ -1117,7 +1130,7 @@
}
private:
- address _static_call; // location of corresponding static_call
+ address _static_call; // location of corresponding static_call
static_stub_Relocation(address static_call) {
_static_call = static_call;
@@ -1318,10 +1331,8 @@
void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
};
-class poll_return_Relocation : public Relocation {
- bool is_data() { return true; }
+class poll_return_Relocation : public poll_Relocation {
relocInfo::relocType type() { return relocInfo::poll_return_type; }
- void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
};
// We know all the xxx_Relocation classes, so now we can define these:
--- a/hotspot/src/share/vm/code/scopeDesc.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/scopeDesc.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -32,20 +32,22 @@
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(obj_decode_offset);
_reexecute = reexecute;
+ _rethrow_exception = rethrow_exception;
_return_oop = return_oop;
decode_body();
}
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(DebugInformationRecorder::serialized_null);
_reexecute = reexecute;
+ _rethrow_exception = rethrow_exception;
_return_oop = return_oop;
decode_body();
}
@@ -56,6 +58,7 @@
_decode_offset = parent->_sender_decode_offset;
_objects = parent->_objects;
_reexecute = false; //reexecute only applies to the first scope
+ _rethrow_exception = false;
_return_oop = false;
decode_body();
}
@@ -227,17 +230,18 @@
}
}
-#ifdef COMPILER2
- if (DoEscapeAnalysis && is_top() && _objects != NULL) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ if (NOT_JVMCI(DoEscapeAnalysis &&) is_top() && _objects != NULL) {
st->print_cr(" Objects");
for (int i = 0; i < _objects->length(); i++) {
ObjectValue* sv = (ObjectValue*) _objects->at(i);
st->print(" - %d: ", sv->id());
+ st->print("%s ", java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())->external_name());
sv->print_fields_on(st);
st->cr();
}
}
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
}
#endif
--- a/hotspot/src/share/vm/code/scopeDesc.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/code/scopeDesc.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -41,7 +41,7 @@
int _bci;
public:
- SimpleScopeDesc(nmethod* code,address pc) {
+ SimpleScopeDesc(nmethod* code, address pc) {
PcDesc* pc_desc = code->pc_desc_at(pc);
assert(pc_desc != NULL, "Must be able to find matching PcDesc");
DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset());
@@ -60,17 +60,18 @@
class ScopeDesc : public ResourceObj {
public:
// Constructor
- ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
+ ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
// Calls above, giving default value of "serialized_null" to the
// "obj_decode_offset" argument. (We don't use a default argument to
// avoid a .hpp-.hpp dependency.)
- ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
+ ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
// JVM state
Method* method() const { return _method; }
int bci() const { return _bci; }
bool should_reexecute() const { return _reexecute; }
+ bool rethrow_exception() const { return _rethrow_exception; }
bool return_oop() const { return _return_oop; }
GrowableArray<ScopeValue*>* locals();
@@ -95,6 +96,7 @@
Method* _method;
int _bci;
bool _reexecute;
+ bool _rethrow_exception;
bool _return_oop;
// Decoding offsets
--- a/hotspot/src/share/vm/compiler/abstractCompiler.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -58,7 +58,7 @@
}
void AbstractCompiler::set_state(int state) {
- // Ensure that ste is only set by one thread at a time
+ // Ensure that state is only set by one thread at a time
MutexLocker only_one(CompileThread_lock);
_compiler_state = state;
CompileThread_lock->notify_all();
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, 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
@@ -27,6 +27,47 @@
#include "ci/compilerInterface.hpp"
+typedef void (*initializer)(void);
+
+#if INCLUDE_JVMCI
+// Per-compiler statistics
+class CompilerStatistics VALUE_OBJ_CLASS_SPEC {
+ friend class VMStructs;
+
+ class Data VALUE_OBJ_CLASS_SPEC {
+ friend class VMStructs;
+ public:
+ elapsedTimer _time; // time spent compiling
+ int _bytes; // number of bytecodes compiled, including inlined bytecodes
+ int _count; // number of compilations
+ Data() : _bytes(0), _count(0) {}
+ void update(elapsedTimer time, int bytes) {
+ _time.add(time);
+ _bytes += bytes;
+ _count++;
+ }
+ void reset() {
+ _time.reset();
+ }
+ };
+
+ public:
+ Data _standard; // stats for non-OSR compilations
+ Data _osr; // stats for OSR compilations
+ int _nmethods_size; //
+ int _nmethods_code_size;
+ int bytes_per_second() {
+ int bytes = _standard._bytes + _osr._bytes;
+ if (bytes == 0) {
+ return 0;
+ }
+ double seconds = _standard._time.seconds() + _osr._time.seconds();
+ return seconds == 0.0 ? 0 : (int) (bytes / seconds);
+ }
+ CompilerStatistics() : _nmethods_size(0), _nmethods_code_size(0) {}
+};
+#endif // INCLUDE_JVMCI
+
class AbstractCompiler : public CHeapObj<mtCompiler> {
private:
volatile int _num_compiler_threads;
@@ -45,12 +86,17 @@
none,
c1,
c2,
+ jvmci,
shark
};
private:
Type _type;
+#if INCLUDE_JVMCI
+ CompilerStatistics _stats;
+#endif
+
public:
AbstractCompiler(Type type) : _type(type), _compiler_state(uninitialized), _num_compiler_threads(0) {}
@@ -115,6 +161,7 @@
// Compiler type queries.
bool is_c1() { return _type == c1; }
bool is_c2() { return _type == c2; }
+ bool is_jvmci() { return _type == jvmci; }
bool is_shark() { return _type == shark; }
// Customization
@@ -138,6 +185,10 @@
virtual void print_timers() {
ShouldNotReachHere();
}
+
+#if INCLUDE_JVMCI
+ CompilerStatistics* stats() { return &_stats; }
+#endif
};
#endif // SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -51,6 +51,11 @@
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "runtime/vframe.hpp"
+#endif
#ifdef COMPILER2
#include "opto/c2compiler.hpp"
#endif
@@ -505,6 +510,30 @@
// Set the interface to the current compiler(s).
int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
+
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ // This is creating a JVMCICompiler singleton.
+ JVMCICompiler* jvmci = new JVMCICompiler();
+
+ if (UseJVMCICompiler) {
+ _compilers[1] = jvmci;
+ if (FLAG_IS_DEFAULT(JVMCIThreads)) {
+ if (BootstrapJVMCI) {
+ // JVMCI will bootstrap so give it more threads
+ c2_count = MIN2(32, os::active_processor_count());
+ }
+ } else {
+ c2_count = JVMCIThreads;
+ }
+ if (FLAG_IS_DEFAULT(JVMCIHostThreads)) {
+ } else {
+ c1_count = JVMCIHostThreads;
+ }
+ }
+ }
+#endif // INCLUDE_JVMCI
+
#ifdef COMPILER1
if (c1_count > 0) {
_compilers[0] = new Compiler();
@@ -512,8 +541,10 @@
#endif // COMPILER1
#ifdef COMPILER2
- if (c2_count > 0) {
- _compilers[1] = new C2Compiler();
+ if (true JVMCI_ONLY( && !UseJVMCICompiler)) {
+ if (c2_count > 0) {
+ _compilers[1] = new C2Compiler();
+ }
}
#endif // COMPILER2
@@ -733,7 +764,7 @@
const bool compiler_thread = true;
for (int i = 0; i < c2_compiler_count; i++) {
// Create a name for our thread.
- sprintf(name_buffer, "C2 CompilerThread%d", i);
+ sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
// Shark and C2
make_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], compiler_thread, CHECK);
@@ -803,7 +834,7 @@
if (osr_bci != InvocationEntryBci) {
tty->print(" osr_bci: %d", osr_bci);
}
- tty->print(" comment: %s count: %d", comment, hot_count);
+ tty->print(" level: %d comment: %s count: %d", comp_level, comment, hot_count);
if (!hot_method.is_null()) {
tty->print(" hot: ");
if (hot_method() != method()) {
@@ -895,6 +926,41 @@
// Should this thread wait for completion of the compile?
blocking = is_compile_blocking();
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ if (blocking) {
+ // Don't allow blocking compiles for requests triggered by JVMCI.
+ if (thread->is_Compiler_thread()) {
+ blocking = false;
+ }
+
+ // Don't allow blocking compiles if inside a class initializer or while performing class loading
+ vframeStream vfst((JavaThread*) thread);
+ for (; !vfst.at_end(); vfst.next()) {
+ if (vfst.method()->is_static_initializer() ||
+ (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+ vfst.method()->name() == vmSymbols::loadClass_name())) {
+ blocking = false;
+ break;
+ }
+ }
+
+ // Don't allow blocking compilation requests to JVMCI
+ // if JVMCI itself is not yet initialized
+ if (!JVMCIRuntime::is_HotSpotJVMCIRuntime_initialized() && compiler(comp_level)->is_jvmci()) {
+ blocking = false;
+ }
+
+ // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
+ // to avoid deadlock between compiler thread(s) and threads run at shutdown
+ // such as the DestroyJavaVM thread.
+ if (JVMCIRuntime::shutdown_called()) {
+ blocking = false;
+ }
+ }
+ }
+#endif // INCLUDE_JVMCI
+
// We will enter the compilation in the queue.
// 14012000: Note that this sets the queued_for_compile bits in
// the target method. We can now reason that a method cannot be
@@ -1076,7 +1142,10 @@
// return requested nmethod
// We accept a higher level osr method
- return osr_bci == InvocationEntryBci ? method->code() : method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
+ if (osr_bci == InvocationEntryBci) {
+ return method->code();
+ }
+ return method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
}
@@ -1199,6 +1268,15 @@
#endif
}
+// ------------------------------------------------------------------
+// CompileBroker::assign_compile_id_unlocked
+//
+// Public wrapper for assign_compile_id that acquires the needed locks
+uint CompileBroker::assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci) {
+ MutexLocker locker(MethodCompileQueue_lock, thread);
+ return assign_compile_id(method, osr_bci);
+}
+
/**
* Should the current thread block until this compilation request
* has been fulfilled?
@@ -1558,6 +1636,35 @@
tty->print("%s", s.as_string());
}
+void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env) {
+
+ if (success) {
+ task->mark_success();
+ if (ci_env != NULL) {
+ task->set_num_inlined_bytecodes(ci_env->num_inlined_bytecodes());
+ }
+ if (_compilation_log != NULL) {
+ nmethod* code = task->code();
+ if (code != NULL) {
+ _compilation_log->log_nmethod(thread, code);
+ }
+ }
+ }
+
+ // simulate crash during compilation
+ assert(task->compile_id() != CICrashAt, "just as planned");
+ if (event.should_commit()) {
+ event.set_method(task->method());
+ event.set_compileID(task->compile_id());
+ event.set_compileLevel(task->comp_level());
+ event.set_succeded(task->is_success());
+ event.set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
+ event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
+ event.set_inlinedBytes(task->num_inlined_bytecodes());
+ event.commit();
+ }
+}
+
// ------------------------------------------------------------------
// CompileBroker::invoke_compiler_on_method
//
@@ -1606,12 +1713,27 @@
push_jni_handle_block();
Method* target_handle = task->method();
int compilable = ciEnv::MethodCompilable;
+ AbstractCompiler *comp = compiler(task_level);
+
+ int system_dictionary_modification_counter;
{
- int system_dictionary_modification_counter;
- {
- MutexLocker locker(Compile_lock, thread);
- system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
- }
+ MutexLocker locker(Compile_lock, thread);
+ system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
+ }
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler && comp != NULL && comp->is_jvmci()) {
+ JVMCICompiler* jvmci = (JVMCICompiler*) comp;
+
+ TraceTime t1("compilation", &time);
+ EventCompilation event;
+
+ JVMCIEnv env(task, system_dictionary_modification_counter);
+ jvmci->compile_method(target_handle, osr_bci, &env);
+
+ post_compile(thread, task, event, task->code() != NULL, NULL);
+ } else
+#endif // INCLUDE_JVMCI
+ {
NoHandleMark nhm;
ThreadToNativeFromVM ttn(thread);
@@ -1637,7 +1759,6 @@
TraceTime t1("compilation", &time);
EventCompilation event;
- AbstractCompiler *comp = compiler(task_level);
if (comp == NULL) {
ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
} else {
@@ -1673,28 +1794,9 @@
err_msg_res("COMPILE SKIPPED: %s", ci_env.failure_reason());
task->print(tty, msg);
}
- } else {
- task->mark_success();
- task->set_num_inlined_bytecodes(ci_env.num_inlined_bytecodes());
- if (_compilation_log != NULL) {
- nmethod* code = task->code();
- if (code != NULL) {
- _compilation_log->log_nmethod(thread, code);
- }
- }
}
- // simulate crash during compilation
- assert(task->compile_id() != CICrashAt, "just as planned");
- if (event.should_commit()) {
- event.set_method(target->get_Method());
- event.set_compileID(compile_id);
- event.set_compileLevel(task->comp_level());
- event.set_succeded(task->is_success());
- event.set_isOsr(is_osr);
- event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
- event.set_inlinedBytes(task->num_inlined_bytecodes());
- event.commit();
- }
+
+ post_compile(thread, task, event, !ci_env.failing(), &ci_env);
}
pop_jni_handle_block();
@@ -1945,13 +2047,19 @@
_peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time;
if (CITime) {
+ int bytes_compiled = method->code_size() + task->num_inlined_bytecodes();
+ JVMCI_ONLY(CompilerStatistics* stats = compiler(task->comp_level())->stats();)
if (is_osr) {
_t_osr_compilation.add(time);
- _sum_osr_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
+ _sum_osr_bytes_compiled += bytes_compiled;
+ JVMCI_ONLY(stats->_osr.update(time, bytes_compiled);)
} else {
_t_standard_compilation.add(time);
_sum_standard_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
+ JVMCI_ONLY(stats->_standard.update(time, bytes_compiled);)
}
+ JVMCI_ONLY(stats->_nmethods_size += code->total_size();)
+ JVMCI_ONLY(stats->_nmethods_code_size += code->insts_size();)
}
if (UsePerfData) {
@@ -2007,22 +2115,106 @@
}
}
-void CompileBroker::print_times() {
+#if INCLUDE_JVMCI
+void CompileBroker::print_times(AbstractCompiler* comp) {
+ CompilerStatistics* stats = comp->stats();
+ tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}",
+ comp->name(), stats->bytes_per_second(),
+ stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count,
+ stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count,
+ stats->_nmethods_size, stats->_nmethods_code_size);
+ comp->print_timers();
+}
+#endif // INCLUDE_JVMCI
+
+void CompileBroker::print_times(bool per_compiler, bool aggregate) {
+#if INCLUDE_JVMCI
+ elapsedTimer standard_compilation;
+ elapsedTimer total_compilation;
+ elapsedTimer osr_compilation;
+
+ int standard_bytes_compiled = 0;
+ int osr_bytes_compiled = 0;
+
+ int standard_compile_count = 0;
+ int osr_compile_count = 0;
+ int total_compile_count = 0;
+
+ int nmethods_size = 0;
+ int nmethods_code_size = 0;
+ bool printedHeader = false;
+
+ for (unsigned int i = 0; i < sizeof(_compilers) / sizeof(AbstractCompiler*); i++) {
+ AbstractCompiler* comp = _compilers[i];
+ if (comp != NULL) {
+ if (per_compiler && aggregate && !printedHeader) {
+ printedHeader = true;
+ tty->cr();
+ tty->print_cr("Individual compiler times (for compiled methods only)");
+ tty->print_cr("------------------------------------------------");
+ tty->cr();
+ }
+ CompilerStatistics* stats = comp->stats();
+
+ standard_compilation.add(stats->_standard._time);
+ osr_compilation.add(stats->_osr._time);
+
+ standard_bytes_compiled += stats->_standard._bytes;
+ osr_bytes_compiled += stats->_osr._bytes;
+
+ standard_compile_count += stats->_standard._count;
+ osr_compile_count += stats->_osr._count;
+
+ nmethods_size += stats->_nmethods_size;
+ nmethods_code_size += stats->_nmethods_code_size;
+
+ if (per_compiler) {
+ print_times(comp);
+ }
+ }
+ }
+ total_compile_count = osr_compile_count + standard_compile_count;
+ total_compilation.add(osr_compilation);
+ total_compilation.add(standard_compilation);
+
+ // In hosted mode, print the JVMCI compiler specific counters manually.
+ if (!UseJVMCICompiler) {
+ JVMCICompiler::print_compilation_timers();
+ }
+#else // INCLUDE_JVMCI
+ elapsedTimer standard_compilation = CompileBroker::_t_standard_compilation;
+ elapsedTimer osr_compilation = CompileBroker::_t_osr_compilation;
+ elapsedTimer total_compilation = CompileBroker::_t_total_compilation;
+
+ int standard_bytes_compiled = CompileBroker::_sum_standard_bytes_compiled;
+ int osr_bytes_compiled = CompileBroker::_sum_osr_bytes_compiled;
+
+ int standard_compile_count = CompileBroker::_total_standard_compile_count;
+ int osr_compile_count = CompileBroker::_total_osr_compile_count;
+ int total_compile_count = CompileBroker::_total_compile_count;
+
+ int nmethods_size = CompileBroker::_sum_nmethod_code_size;
+ int nmethods_code_size = CompileBroker::_sum_nmethod_size;
+#endif // INCLUDE_JVMCI
+
+ if (!aggregate) {
+ return;
+ }
tty->cr();
tty->print_cr("Accumulated compiler times");
tty->print_cr("----------------------------------------------------------");
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
- tty->print_cr(" Total compilation time : %7.3f s", CompileBroker::_t_total_compilation.seconds());
+ tty->print_cr(" Total compilation time : %7.3f s", total_compilation.seconds());
tty->print_cr(" Standard compilation : %7.3f s, Average : %2.3f s",
- CompileBroker::_t_standard_compilation.seconds(),
- CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
+ standard_compilation.seconds(),
+ standard_compilation.seconds() / standard_compile_count);
tty->print_cr(" Bailed out compilation : %7.3f s, Average : %2.3f s",
CompileBroker::_t_bailedout_compilation.seconds(),
CompileBroker::_t_bailedout_compilation.seconds() / CompileBroker::_total_bailout_count);
tty->print_cr(" On stack replacement : %7.3f s, Average : %2.3f s",
- CompileBroker::_t_osr_compilation.seconds(),
- CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
+ osr_compilation.seconds(),
+ osr_compilation.seconds() / osr_compile_count);
tty->print_cr(" Invalidated : %7.3f s, Average : %2.3f s",
CompileBroker::_t_invalidated_compilation.seconds(),
CompileBroker::_t_invalidated_compilation.seconds() / CompileBroker::_total_invalidated_count);
@@ -2038,18 +2230,19 @@
comp->print_timers();
}
tty->cr();
- tty->print_cr(" Total compiled methods : %8d methods", CompileBroker::_total_compile_count);
- tty->print_cr(" Standard compilation : %8d methods", CompileBroker::_total_standard_compile_count);
- tty->print_cr(" On stack replacement : %8d methods", CompileBroker::_total_osr_compile_count);
- int tcb = CompileBroker::_sum_osr_bytes_compiled + CompileBroker::_sum_standard_bytes_compiled;
+ tty->print_cr(" Total compiled methods : %8d methods", total_compile_count);
+ tty->print_cr(" Standard compilation : %8d methods", standard_compile_count);
+ tty->print_cr(" On stack replacement : %8d methods", osr_compile_count);
+ int tcb = osr_bytes_compiled + standard_bytes_compiled;
tty->print_cr(" Total compiled bytecodes : %8d bytes", tcb);
- tty->print_cr(" Standard compilation : %8d bytes", CompileBroker::_sum_standard_bytes_compiled);
- tty->print_cr(" On stack replacement : %8d bytes", CompileBroker::_sum_osr_bytes_compiled);
- int bps = (int)(tcb / CompileBroker::_t_total_compilation.seconds());
+ tty->print_cr(" Standard compilation : %8d bytes", standard_bytes_compiled);
+ tty->print_cr(" On stack replacement : %8d bytes", osr_bytes_compiled);
+ double tcs = total_compilation.seconds();
+ int bps = tcs == 0.0 ? 0 : (int)(tcb / tcs);
tty->print_cr(" Average compilation speed : %8d bytes/s", bps);
tty->cr();
- tty->print_cr(" nmethod code size : %8d bytes", CompileBroker::_sum_nmethod_code_size);
- tty->print_cr(" nmethod total size : %8d bytes", CompileBroker::_sum_nmethod_size);
+ tty->print_cr(" nmethod code size : %8d bytes", nmethods_code_size);
+ tty->print_cr(" nmethod total size : %8d bytes", nmethods_size);
}
// Debugging output for failure
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -29,6 +29,7 @@
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileTask.hpp"
#include "runtime/perfData.hpp"
+#include "trace/tracing.hpp"
class nmethod;
class nmethodLocker;
@@ -243,6 +244,7 @@
static void wait_for_completion(CompileTask* task);
static void invoke_compiler_on_method(CompileTask* task);
+ static void post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env);
static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
static void push_jni_handle_block();
static void pop_jni_handle_block();
@@ -288,6 +290,9 @@
int hot_count,
const char* comment, Thread* thread);
+ // Acquire any needed locks and assign a compile id
+ static uint assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci);
+
static void compiler_thread_loop();
static uint get_compilation_id() { return _compilation_id; }
@@ -336,8 +341,13 @@
// Redefine Classes support
static void mark_on_stack();
+#if INCLUDE_JVMCI
+ // Print curent compilation time stats for a given compiler
+ static void print_times(AbstractCompiler* comp);
+#endif
+
// Print a detailed accounting of compilation time
- static void print_times();
+ static void print_times(bool per_compiler = true, bool aggregate = true);
// Debugging output for failure
static void print_last_compile();
--- a/hotspot/src/share/vm/compiler/compileTask.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -183,6 +183,10 @@
if (!short_form) {
st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
}
+ // print compiler name if requested
+ if (CIPrintCompilerName) {
+ st->print("%s:", CompileBroker::compiler_name(comp_level));
+ }
st->print("%4d ", compile_id); // print compilation number
// For unloaded methods the transition to zombie occurs after the
@@ -271,7 +275,8 @@
if (_osr_bci != CompileBroker::standard_entry_bci) {
log->print(" osr_bci='%d'", _osr_bci);
}
- if (_comp_level != CompLevel_highest_tier) {
+ // Always print the level in tiered.
+ if (_comp_level != CompLevel_highest_tier || TieredCompilation) {
log->print(" level='%d'", _comp_level);
}
if (_is_blocking) {
@@ -307,6 +312,24 @@
// ------------------------------------------------------------------
+// CompileTask::log_task_dequeued
+void CompileTask::log_task_dequeued(const char* comment) {
+ if (LogCompilation && xtty != NULL) {
+ Thread* thread = Thread::current();
+ ttyLocker ttyl;
+ ResourceMark rm(thread);
+
+ xtty->begin_elem("task_dequeued");
+ log_task(xtty);
+ if (comment != NULL) {
+ xtty->print(" comment='%s'", comment);
+ }
+ xtty->end_elem();
+ }
+}
+
+
+// ------------------------------------------------------------------
// CompileTask::log_task_start
void CompileTask::log_task_start(CompileLog* log) {
log->begin_head("task");
--- a/hotspot/src/share/vm/compiler/compileTask.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileTask.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -133,6 +133,7 @@
void log_task(xmlStream* log);
void log_task_queued();
+ void log_task_dequeued(const char* comment);
void log_task_start(CompileLog* log);
void log_task_done(CompileLog* log);
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -487,8 +487,14 @@
void Disassembler::decode(CodeBlob* cb, outputStream* st) {
if (!load_library()) return;
+ if (cb->is_nmethod()) {
+ decode((nmethod*)cb, st);
+ return;
+ }
decode_env env(cb, st);
- env.output()->print_cr("Decoding CodeBlob " PTR_FORMAT, cb);
+ env.output()->print_cr("----------------------------------------------------------------------");
+ env.output()->print_cr("%s", cb->name());
+ env.output()->print_cr(" at [" PTR_FORMAT ", " PTR_FORMAT "] %d bytes", cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*));
env.decode_instructions(cb->code_begin(), cb->code_end());
}
@@ -501,8 +507,7 @@
void Disassembler::decode(nmethod* nm, outputStream* st) {
if (!load_library()) return;
decode_env env(nm, st);
- env.output()->print_cr("Decoding compiled method " PTR_FORMAT ":", nm);
- env.output()->print_cr("Code:");
+ env.output()->print_cr("----------------------------------------------------------------------");
#ifdef SHARK
SharkEntry* entry = (SharkEntry *) nm->code_begin();
@@ -513,6 +518,21 @@
unsigned char* end = nm->code_end();
#endif // SHARK
+ nm->method()->method_holder()->name()->print_symbol_on(env.output());
+ env.output()->print(".");
+ nm->method()->name()->print_symbol_on(env.output());
+ nm->method()->signature()->print_symbol_on(env.output());
+#if INCLUDE_JVMCI
+ {
+ char buffer[O_BUFLEN];
+ char* jvmciName = nm->jvmci_installed_code_name(buffer, O_BUFLEN);
+ if (jvmciName != NULL) {
+ env.output()->print(" (%s)", jvmciName);
+ }
+ }
+#endif
+ env.output()->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT "] %d bytes", p, end, ((jlong)(end - p)));
+
// If there has been profiling, print the buckets.
if (FlatProfiler::bucket_start_for(p) != NULL) {
unsigned char* p1 = p;
--- a/hotspot/src/share/vm/compiler/oopMap.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/oopMap.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -39,6 +39,9 @@
#ifdef COMPILER2
#include "opto/optoreg.hpp"
#endif
+#ifdef SPARC
+#include "vmreg_sparc.inline.hpp"
+#endif
// OopMapStream
@@ -272,10 +275,15 @@
static void add_derived_oop(oop* base, oop* derived) {
#ifndef TIERED
COMPILER1_PRESENT(ShouldNotReachHere();)
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ ShouldNotReachHere();
+ }
+#endif
#endif // TIERED
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
DerivedPointerTable::add(derived, base);
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
}
@@ -284,7 +292,7 @@
// Print oopmap and regmap
tty->print_cr("------ ");
CodeBlob* cb = fr->cb();
- ImmutableOopMapSet* maps = cb->oop_maps();
+ const ImmutableOopMapSet* maps = cb->oop_maps();
const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
map->print();
if( cb->is_nmethod() ) {
@@ -321,7 +329,7 @@
NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
- ImmutableOopMapSet* maps = cb->oop_maps();
+ const ImmutableOopMapSet* maps = cb->oop_maps();
const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
assert(map != NULL, "no ptr map found");
@@ -333,6 +341,11 @@
if (!oms.is_done()) {
#ifndef TIERED
COMPILER1_PRESENT(ShouldNotReachHere();)
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ ShouldNotReachHere();
+ }
+#endif
#endif // !TIERED
// Protect the operation on the derived pointers. This
// protects the addition of derived pointers to the shared
@@ -448,7 +461,7 @@
// Check that runtime stubs save all callee-saved registers
#ifdef COMPILER2
- assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
+ assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() ||
(nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
"must save all");
#endif // COMPILER2
@@ -462,13 +475,18 @@
bool ImmutableOopMap::has_derived_pointer() const {
#ifndef TIERED
COMPILER1_PRESENT(return false);
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ return false;
+ }
+#endif
#endif // !TIERED
-#ifdef COMPILER2
- OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ OopMapStream oms(this,OopMapValue::derived_oop_value);
return oms.is_done();
#else
return false;
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
}
#endif //PRODUCT
@@ -601,74 +619,9 @@
}
#endif
-class ImmutableOopMapBuilder {
-private:
- class Mapping;
-
-private:
- const OopMapSet* _set;
- const OopMap* _empty;
- const OopMap* _last;
- int _empty_offset;
- int _last_offset;
- int _offset;
- Mapping* _mapping;
- ImmutableOopMapSet* _new_set;
-
- /* Used for bookkeeping when building ImmutableOopMaps */
- class Mapping : public ResourceObj {
- public:
- enum kind_t { OOPMAP_UNKNOWN = 0, OOPMAP_NEW = 1, OOPMAP_EMPTY = 2, OOPMAP_DUPLICATE = 3 };
-
- kind_t _kind;
- int _offset;
- int _size;
- const OopMap* _map;
- const OopMap* _other;
-
- Mapping() : _kind(OOPMAP_UNKNOWN), _offset(-1), _size(-1), _map(NULL) {}
-
- void set(kind_t kind, int offset, int size, const OopMap* map = 0, const OopMap* other = 0) {
- _kind = kind;
- _offset = offset;
- _size = size;
- _map = map;
- _other = other;
- }
- };
-
-public:
- ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0) {
- _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
- }
-
- int heap_size();
- ImmutableOopMapSet* build();
-private:
- bool is_empty(const OopMap* map) const {
- return map->count() == 0;
- }
-
- bool is_last_duplicate(const OopMap* map) {
- if (_last != NULL && _last->count() > 0 && _last->equals(map)) {
- return true;
- }
- return false;
- }
-
-#ifdef ASSERT
- void verify(address buffer, int size, const ImmutableOopMapSet* set);
-#endif
-
- bool has_empty() const {
- return _empty_offset != -1;
- }
-
- int size_for(const OopMap* map) const;
- void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set);
- int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set);
- void fill(ImmutableOopMapSet* set, int size);
-};
+ImmutableOopMapBuilder::ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0), _required(-1) {
+ _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
+}
int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
@@ -713,6 +666,7 @@
int total = base + pairs + _offset;
DEBUG_ONLY(total += 8);
+ _required = total;
return total;
}
@@ -764,19 +718,23 @@
}
#endif
+ImmutableOopMapSet* ImmutableOopMapBuilder::generate_into(address buffer) {
+ DEBUG_ONLY(memset(&buffer[_required-8], 0xff, 8));
+
+ _new_set = new (buffer) ImmutableOopMapSet(_set, _required);
+ fill(_new_set, _required);
+
+ DEBUG_ONLY(verify(buffer, _required, _new_set));
+
+ return _new_set;
+}
+
ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
- int required = heap_size();
+ _required = heap_size();
// We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
- address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, required, mtCode);
- DEBUG_ONLY(memset(&buffer[required-8], 0xff, 8));
-
- _new_set = new (buffer) ImmutableOopMapSet(_set, required);
- fill(_new_set, required);
-
- DEBUG_ONLY(verify(buffer, required, _new_set));
-
- return _new_set;
+ address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);
+ return generate_into(buffer);
}
ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
@@ -788,7 +746,7 @@
//------------------------------DerivedPointerTable---------------------------
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
class DerivedPointerEntry : public CHeapObj<mtCompiler> {
private:
@@ -881,4 +839,4 @@
_active = false;
}
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
--- a/hotspot/src/share/vm/compiler/oopMap.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/compiler/oopMap.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, 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
@@ -184,6 +184,8 @@
void copy_data_to(address addr) const;
OopMap* deep_copy();
+ bool has_derived_pointer() const PRODUCT_RETURN0;
+
bool legal_vm_reg_name(VMReg local) {
return OopMapValue::legal_vm_reg_name(local);
}
@@ -350,13 +352,82 @@
#endif
};
+class ImmutableOopMapBuilder {
+private:
+ class Mapping;
+
+private:
+ const OopMapSet* _set;
+ const OopMap* _empty;
+ const OopMap* _last;
+ int _empty_offset;
+ int _last_offset;
+ int _offset;
+ int _required;
+ Mapping* _mapping;
+ ImmutableOopMapSet* _new_set;
+
+ /* Used for bookkeeping when building ImmutableOopMaps */
+ class Mapping : public ResourceObj {
+ public:
+ enum kind_t { OOPMAP_UNKNOWN = 0, OOPMAP_NEW = 1, OOPMAP_EMPTY = 2, OOPMAP_DUPLICATE = 3 };
+
+ kind_t _kind;
+ int _offset;
+ int _size;
+ const OopMap* _map;
+ const OopMap* _other;
+
+ Mapping() : _kind(OOPMAP_UNKNOWN), _offset(-1), _size(-1), _map(NULL) {}
+
+ void set(kind_t kind, int offset, int size, const OopMap* map = 0, const OopMap* other = 0) {
+ _kind = kind;
+ _offset = offset;
+ _size = size;
+ _map = map;
+ _other = other;
+ }
+ };
+
+public:
+ ImmutableOopMapBuilder(const OopMapSet* set);
+
+ int heap_size();
+ ImmutableOopMapSet* build();
+ ImmutableOopMapSet* generate_into(address buffer);
+private:
+ bool is_empty(const OopMap* map) const {
+ return map->count() == 0;
+ }
+
+ bool is_last_duplicate(const OopMap* map) {
+ if (_last != NULL && _last->count() > 0 && _last->equals(map)) {
+ return true;
+ }
+ return false;
+ }
+
+#ifdef ASSERT
+ void verify(address buffer, int size, const ImmutableOopMapSet* set);
+#endif
+
+ bool has_empty() const {
+ return _empty_offset != -1;
+ }
+
+ int size_for(const OopMap* map) const;
+ void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set);
+ int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set);
+ void fill(ImmutableOopMapSet* set, int size);
+};
+
// Derived pointer support. This table keeps track of all derived points on a
// stack. It is cleared before each scavenge/GC. During the traversal of all
// oops, it is filled in with references to all locations that contains a
// derived oop (assumed to be very few). When the GC is complete, the derived
// pointers are updated based on their base pointers new value and an offset.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
class DerivedPointerTable : public AllStatic {
friend class VMStructs;
private:
@@ -392,6 +463,6 @@
}
}
};
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
#endif // SHARE_VM_COMPILER_OOPMAP_HPP
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -2367,7 +2367,9 @@
// way with the marking information used by GC.
NoRefDiscovery no_discovery(ref_processor());
- COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTableDeactivate dpt_deact;
+#endif
// Clear any marks from a previous round
verification_mark_bm()->clear_all();
@@ -2987,7 +2989,9 @@
}
{
- COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTableDeactivate dpt_deact;
+#endif
if (CMSParallelInitialMarkEnabled) {
// The parallel version.
WorkGang* workers = gch->workers();
@@ -4316,7 +4320,9 @@
}
{
- COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTableDeactivate dpt_deact;
+#endif
// Note on the role of the mod union table:
// Since the marker in "markFromRoots" marks concurrently with
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1507,7 +1507,9 @@
check_bitmaps("Full GC Start");
pre_full_gc_dump(gc_timer);
- COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::clear();
+#endif
// Disable discovery and empty the discovered lists
// for the CM ref processor.
@@ -1567,7 +1569,9 @@
// not been removed from the discovered lists.
ref_processor_stw()->enqueue_discovered_references();
- COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::update_pointers();
+#endif
MemoryService::track_memory_usage();
@@ -3630,8 +3634,9 @@
// FIXME: what is this about?
// I'm ignoring the "fill_newgen()" call if "alloc_event_enabled"
// is set.
- COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(),
- "derived pointer present"));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ assert(DerivedPointerTable::is_empty(), "derived pointer present");
+#endif
// always_do_update_barrier = true;
resize_all_tlabs();
@@ -4037,7 +4042,9 @@
check_bitmaps("GC Start");
- COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::clear();
+#endif
// Please see comment in g1CollectedHeap.hpp and
// G1CollectedHeap::ref_processing_init() to see how
@@ -5666,7 +5673,9 @@
enqueue_discovered_references(per_thread_states);
redirty_logged_cards();
- COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::update_pointers();
+#endif
}
void G1CollectedHeap::record_obj_copy_mem_stats() {
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -93,8 +93,10 @@
mark_sweep_phase2();
+#if defined(COMPILER2) || INCLUDE_JVMCI
// Don't add any more derived pointers during phase3
- COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+ DerivedPointerTable::set_active(false);
+#endif
mark_sweep_phase3();
@@ -168,7 +170,9 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTableDeactivate dpt_deact;
+#endif
g1h->prepare_for_verify();
// Note: we can verify only the heap here. When an object is
// marked, the previous value of the mark word (including
--- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -247,3 +247,52 @@
}
}
}
+
+void G1SATBCardTableModRefBS::write_ref_nmethod_post(oop* dst, nmethod* nm) {
+ oop obj = oopDesc::load_heap_oop(dst);
+ if (obj != NULL) {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ HeapRegion* hr = g1h->heap_region_containing(obj);
+ hr->add_strong_code_root(nm);
+ }
+}
+
+class G1EnsureLastRefToRegion : public OopClosure {
+ G1CollectedHeap* _g1h;
+ HeapRegion* _hr;
+ oop* _dst;
+
+ bool _value;
+public:
+ G1EnsureLastRefToRegion(G1CollectedHeap* g1h, HeapRegion* hr, oop* dst) :
+ _g1h(g1h), _hr(hr), _dst(dst), _value(true) {}
+
+ void do_oop(oop* p) {
+ if (_value && p != _dst) {
+ oop obj = oopDesc::load_heap_oop(p);
+ if (obj != NULL) {
+ HeapRegion* hr = _g1h->heap_region_containing(obj);
+ if (hr == _hr) {
+ // Another reference to the same region.
+ _value = false;
+ }
+ }
+ }
+ }
+ void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+ bool value() const { return _value; }
+};
+
+void G1SATBCardTableModRefBS::write_ref_nmethod_pre(oop* dst, nmethod* nm) {
+ oop obj = oopDesc::load_heap_oop(dst);
+ if (obj != NULL) {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ HeapRegion* hr = g1h->heap_region_containing(obj);
+ G1EnsureLastRefToRegion ensure_last_ref(g1h, hr, dst);
+ nm->oops_do(&ensure_last_ref);
+ if (ensure_last_ref.value()) {
+ // Last reference to this region, remove the nmethod from the rset.
+ hr->remove_strong_code_root(nm);
+ }
+ }
+}
--- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -38,6 +38,7 @@
// snapshot-at-the-beginning marking.
class G1SATBCardTableModRefBS: public CardTableModRefBS {
+ friend class VMStructs;
protected:
enum G1CardValues {
g1_young_gen = CT_MR_BS_last_reserved << 1
@@ -122,6 +123,9 @@
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
+ virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm);
+ virtual void write_ref_nmethod_post(oop* dst, nmethod* nm);
+
};
template<>
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -189,7 +189,9 @@
allocate_stacks();
- COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::clear();
+#endif
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_softrefs);
@@ -198,9 +200,11 @@
mark_sweep_phase2();
+#if defined(COMPILER2) || INCLUDE_JVMCI
// Don't add any more derived pointers during phase3
- COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
- COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+ assert(DerivedPointerTable::is_active(), "Sanity");
+ DerivedPointerTable::set_active(false);
+#endif
mark_sweep_phase3();
@@ -245,7 +249,9 @@
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
- COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::update_pointers();
+#endif
ref_processor()->enqueue_discovered_references(NULL);
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1045,7 +1045,9 @@
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
- COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::update_pointers();
+#endif
ref_processor()->enqueue_discovered_references(NULL);
@@ -2042,7 +2044,9 @@
CodeCache::gc_prologue();
- COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::clear();
+#endif
ref_processor()->enable_discovery();
ref_processor()->setup_policy(maximum_heap_compaction);
@@ -2056,8 +2060,10 @@
&& GCCause::is_user_requested_gc(gc_cause);
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
- COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
- COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ assert(DerivedPointerTable::is_active(), "Sanity");
+ DerivedPointerTable::set_active(false);
+#endif
// adjust_roots() updates Universe::_intArrayKlassObj which is
// needed by the compaction for filling holes in the dense prefix.
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -351,7 +351,9 @@
}
save_to_space_top_before_gc();
- COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::clear();
+#endif
reference_processor()->enable_discovery();
reference_processor()->setup_policy(false);
@@ -623,7 +625,9 @@
assert(young_gen->to_space()->is_empty(), "to space should be empty now");
}
- COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ DerivedPointerTable::update_pointers();
+#endif
NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -96,8 +96,10 @@
mark_sweep_phase2();
// Don't add any more derived pointers during phase3
- COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
- COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ assert(DerivedPointerTable::is_active(), "Sanity");
+ DerivedPointerTable::set_active(false);
+#endif
mark_sweep_phase3();
--- a/hotspot/src/share/vm/gc/shared/barrierSet.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -188,6 +188,9 @@
static void static_write_ref_array_pre(HeapWord* start, size_t count);
static void static_write_ref_array_post(HeapWord* start, size_t count);
+ virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm) {}
+ virtual void write_ref_nmethod_post(oop* dst, nmethod* nm) {}
+
protected:
virtual void write_ref_array_work(MemRegion mr) = 0;
public:
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -349,7 +349,7 @@
guarantee(obj == NULL || (HeapWord*)obj >= _boundary,
err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
"clean card crosses boundary" PTR_FORMAT,
- p2i((HeapWord*)obj), p2i(jp), p2i(_boundary)));
+ p2i(obj), p2i(jp), p2i(_boundary)));
}
public:
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -231,7 +231,7 @@
void CollectedHeap::pre_initialize() {
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
// otherwise remains unused.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
_defer_initial_card_mark = ReduceInitialCardMarks && can_elide_tlab_store_barriers()
&& (DeferInitialCardMark || card_mark_must_follow_store());
#else
@@ -539,7 +539,7 @@
" to threads list is doomed to failure!");
for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
// The deferred store barriers must all have been flushed to the
// card-table (or other remembered set structure) before GC starts
// processing the card-table (or other remembered set).
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -90,7 +90,8 @@
GCHeapLog* _gc_heap_log;
- // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 is being used
+ // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
+ // or INCLUDE_JVMCI is being used
bool _defer_initial_card_mark;
MemRegion _reserved;
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1224,11 +1224,11 @@
};
void GenCollectedHeap::gc_epilogue(bool full) {
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
resize_all_tlabs();
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -54,8 +54,11 @@
java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
_always_clear_soft_ref_policy = new AlwaysClearPolicy();
- _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
- NOT_COMPILER2(LRUCurrentHeapPolicy());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ _default_soft_ref_policy = new LRUMaxHeapPolicy();
+#else
+ _default_soft_ref_policy = new LRUCurrentHeapPolicy();
+#endif
if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
vm_exit_during_initialization("Could not allocate reference policy object");
}
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -459,11 +459,11 @@
address AbstractInterpreter::deopt_reexecute_entry(Method* method, address bcp) {
assert(method->contains(bcp), "just checkin'");
Bytecodes::Code code = Bytecodes::java_code_at(method, bcp);
-#ifdef COMPILER1
+#if defined(COMPILER1) || INCLUDE_JVMCI
if(code == Bytecodes::_athrow ) {
return Interpreter::rethrow_exception_entry();
}
-#endif /* COMPILER1 */
+#endif /* COMPILER1 || INCLUDE_JVMCI */
return Interpreter::deopt_entry(vtos, 0);
}
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -481,6 +481,17 @@
}
} while (should_repeat == true);
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler && h_method->method_data() != NULL) {
+ ResourceMark rm(thread);
+ ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci, NULL);
+ if (pdata != NULL && pdata->is_BitData()) {
+ BitData* bit_data = (BitData*) pdata;
+ bit_data->set_exception_seen();
+ }
+ }
+#endif
+
// notify JVMTI of an exception throw; JVMTI will detect if this is a first
// time throw or a stack unwinding throw and accordingly notify the debugger
if (JvmtiExport::can_post_on_exceptions()) {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -124,7 +124,7 @@
// Note: with several active threads, the must_be_compiled may be true
// while can_be_compiled is false; remove assert
// assert(CompilationPolicy::can_be_compiled(selected_method), "cannot compile");
- if (THREAD->is_Compiler_thread()) {
+ if (!THREAD->can_call_java()) {
// don't force compilation, resolve was on behalf of compiler
return;
}
@@ -450,7 +450,7 @@
}
return result;
} else if (iid == vmIntrinsics::_invokeGeneric
- && !THREAD->is_Compiler_thread()
+ && THREAD->can_call_java()
&& appendix_result_or_null != NULL) {
// This is a method with type-checking semantics.
// We will ask Java code to spin an adapter method for it.
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -174,9 +174,11 @@
static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
Handle *appendix_result_or_null,
Handle *method_type_result, TRAPS);
+ JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod()
// Not Linktime so doesn't take LinkInfo
static methodHandle lookup_instance_method_in_klasses (
KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+ JVMCI_ONLY(private:)
// Similar loader constraint checking functions that throw
// LinkageError with descriptive message.
--- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -59,6 +59,8 @@
address generate_safept_entry_for(TosState state, address runtime_entry);
void generate_throw_exception();
+ void lock_method();
+
// Instruction generation
void generate_and_dispatch (Template* t, TosState tos_out = ilgl);
void set_vtos_entry_points (Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/defaultStream.hpp"
+
+Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose) {
+ if (!EnableJVMCI) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
+Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose) {
+ if (!EnableJVMCI) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
+#define SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+/*
+ * Here we have JVMCI arguments constraints functions, which are called automatically
+ * whenever flag's value changes. If the constraint fails the function should return
+ * an appropriate error value.
+ */
+
+Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose);
+Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose);
+
+#endif /* SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#include "precompiled.hpp"
+#include "code/compiledIC.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+#ifdef TARGET_ARCH_x86
+# include "vmreg_x86.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "vmreg_sparc.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "vmreg_zero.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "vmreg_arm.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "vmreg_ppc.inline.hpp"
+#endif
+
+
+// frequently used constants
+// Allocate them with new so they are never destroyed (otherwise, a
+// forced exit could destroy these objects while they are still in
+// use).
+ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
+ConstantIntValue* CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
+ConstantIntValue* CodeInstaller::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
+ConstantIntValue* CodeInstaller::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
+ConstantIntValue* CodeInstaller::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
+LocationValue* CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
+
+Method* getMethodFromHotSpotMethod(oop hotspot_method) {
+ assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass()), "sanity");
+ return CompilerToVM::asMethod(hotspot_method);
+}
+
+VMReg getVMRegFromLocation(oop location, int total_frame_size) {
+ oop reg = code_Location::reg(location);
+ jint offset = code_Location::offset(location);
+
+ if (reg != NULL) {
+ // register
+ jint number = code_Register::number(reg);
+ VMReg vmReg = CodeInstaller::get_hotspot_reg(number);
+ assert(offset % 4 == 0, "must be aligned");
+ return vmReg->next(offset / 4);
+ } else {
+ // stack slot
+ assert(offset % 4 == 0, "must be aligned");
+ return VMRegImpl::stack2reg(offset / 4);
+ }
+}
+
+// creates a HotSpot oop map out of the byte arrays provided by DebugInfo
+OopMap* CodeInstaller::create_oop_map(oop debug_info) {
+ oop reference_map = DebugInfo::referenceMap(debug_info);
+ if (HotSpotReferenceMap::maxRegisterSize(reference_map) > 16) {
+ _has_wide_vector = true;
+ }
+ OopMap* map = new OopMap(_total_frame_size, _parameter_count);
+ objArrayOop objects = HotSpotReferenceMap::objects(reference_map);
+ objArrayOop derivedBase = HotSpotReferenceMap::derivedBase(reference_map);
+ typeArrayOop sizeInBytes = HotSpotReferenceMap::sizeInBytes(reference_map);
+ for (int i = 0; i < objects->length(); i++) {
+ oop location = objects->obj_at(i);
+ oop baseLocation = derivedBase->obj_at(i);
+ int bytes = sizeInBytes->int_at(i);
+
+ VMReg vmReg = getVMRegFromLocation(location, _total_frame_size);
+ if (baseLocation != NULL) {
+ // derived oop
+ assert(bytes == 8, "derived oop can't be compressed");
+ VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size);
+ map->set_derived_oop(vmReg, baseReg);
+ } else if (bytes == 8) {
+ // wide oop
+ map->set_oop(vmReg);
+ } else {
+ // narrow oop
+ assert(bytes == 4, "wrong size");
+ map->set_narrowoop(vmReg);
+ }
+ }
+
+ oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
+ if (callee_save_info != NULL) {
+ objArrayOop registers = RegisterSaveLayout::registers(callee_save_info);
+ typeArrayOop slots = RegisterSaveLayout::slots(callee_save_info);
+ for (jint i = 0; i < slots->length(); i++) {
+ oop jvmci_reg = registers->obj_at(i);
+ jint jvmci_reg_number = code_Register::number(jvmci_reg);
+ VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number);
+ // HotSpot stack slots are 4 bytes
+ jint jvmci_slot = slots->int_at(i);
+ jint hotspot_slot = jvmci_slot * VMRegImpl::slots_per_word;
+ VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot);
+ map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg);
+#ifdef _LP64
+ // (copied from generate_oop_map() in c1_Runtime1_x86.cpp)
+ VMReg hotspot_slot_hi_as_reg = VMRegImpl::stack2reg(hotspot_slot + 1);
+ map->set_callee_saved(hotspot_slot_hi_as_reg, hotspot_reg->next());
+#endif
+ }
+ }
+ return map;
+}
+
+static void record_metadata_reference(oop obj, jlong prim, jboolean compressed, OopRecorder* oop_recorder) {
+ if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
+ Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+ if (compressed) {
+ assert(Klass::decode_klass((narrowKlass) prim) == klass, err_msg("%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim));
+ } else {
+ assert((Klass*) prim == klass, err_msg("%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim));
+ }
+ int index = oop_recorder->find_index(klass);
+ TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string());
+ } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj);
+ assert(!compressed, err_msg("unexpected compressed method pointer %s @ " INTPTR_FORMAT " = " PTR64_FORMAT, method->name()->as_C_string(), p2i(method), prim));
+ int index = oop_recorder->find_index(method);
+ TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string());
+ } else {
+ assert(java_lang_String::is_instance(obj),
+ err_msg("unexpected metadata reference (%s) for constant " JLONG_FORMAT " (" PTR64_FORMAT ")", obj->klass()->name()->as_C_string(), prim, prim));
+ }
+}
+
+// Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectTypeImpl.klass()).
+static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) {
+ if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+ oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
+ jlong prim = HotSpotMetaspaceConstantImpl::primitive(constant);
+ assert(obj != NULL, "must have an object");
+ assert(prim != 0, "must have a primitive value");
+
+ record_metadata_reference(obj, prim, false, oop_recorder);
+ }
+}
+
+static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) {
+ record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder);
+}
+
+Location::Type CodeInstaller::get_oop_type(oop value) {
+ oop lirKind = Value::lirKind(value);
+ oop platformKind = LIRKind::platformKind(lirKind);
+ assert(LIRKind::referenceMask(lirKind) == 1, "unexpected referenceMask");
+
+ if (platformKind == word_kind()) {
+ return Location::oop;
+ } else {
+ return Location::narrowoop;
+ }
+}
+
+ScopeValue* CodeInstaller::get_scope_value(oop value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) {
+ second = NULL;
+ if (value == Value::ILLEGAL()) {
+ assert(type == T_ILLEGAL, "expected legal value");
+ return _illegal_value;
+ } else if (value->is_a(RegisterValue::klass())) {
+ oop reg = RegisterValue::reg(value);
+ jint number = code_Register::number(reg);
+ VMReg hotspotRegister = get_hotspot_reg(number);
+ if (is_general_purpose_reg(hotspotRegister)) {
+ Location::Type locationType;
+ if (type == T_OBJECT) {
+ locationType = get_oop_type(value);
+ } else if (type == T_LONG) {
+ locationType = Location::lng;
+ } else {
+ assert(type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN, "unexpected type in cpu register");
+ locationType = Location::int_in_long;
+ }
+ ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister));
+ if (type == T_LONG) {
+ second = value;
+ }
+ return value;
+ } else {
+ assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register");
+ Location::Type locationType;
+ if (type == T_FLOAT) {
+ // this seems weird, but the same value is used in c1_LinearScan
+ locationType = Location::normal;
+ } else {
+ locationType = Location::dbl;
+ }
+ ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister));
+ if (type == T_DOUBLE) {
+ second = value;
+ }
+ return value;
+ }
+ } else if (value->is_a(StackSlot::klass())) {
+ jint offset = StackSlot::offset(value);
+ if (StackSlot::addFrameSize(value)) {
+ offset += _total_frame_size;
+ }
+
+ Location::Type locationType;
+ if (type == T_OBJECT) {
+ locationType = get_oop_type(value);
+ } else if (type == T_LONG) {
+ locationType = Location::lng;
+ } else if (type == T_DOUBLE) {
+ locationType = Location::dbl;
+ } else {
+ assert(type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN, "unexpected type in stack slot");
+ locationType = Location::normal;
+ }
+ ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset));
+ if (type == T_DOUBLE || type == T_LONG) {
+ second = value;
+ }
+ return value;
+ } else if (value->is_a(JavaConstant::klass())) {
+ record_metadata_in_constant(value, _oop_recorder);
+ if (value->is_a(PrimitiveConstant::klass())) {
+ if (value->is_a(RawConstant::klass())) {
+ jlong prim = PrimitiveConstant::primitive(value);
+ return new ConstantLongValue(prim);
+ } else {
+ assert(type == JVMCIRuntime::kindToBasicType(JavaKind::typeChar(PrimitiveConstant::kind(value))), "primitive constant type doesn't match");
+ if (type == T_INT || type == T_FLOAT) {
+ jint prim = (jint)PrimitiveConstant::primitive(value);
+ switch (prim) {
+ case -1: return _int_m1_scope_value;
+ case 0: return _int_0_scope_value;
+ case 1: return _int_1_scope_value;
+ case 2: return _int_2_scope_value;
+ default: return new ConstantIntValue(prim);
+ }
+ } else {
+ assert(type == T_LONG || type == T_DOUBLE, "unexpected primitive constant type");
+ jlong prim = PrimitiveConstant::primitive(value);
+ second = _int_1_scope_value;
+ return new ConstantLongValue(prim);
+ }
+ }
+ } else {
+ assert(type == T_OBJECT, "unexpected object constant");
+ if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) {
+ return _oop_null_scope_value;
+ } else {
+ assert(value->is_a(HotSpotObjectConstantImpl::klass()), "unexpected constant type");
+ oop obj = HotSpotObjectConstantImpl::object(value);
+ assert(obj != NULL, "null value must be in NullConstant");
+ return new ConstantOopWriteValue(JNIHandles::make_local(obj));
+ }
+ }
+ } else if (value->is_a(VirtualObject::klass())) {
+ assert(type == T_OBJECT, "unexpected virtual object");
+ int id = VirtualObject::id(value);
+ ScopeValue* object = objects->at(id);
+ assert(object != NULL, "missing value");
+ return object;
+ } else {
+ value->klass()->print();
+ value->print();
+ }
+ ShouldNotReachHere();
+ return NULL;
+}
+
+void CodeInstaller::record_object_value(ObjectValue* sv, oop value, GrowableArray<ScopeValue*>* objects) {
+ oop type = VirtualObject::type(value);
+ int id = VirtualObject::id(value);
+ oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+ Klass* klass = java_lang_Class::as_Klass(javaMirror);
+ bool isLongArray = klass == Universe::longArrayKlassObj();
+
+ objArrayOop values = VirtualObject::values(value);
+ objArrayOop slotKinds = VirtualObject::slotKinds(value);
+ for (jint i = 0; i < values->length(); i++) {
+ ScopeValue* cur_second = NULL;
+ oop object = values->obj_at(i);
+ oop kind = slotKinds->obj_at(i);
+ BasicType type = JVMCIRuntime::kindToBasicType(JavaKind::typeChar(kind));
+ ScopeValue* value = get_scope_value(object, type, objects, cur_second);
+
+ if (isLongArray && cur_second == NULL) {
+ // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
+ // add an int 0 constant
+ cur_second = _int_0_scope_value;
+ }
+
+ if (cur_second != NULL) {
+ sv->field_values()->append(cur_second);
+ }
+ assert(value != NULL, "missing value");
+ sv->field_values()->append(value);
+ }
+}
+
+MonitorValue* CodeInstaller::get_monitor_value(oop value, GrowableArray<ScopeValue*>* objects) {
+ guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type StackLockValue");
+
+ ScopeValue* second = NULL;
+ ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), T_OBJECT, objects, second);
+ assert(second == NULL, "monitor cannot occupy two stack slots");
+
+ ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), T_LONG, objects, second);
+ assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
+ assert(lock_data_value->is_location(), "invalid monitor location");
+ Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
+
+ bool eliminated = false;
+ if (StackLockValue::eliminated(value)) {
+ eliminated = true;
+ }
+
+ return new MonitorValue(owner_value, lock_data_loc, eliminated);
+}
+
+void CodeInstaller::initialize_dependencies(oop compiled_code, OopRecorder* recorder) {
+ JavaThread* thread = JavaThread::current();
+ CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL;
+ _oop_recorder = recorder;
+ _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL);
+ objArrayHandle assumptions = HotSpotCompiledCode::assumptions(compiled_code);
+ if (!assumptions.is_null()) {
+ int length = assumptions->length();
+ for (int i = 0; i < length; ++i) {
+ Handle assumption = assumptions->obj_at(i);
+ if (!assumption.is_null()) {
+ if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
+ assumption_NoFinalizableSubclass(assumption);
+ } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
+ assumption_ConcreteSubtype(assumption);
+ } else if (assumption->klass() == Assumptions_LeafType::klass()) {
+ assumption_LeafType(assumption);
+ } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
+ assumption_ConcreteMethod(assumption);
+ } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
+ assumption_CallSiteTargetValue(assumption);
+ } else {
+ assumption->print();
+ fatal("unexpected Assumption subclass");
+ }
+ }
+ }
+ }
+ objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code);
+ if (!methods.is_null()) {
+ int length = methods->length();
+ for (int i = 0; i < length; ++i) {
+ Handle method_handle = methods->obj_at(i);
+ methodHandle method = getMethodFromHotSpotMethod(method_handle());
+
+ _dependencies->assert_evol_method(method());
+ }
+ }
+}
+
+RelocBuffer::~RelocBuffer() {
+ if (_buffer != NULL) {
+ FREE_C_HEAP_ARRAY(char, _buffer);
+ }
+}
+
+address RelocBuffer::begin() const {
+ if (_buffer != NULL) {
+ return (address) _buffer;
+ }
+ return (address) _static_buffer;
+}
+
+void RelocBuffer::set_size(size_t bytes) {
+ assert(bytes <= _size, "can't grow in size!");
+ _size = bytes;
+}
+
+void RelocBuffer::ensure_size(size_t bytes) {
+ assert(_buffer == NULL, "can only be used once");
+ assert(_size == 0, "can only be used once");
+ if (bytes >= RelocBuffer::stack_size) {
+ _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtInternal);
+ }
+ _size = bytes;
+}
+
+JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle& compiled_code, CodeMetadata& metadata) {
+ CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
+ jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
+ initialize_dependencies(JNIHandles::resolve(compiled_code_obj), NULL);
+
+ // Get instructions and constants CodeSections early because we need it.
+ _instructions = buffer.insts();
+ _constants = buffer.consts();
+
+ initialize_fields(target(), JNIHandles::resolve(compiled_code_obj));
+ if (!initialize_buffer(buffer)) {
+ return JVMCIEnv::code_too_large;
+ }
+ process_exception_handlers();
+
+ _debug_recorder->pcs_size(); // ehm, create the sentinel record
+
+ assert(_debug_recorder->pcs_length() >= 2, "must be at least 2");
+
+ metadata.set_pc_desc(_debug_recorder->pcs(), _debug_recorder->pcs_length());
+ metadata.set_scopes(_debug_recorder->stream()->buffer(), _debug_recorder->data_size());
+ metadata.set_exception_table(&_exception_handler_table);
+
+ RelocBuffer* reloc_buffer = metadata.get_reloc_buffer();
+
+ reloc_buffer->ensure_size(buffer.total_relocation_size());
+ size_t size = (size_t) buffer.copy_relocations_to(reloc_buffer->begin(), (CodeBuffer::csize_t) reloc_buffer->size(), true);
+ reloc_buffer->set_size(size);
+ return JVMCIEnv::ok;
+}
+
+// constructor used to create a method
+JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Handle target, Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log) {
+ CodeBuffer buffer("JVMCI Compiler CodeBuffer");
+ jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
+ OopRecorder* recorder = new OopRecorder(&_arena, true);
+ initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder);
+
+ // Get instructions and constants CodeSections early because we need it.
+ _instructions = buffer.insts();
+ _constants = buffer.consts();
+
+ initialize_fields(target(), JNIHandles::resolve(compiled_code_obj));
+ JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer);
+ if (result != JVMCIEnv::ok) {
+ return result;
+ }
+ process_exception_handlers();
+
+ int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
+
+ if (!compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
+ oop stubName = HotSpotCompiledCode::name(compiled_code_obj);
+ char* name = strdup(java_lang_String::as_utf8_string(stubName));
+ cb = RuntimeStub::new_runtime_stub(name,
+ &buffer,
+ CodeOffsets::frame_never_safe,
+ stack_slots,
+ _debug_recorder->_oopmaps,
+ false);
+ result = JVMCIEnv::ok;
+ } else {
+ nmethod* nm = NULL;
+ methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code));
+ jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code);
+ jint id = HotSpotCompiledNmethod::id(compiled_code);
+ bool has_unsafe_access = HotSpotCompiledNmethod::hasUnsafeAccess(compiled_code) == JNI_TRUE;
+ JVMCIEnv* env = (JVMCIEnv*) (address) HotSpotCompiledNmethod::jvmciEnv(compiled_code);
+ if (id == -1) {
+ // Make sure a valid compile_id is associated with every compile
+ id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
+ }
+ result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer,
+ stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+ compiler, _debug_recorder, _dependencies, env, id,
+ has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
+ cb = nm;
+ }
+
+ if (cb != NULL) {
+ // Make sure the pre-calculated constants section size was correct.
+ guarantee((cb->code_begin() - cb->content_begin()) >= _constants_size, err_msg("%d < %d", (int)(cb->code_begin() - cb->content_begin()), _constants_size));
+ }
+ return result;
+}
+
+void CodeInstaller::initialize_fields(oop target, oop compiled_code) {
+ if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
+ Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code);
+ methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod());
+ _parameter_count = method->size_of_parameters();
+ TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string());
+ } else {
+ // Must be a HotSpotCompiledRuntimeStub.
+ // Only used in OopMap constructor for non-product builds
+ _parameter_count = 0;
+ }
+ _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code));
+ _exception_handlers_handle = JNIHandles::make_local(HotSpotCompiledCode::exceptionHandlers(compiled_code));
+
+ _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code));
+ _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code);
+ _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code);
+ _custom_stack_area_offset = HotSpotCompiledCode::customStackAreaOffset(compiled_code);
+
+ // Pre-calculate the constants section size. This is required for PC-relative addressing.
+ _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code));
+ guarantee(HotSpotCompiledCode::dataSectionAlignment(compiled_code) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+ _constants_size = data_section()->length();
+
+ _data_section_patches_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSectionPatches(compiled_code));
+
+#ifndef PRODUCT
+ _comments_handle = JNIHandles::make_local(HotSpotCompiledCode::comments(compiled_code));
+#endif
+
+ _next_call_type = INVOKE_INVALID;
+
+ _has_wide_vector = false;
+
+ oop arch = TargetDescription::arch(target);
+ _word_kind_handle = JNIHandles::make_local(Architecture::wordKind(arch));
+}
+
+int CodeInstaller::estimate_stubs_size() {
+ // Return size for all stubs.
+ int static_call_stubs = 0;
+ objArrayOop sites = this->sites();
+ for (int i = 0; i < sites->length(); i++) {
+ oop site = sites->obj_at(i);
+ if (site->is_a(CompilationResult_Mark::klass())) {
+ oop id_obj = CompilationResult_Mark::id(site);
+ if (id_obj != NULL) {
+ assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected");
+ jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+ if (id == INVOKESTATIC || id == INVOKESPECIAL) {
+ static_call_stubs++;
+ }
+ }
+ }
+ }
+ return static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+}
+
+// perform data and call relocation on the CodeBuffer
+JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer) {
+ objArrayHandle sites = this->sites();
+ int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
+
+ // Allocate enough space in the stub section for the static call
+ // stubs. Stubs have extra relocs but they are managed by the stub
+ // section itself so they don't need to be accounted for in the
+ // locs_buffer above.
+ int stubs_size = estimate_stubs_size();
+ int total_size = round_to(_code_size, buffer.insts()->alignment()) + round_to(_constants_size, buffer.consts()->alignment()) + round_to(stubs_size, buffer.stubs()->alignment());
+
+ if (total_size > JVMCINMethodSizeLimit) {
+ return JVMCIEnv::code_too_large;
+ }
+
+ buffer.initialize(total_size, locs_buffer_size);
+ if (buffer.blob() == NULL) {
+ return JVMCIEnv::cache_full;
+ }
+ buffer.initialize_stubs_size(stubs_size);
+ buffer.initialize_consts_size(_constants_size);
+
+ _debug_recorder = new DebugInformationRecorder(_oop_recorder);
+ _debug_recorder->set_oopmaps(new OopMapSet());
+
+ buffer.initialize_oop_recorder(_oop_recorder);
+
+ // copy the constant data into the newly created CodeBuffer
+ address end_data = _constants->start() + _constants_size;
+ memcpy(_constants->start(), data_section()->base(T_BYTE), _constants_size);
+ _constants->set_end(end_data);
+
+ // copy the code into the newly created CodeBuffer
+ address end_pc = _instructions->start() + _code_size;
+ guarantee(_instructions->allocates2(end_pc), "initialize should have reserved enough space for all the code");
+ memcpy(_instructions->start(), code()->base(T_BYTE), _code_size);
+ _instructions->set_end(end_pc);
+
+ for (int i = 0; i < data_section_patches()->length(); i++) {
+ Handle patch = data_section_patches()->obj_at(i);
+ Handle reference = CompilationResult_DataPatch::reference(patch);
+ assert(reference->is_a(CompilationResult_ConstantReference::klass()), err_msg("patch in data section must be a ConstantReference"));
+ Handle constant = CompilationResult_ConstantReference::constant(reference);
+ if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+ record_metadata_in_patch(constant, _oop_recorder);
+ } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ int oop_index = _oop_recorder->find_index(value);
+
+ address dest = _constants->start() + CompilationResult_Site::pcOffset(patch);
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+ _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const);
+#else
+ fatal("unexpected compressed oop in 32-bit mode");
+#endif
+ } else {
+ _constants->relocate(dest, oop_Relocation::spec(oop_index));
+ }
+ } else {
+ ShouldNotReachHere();
+ }
+ }
+ jint last_pc_offset = -1;
+ for (int i = 0; i < sites->length(); i++) {
+ {
+ No_Safepoint_Verifier no_safepoint;
+ oop site = sites->obj_at(i);
+ jint pc_offset = CompilationResult_Site::pcOffset(site);
+
+ if (site->is_a(CompilationResult_Call::klass())) {
+ TRACE_jvmci_4("call at %i", pc_offset);
+ site_Call(buffer, pc_offset, site);
+ } else if (site->is_a(CompilationResult_Infopoint::klass())) {
+ // three reasons for infopoints denote actual safepoints
+ oop reason = CompilationResult_Infopoint::reason(site);
+ if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+ TRACE_jvmci_4("safepoint at %i", pc_offset);
+ site_Safepoint(buffer, pc_offset, site);
+ } else {
+ // if the infopoint is not an actual safepoint, it must have one of the other reasons
+ // (safeguard against new safepoint types that require handling above)
+ assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, "");
+ site_Infopoint(buffer, pc_offset, site);
+ }
+ } else if (site->is_a(CompilationResult_DataPatch::klass())) {
+ TRACE_jvmci_4("datapatch at %i", pc_offset);
+ site_DataPatch(buffer, pc_offset, site);
+ } else if (site->is_a(CompilationResult_Mark::klass())) {
+ TRACE_jvmci_4("mark at %i", pc_offset);
+ site_Mark(buffer, pc_offset, site);
+ } else {
+ fatal("unexpected Site subclass");
+ }
+ last_pc_offset = pc_offset;
+ }
+ if (CodeInstallSafepointChecks && SafepointSynchronize::do_call_back()) {
+ // this is a hacky way to force a safepoint check but nothing else was jumping out at me.
+ ThreadToNativeFromVM ttnfv(JavaThread::current());
+ }
+ }
+
+#ifndef PRODUCT
+ if (comments() != NULL) {
+ No_Safepoint_Verifier no_safepoint;
+ for (int i = 0; i < comments()->length(); i++) {
+ oop comment = comments()->obj_at(i);
+ assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
+ jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
+ char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
+ buffer.block_comment(offset, text);
+ }
+ }
+#endif
+ return JVMCIEnv::ok;
+}
+
+void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) {
+ Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption());
+ Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle));
+ _dependencies->assert_has_no_finalizable_subclasses(receiverType);
+}
+
+void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) {
+ Handle context_handle = Assumptions_ConcreteSubtype::context(assumption());
+ Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption());
+ Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+ Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle));
+
+ assert(context->is_abstract(), "");
+ _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
+}
+
+void CodeInstaller::assumption_LeafType(Handle assumption) {
+ Handle context_handle = Assumptions_LeafType::context(assumption());
+ Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+
+ _dependencies->assert_leaf_type(context);
+}
+
+void CodeInstaller::assumption_ConcreteMethod(Handle assumption) {
+ Handle impl_handle = Assumptions_ConcreteMethod::impl(assumption());
+ Handle context_handle = Assumptions_ConcreteMethod::context(assumption());
+
+ methodHandle impl = getMethodFromHotSpotMethod(impl_handle());
+ Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+
+ _dependencies->assert_unique_concrete_method(context, impl());
+}
+
+void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) {
+ Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption());
+ Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption());
+
+ _dependencies->assert_call_site_target_value(callSite(), methodHandle());
+}
+
+void CodeInstaller::process_exception_handlers() {
+ if (exception_handlers() != NULL) {
+ objArrayOop handlers = exception_handlers();
+ for (int i = 0; i < handlers->length(); i++) {
+ oop exc = handlers->obj_at(i);
+ jint pc_offset = CompilationResult_Site::pcOffset(exc);
+ jint handler_offset = CompilationResult_ExceptionHandler::handlerPos(exc);
+
+ // Subtable header
+ _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0));
+
+ // Subtable entry
+ _exception_handler_table.add_entry(HandlerTableEntry(-1, handler_offset, 0));
+ }
+ }
+}
+
+// If deoptimization happens, the interpreter should reexecute these bytecodes.
+// This function mainly helps the compilers to set up the reexecute bit.
+static bool bytecode_should_reexecute(Bytecodes::Code code) {
+ switch (code) {
+ case Bytecodes::_invokedynamic:
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokeinterface:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ return false;
+ default:
+ return true;
+ }
+ return true;
+}
+
+GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(oop debug_info) {
+ objArrayOop virtualObjects = DebugInfo::virtualObjectMapping(debug_info);
+ if (virtualObjects == NULL) {
+ return NULL;
+ }
+ GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL);
+ // Create the unique ObjectValues
+ for (int i = 0; i < virtualObjects->length(); i++) {
+ oop value = virtualObjects->obj_at(i);
+ int id = VirtualObject::id(value);
+ oop type = VirtualObject::type(value);
+ oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+ ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror)));
+ assert(objects->at(id) == NULL, "once");
+ objects->at_put(id, sv);
+ }
+ // All the values which could be referenced by the VirtualObjects
+ // exist, so now describe all the VirtualObjects themselves.
+ for (int i = 0; i < virtualObjects->length(); i++) {
+ oop value = virtualObjects->obj_at(i);
+ int id = VirtualObject::id(value);
+ record_object_value(objects->at(id)->as_ObjectValue(), value, objects);
+ }
+ _debug_recorder->dump_object_pool(objects);
+ return objects;
+}
+
+void CodeInstaller::record_scope(jint pc_offset, oop debug_info) {
+ oop position = DebugInfo::bytecodePosition(debug_info);
+ if (position == NULL) {
+ // Stubs do not record scope info, just oop maps
+ return;
+ }
+
+ GrowableArray<ScopeValue*>* objectMapping = record_virtual_objects(debug_info);
+ record_scope(pc_offset, position, objectMapping);
+}
+
+void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray<ScopeValue*>* objects) {
+ oop frame = NULL;
+ if (position->is_a(BytecodeFrame::klass())) {
+ frame = position;
+ }
+ oop caller_frame = BytecodePosition::caller(position);
+ if (caller_frame != NULL) {
+ record_scope(pc_offset, caller_frame, objects);
+ }
+
+ oop hotspot_method = BytecodePosition::method(position);
+ Method* method = getMethodFromHotSpotMethod(hotspot_method);
+ jint bci = BytecodePosition::bci(position);
+ if (bci == BytecodeFrame::BEFORE_BCI()) {
+ bci = SynchronizationEntryBCI;
+ }
+
+ TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string());
+
+ bool reexecute = false;
+ if (frame != NULL) {
+ if (bci == SynchronizationEntryBCI){
+ reexecute = false;
+ } else {
+ Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
+ reexecute = bytecode_should_reexecute(code);
+ if (frame != NULL) {
+ reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE);
+ }
+ }
+ }
+
+ DebugToken* locals_token = NULL;
+ DebugToken* expressions_token = NULL;
+ DebugToken* monitors_token = NULL;
+ bool throw_exception = false;
+
+ if (frame != NULL) {
+ jint local_count = BytecodeFrame::numLocals(frame);
+ jint expression_count = BytecodeFrame::numStack(frame);
+ jint monitor_count = BytecodeFrame::numLocks(frame);
+ objArrayOop values = BytecodeFrame::values(frame);
+ objArrayOop slotKinds = BytecodeFrame::slotKinds(frame);
+
+ assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length");
+ assert(local_count + expression_count == slotKinds->length(), "unexpected slotKinds length");
+
+ GrowableArray<ScopeValue*>* locals = local_count > 0 ? new GrowableArray<ScopeValue*> (local_count) : NULL;
+ GrowableArray<ScopeValue*>* expressions = expression_count > 0 ? new GrowableArray<ScopeValue*> (expression_count) : NULL;
+ GrowableArray<MonitorValue*>* monitors = monitor_count > 0 ? new GrowableArray<MonitorValue*> (monitor_count) : NULL;
+
+ TRACE_jvmci_2("Scope at bci %d with %d values", bci, values->length());
+ TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
+
+ for (jint i = 0; i < values->length(); i++) {
+ ScopeValue* second = NULL;
+ oop value = values->obj_at(i);
+ if (i < local_count) {
+ oop kind = slotKinds->obj_at(i);
+ BasicType type = JVMCIRuntime::kindToBasicType(JavaKind::typeChar(kind));
+ ScopeValue* first = get_scope_value(value, type, objects, second);
+ if (second != NULL) {
+ locals->append(second);
+ }
+ locals->append(first);
+ } else if (i < local_count + expression_count) {
+ oop kind = slotKinds->obj_at(i);
+ BasicType type = JVMCIRuntime::kindToBasicType(JavaKind::typeChar(kind));
+ ScopeValue* first = get_scope_value(value, type, objects, second);
+ if (second != NULL) {
+ expressions->append(second);
+ }
+ expressions->append(first);
+ } else {
+ monitors->append(get_monitor_value(value, objects));
+ }
+ if (second != NULL) {
+ i++;
+ assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL");
+ assert(values->obj_at(i) == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
+ }
+ }
+
+ locals_token = _debug_recorder->create_scope_values(locals);
+ expressions_token = _debug_recorder->create_scope_values(expressions);
+ monitors_token = _debug_recorder->create_monitor_values(monitors);
+
+ throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE;
+ }
+
+ _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false,
+ locals_token, expressions_token, monitors_token);
+}
+
+void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
+ oop debug_info = CompilationResult_Infopoint::debugInfo(site);
+ assert(debug_info != NULL, "debug info expected");
+
+ // address instruction = _instructions->start() + pc_offset;
+ // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
+ _debug_recorder->add_safepoint(pc_offset, create_oop_map(debug_info));
+ record_scope(pc_offset, debug_info);
+ _debug_recorder->end_safepoint(pc_offset);
+}
+
+void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site) {
+ oop debug_info = CompilationResult_Infopoint::debugInfo(site);
+ assert(debug_info != NULL, "debug info expected");
+
+ _debug_recorder->add_non_safepoint(pc_offset);
+ record_scope(pc_offset, debug_info);
+ _debug_recorder->end_non_safepoint(pc_offset);
+}
+
+void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) {
+ oop target = CompilationResult_Call::target(site);
+ InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+
+ oop hotspot_method = NULL; // JavaMethod
+ oop foreign_call = NULL;
+
+ if (target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+ foreign_call = target;
+ } else {
+ hotspot_method = target;
+ }
+
+ oop debug_info = CompilationResult_Call::debugInfo(site);
+
+ assert(!!hotspot_method ^ !!foreign_call, "Call site needs exactly one type");
+
+ NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
+ jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
+
+ if (debug_info != NULL) {
+ _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(debug_info));
+ record_scope(next_pc_offset, debug_info);
+ }
+
+ if (foreign_call != NULL) {
+ jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call);
+ CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination);
+ } else { // method != NULL
+ assert(hotspot_method != NULL, "unexpected JavaMethod");
+ assert(debug_info != NULL, "debug info expected");
+
+ TRACE_jvmci_3("method call");
+ CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
+ if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
+ // Need a static call stub for transitions from compiled to interpreted.
+ CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
+ }
+ }
+
+ _next_call_type = INVOKE_INVALID;
+
+ if (debug_info != NULL) {
+ _debug_recorder->end_safepoint(next_pc_offset);
+ }
+}
+
+void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) {
+ oop reference = CompilationResult_DataPatch::reference(site);
+ if (reference->is_a(CompilationResult_ConstantReference::klass())) {
+ Handle constant = CompilationResult_ConstantReference::constant(reference);
+ if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+ pd_patch_OopConstant(pc_offset, constant);
+ } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+ record_metadata_in_patch(constant, _oop_recorder);
+ } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
+ fatal("sentinel constant unsupported");
+ } else {
+ fatal("unknown constant type in data patch");
+ }
+ } else if (reference->is_a(CompilationResult_DataSectionReference::klass())) {
+ int data_offset = CompilationResult_DataSectionReference::offset(reference);
+ assert(0 <= data_offset && data_offset < _constants_size, err_msg("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size));
+ pd_patch_DataSectionReference(pc_offset, data_offset);
+ } else {
+ fatal("unknown data patch type");
+ }
+}
+
+void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
+ oop id_obj = CompilationResult_Mark::id(site);
+
+ if (id_obj != NULL) {
+ assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected");
+ jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+
+ address pc = _instructions->start() + pc_offset;
+
+ switch (id) {
+ case UNVERIFIED_ENTRY:
+ _offsets.set_value(CodeOffsets::Entry, pc_offset);
+ break;
+ case VERIFIED_ENTRY:
+ _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset);
+ break;
+ case OSR_ENTRY:
+ _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset);
+ break;
+ case EXCEPTION_HANDLER_ENTRY:
+ _offsets.set_value(CodeOffsets::Exceptions, pc_offset);
+ break;
+ case DEOPT_HANDLER_ENTRY:
+ _offsets.set_value(CodeOffsets::Deopt, pc_offset);
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE:
+ case INLINE_INVOKE:
+ case INVOKESTATIC:
+ case INVOKESPECIAL:
+ _next_call_type = (MarkId) id;
+ _invoke_mark_pc = pc;
+ break;
+ case POLL_NEAR:
+ case POLL_FAR:
+ case POLL_RETURN_NEAR:
+ case POLL_RETURN_FAR:
+ pd_relocate_poll(pc, id);
+ break;
+ case CARD_TABLE_ADDRESS:
+ case HEAP_TOP_ADDRESS:
+ case HEAP_END_ADDRESS:
+ case NARROW_KLASS_BASE_ADDRESS:
+ case CRC_TABLE_ADDRESS:
+ break;
+ default:
+ ShouldNotReachHere();
+ break;
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
+#define SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
+
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "code/nativeInst.hpp"
+
+class RelocBuffer : public StackObj {
+ enum { stack_size = 1024 };
+public:
+ RelocBuffer() : _size(0), _buffer(0) {}
+ ~RelocBuffer();
+ void ensure_size(size_t bytes);
+ void set_size(size_t bytes);
+ address begin() const;
+ size_t size() const { return _size; }
+private:
+ size_t _size;
+ char _static_buffer[stack_size];
+ char *_buffer;
+};
+
+class CodeMetadata {
+public:
+ CodeMetadata() {}
+
+ CodeBlob* get_code_blob() const { return _cb; }
+
+ PcDesc* get_pc_desc() const { return _pc_desc; }
+ int get_nr_pc_desc() const { return _nr_pc_desc; }
+
+ u_char* get_scopes_desc() const { return _scopes_desc; }
+ int get_scopes_size() const { return _nr_scopes_desc; }
+
+ RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; }
+
+ ExceptionHandlerTable* get_exception_table() { return _exception_table; }
+
+ void set_pc_desc(PcDesc* desc, int count) {
+ _pc_desc = desc;
+ _nr_pc_desc = count;
+ }
+
+ void set_scopes(u_char* scopes, int size) {
+ _scopes_desc = scopes;
+ _nr_scopes_desc = size;
+ }
+
+ void set_exception_table(ExceptionHandlerTable* table) {
+ _exception_table = table;
+ }
+
+private:
+ CodeBlob* _cb;
+ PcDesc* _pc_desc;
+ int _nr_pc_desc;
+
+ u_char* _scopes_desc;
+ int _nr_scopes_desc;
+
+ RelocBuffer _reloc_buffer;
+ ExceptionHandlerTable* _exception_table;
+};
+
+/*
+ * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
+ */
+class CodeInstaller : public StackObj {
+ friend class VMStructs;
+private:
+ enum MarkId {
+ VERIFIED_ENTRY = 1,
+ UNVERIFIED_ENTRY = 2,
+ OSR_ENTRY = 3,
+ EXCEPTION_HANDLER_ENTRY = 4,
+ DEOPT_HANDLER_ENTRY = 5,
+ INVOKEINTERFACE = 6,
+ INVOKEVIRTUAL = 7,
+ INVOKESTATIC = 8,
+ INVOKESPECIAL = 9,
+ INLINE_INVOKE = 10,
+ POLL_NEAR = 11,
+ POLL_RETURN_NEAR = 12,
+ POLL_FAR = 13,
+ POLL_RETURN_FAR = 14,
+ CARD_TABLE_ADDRESS = 15,
+ HEAP_TOP_ADDRESS = 16,
+ HEAP_END_ADDRESS = 17,
+ NARROW_KLASS_BASE_ADDRESS = 18,
+ CRC_TABLE_ADDRESS = 19,
+ INVOKE_INVALID = -1
+ };
+
+ Arena _arena;
+
+ jobject _data_section_handle;
+ jobject _data_section_patches_handle;
+ jobject _sites_handle;
+ jobject _exception_handlers_handle;
+ CodeOffsets _offsets;
+
+ jobject _code_handle;
+ jint _code_size;
+ jint _total_frame_size;
+ jint _custom_stack_area_offset;
+ jint _parameter_count;
+ jint _constants_size;
+#ifndef PRODUCT
+ jobject _comments_handle;
+#endif
+
+ bool _has_wide_vector;
+ jobject _word_kind_handle;
+
+ MarkId _next_call_type;
+ address _invoke_mark_pc;
+
+ CodeSection* _instructions;
+ CodeSection* _constants;
+
+ OopRecorder* _oop_recorder;
+ DebugInformationRecorder* _debug_recorder;
+ Dependencies* _dependencies;
+ ExceptionHandlerTable _exception_handler_table;
+
+ static ConstantOopWriteValue* _oop_null_scope_value;
+ static ConstantIntValue* _int_m1_scope_value;
+ static ConstantIntValue* _int_0_scope_value;
+ static ConstantIntValue* _int_1_scope_value;
+ static ConstantIntValue* _int_2_scope_value;
+ static LocationValue* _illegal_value;
+
+ jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
+ void pd_patch_OopConstant(int pc_offset, Handle& constant);
+ void pd_patch_DataSectionReference(int pc_offset, int data_offset);
+ void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
+ void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
+ void pd_relocate_JavaMethod(oop method, jint pc_offset);
+ void pd_relocate_poll(address pc, jint mark);
+
+ objArrayOop sites() { return (objArrayOop) JNIHandles::resolve(_sites_handle); }
+ arrayOop code() { return (arrayOop) JNIHandles::resolve(_code_handle); }
+ arrayOop data_section() { return (arrayOop) JNIHandles::resolve(_data_section_handle); }
+ objArrayOop data_section_patches() { return (objArrayOop) JNIHandles::resolve(_data_section_patches_handle); }
+ objArrayOop exception_handlers() { return (objArrayOop) JNIHandles::resolve(_exception_handlers_handle); }
+#ifndef PRODUCT
+ objArrayOop comments() { return (objArrayOop) JNIHandles::resolve(_comments_handle); }
+#endif
+
+ void record_resolved(oop obj);
+
+ oop word_kind() { return (oop) JNIHandles::resolve(_word_kind_handle); }
+
+public:
+ CodeInstaller() : _arena(mtCompiler) {}
+
+ JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle& compiled_code, CodeMetadata& metadata);
+ JVMCIEnv::CodeInstallResult install(JVMCICompiler* compiler, Handle target, Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log);
+
+ static address runtime_call_target_address(oop runtime_call);
+ static VMReg get_hotspot_reg(jint jvmciRegisterNumber);
+ static bool is_general_purpose_reg(VMReg hotspotRegister);
+
+ const OopMapSet* oopMapSet() const { return _debug_recorder->_oopmaps; }
+
+protected:
+ Location::Type get_oop_type(oop value);
+ ScopeValue* get_scope_value(oop value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second);
+ MonitorValue* get_monitor_value(oop value, GrowableArray<ScopeValue*>* objects);
+
+ // extract the fields of the CompilationResult
+ void initialize_fields(oop target, oop target_method);
+ void initialize_dependencies(oop target_method, OopRecorder* oop_recorder);
+
+ int estimate_stubs_size();
+
+ // perform data and call relocation on the CodeBuffer
+ JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer);
+
+ void assumption_NoFinalizableSubclass(Handle assumption);
+ void assumption_ConcreteSubtype(Handle assumption);
+ void assumption_LeafType(Handle assumption);
+ void assumption_ConcreteMethod(Handle assumption);
+ void assumption_CallSiteTargetValue(Handle assumption);
+
+ void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site);
+ void site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site);
+ void site_Call(CodeBuffer& buffer, jint pc_offset, oop site);
+ void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site);
+ void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site);
+
+ OopMap* create_oop_map(oop debug_info);
+
+ void record_scope(jint pc_offset, oop debug_info);
+ void record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects);
+ void record_object_value(ObjectValue* sv, oop value, GrowableArray<ScopeValue*>* objects);
+
+ GrowableArray<ScopeValue*>* record_virtual_objects(oop debug_info);
+
+ void process_exception_handlers();
+ int estimateStubSpace(int static_call_stubs);
+};
+
+/**
+ * Gets the Method metaspace object from a HotSpotResolvedJavaMethodImpl Java object.
+ */
+Method* getMethodFromHotSpotMethod(oop hotspot_method);
+
+
+
+#endif // SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+#include "precompiled.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/handles.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "runtime/compilationPolicy.hpp"
+#include "runtime/globals_extension.hpp"
+
+JVMCICompiler* JVMCICompiler::_instance = NULL;
+elapsedTimer JVMCICompiler::_codeInstallTimer;
+
+JVMCICompiler::JVMCICompiler() : AbstractCompiler(jvmci) {
+ _bootstrapping = false;
+ _methodsCompiled = 0;
+ assert(_instance == NULL, "only one instance allowed");
+ _instance = this;
+}
+
+// Initialization
+void JVMCICompiler::initialize() {
+ if (!UseCompiler || !EnableJVMCI || !UseJVMCICompiler || !should_perform_init()) {
+ return;
+ }
+
+ set_state(initialized);
+
+ // JVMCI is considered as application code so we need to
+ // stop the VM deferring compilation now.
+ CompilationPolicy::completed_vm_startup();
+}
+
+void JVMCICompiler::bootstrap() {
+#ifndef PRODUCT
+ // We turn off CompileTheWorld so that compilation requests are not
+ // ignored during bootstrap or that JVMCI can be compiled by C1/C2.
+ FlagSetting ctwOff(CompileTheWorld, false);
+#endif
+
+ JavaThread* THREAD = JavaThread::current();
+ _bootstrapping = true;
+ ResourceMark rm;
+ HandleMark hm;
+ if (PrintBootstrap) {
+ tty->print("Bootstrapping JVMCI");
+ }
+ jlong start = os::javaTimeMillis();
+
+ Array<Method*>* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods();
+ // Initialize compile queue with a selected set of methods.
+ int len = objectMethods->length();
+ for (int i = 0; i < len; i++) {
+ methodHandle mh = objectMethods->at(i);
+ if (!mh->is_native() && !mh->is_static() && !mh->is_initializer()) {
+ ResourceMark rm;
+ int hot_count = 10; // TODO: what's the appropriate value?
+ CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, "bootstrap", THREAD);
+ }
+ }
+
+ int qsize;
+ bool first_round = true;
+ int z = 0;
+ do {
+ // Loop until there is something in the queue.
+ do {
+ os::sleep(THREAD, 100, true);
+ qsize = CompileBroker::queue_size(CompLevel_full_optimization);
+ } while (first_round && qsize == 0);
+ first_round = false;
+ if (PrintBootstrap) {
+ while (z < (_methodsCompiled / 100)) {
+ ++z;
+ tty->print_raw(".");
+ }
+ }
+ } while (qsize != 0);
+
+ if (PrintBootstrap) {
+ tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methodsCompiled);
+ }
+ _bootstrapping = false;
+}
+
+void JVMCICompiler::compile_method(methodHandle method, int entry_bci, JVMCIEnv* env) {
+ JVMCI_EXCEPTION_CONTEXT
+
+ bool is_osr = entry_bci != InvocationEntryBci;
+ if (_bootstrapping && is_osr) {
+ // no OSR compilations during bootstrap - the compiler is just too slow at this point,
+ // and we know that there are no endless loops
+ return;
+ }
+
+ JVMCIRuntime::initialize_well_known_classes(CHECK_ABORT);
+
+ HandleMark hm;
+ ResourceMark rm;
+ Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_ABORT);
+
+ JavaValue method_result(T_OBJECT);
+ {
+ JavaCallArguments args;
+ args.push_long((jlong) (address) method());
+ JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_ABORT);
+ }
+
+ JavaValue result(T_VOID);
+ JavaCallArguments args;
+ args.push_oop(receiver);
+ args.push_oop((oop)method_result.get_jobject());
+ args.push_int(entry_bci);
+ args.push_long((jlong) (address) env);
+ args.push_int(env->task()->compile_id());
+ JavaCalls::call_special(&result, receiver->klass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, CHECK_ABORT);
+
+ _methodsCompiled++;
+}
+
+
+// Compilation entry point for methods
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+ ShouldNotReachHere();
+}
+
+// Print compilation timers and statistics
+void JVMCICompiler::print_timers() {
+ print_compilation_timers();
+}
+
+// Print compilation timers and statistics
+void JVMCICompiler::print_compilation_timers() {
+ TRACE_jvmci_1("JVMCICompiler::print_timers");
+ tty->print_cr(" JVMCI code install time: %6.3f s", _codeInstallTimer.seconds());
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
+#define SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
+
+#include "compiler/abstractCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "utilities/exceptions.hpp"
+
+class JVMCICompiler : public AbstractCompiler {
+private:
+ bool _bootstrapping;
+
+ /**
+ * Number of methods compiled by JVMCI. This is not synchronized
+ * so may not be 100% accurate.
+ */
+ volatile int _methodsCompiled;
+
+ static JVMCICompiler* _instance;
+
+ static elapsedTimer _codeInstallTimer;
+
+public:
+ JVMCICompiler();
+
+ static JVMCICompiler* instance(TRAPS) {
+ if (!EnableJVMCI) {
+ THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+ }
+ return _instance;
+ }
+
+ virtual const char* name() { return "JVMCI"; }
+
+ virtual bool supports_native() { return true; }
+ virtual bool supports_osr () { return true; }
+
+ bool is_jvmci() { return true; }
+ bool is_c1 () { return false; }
+ bool is_c2 () { return false; }
+
+ bool needs_stubs () { return false; }
+
+ // Initialization
+ virtual void initialize();
+
+ void bootstrap();
+
+ // Compilation entry point for methods
+ virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+
+ void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
+
+ // Print compilation timers and statistics
+ virtual void print_timers();
+
+ // Print compilation statistics
+ void reset_compilation_stats();
+
+ // Print compilation timers and statistics
+ static void print_compilation_timers();
+
+ static elapsedTimer* codeInstallTimer() { return &_codeInstallTimer; }
+};
+
+#endif // SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#include "precompiled.hpp"
+#include "code/codeCache.hpp"
+#include "code/scopeDesc.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/generateOopMap.hpp"
+#include "oops/fieldStreams.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "runtime/fieldDescriptor.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "compiler/abstractCompiler.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "compiler/disassembler.hpp"
+#include "compiler/oopMap.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/vframe.hpp"
+#include "runtime/vframe_hp.hpp"
+#include "runtime/vmStructs.hpp"
+
+
+// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
+#define C2V_VMENTRY(result_type, name, signature) \
+ JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+ TRACE_jvmci_1("CompilerToVM::" #name); \
+ TRACE_CALL(result_type, jvmci_ ## name signature) \
+ JVMCI_VM_ENTRY_MARK; \
+
+#define C2V_END }
+
+oop CompilerToVM::get_jvmci_method(methodHandle method, TRAPS) {
+ if (method() != NULL) {
+ JavaValue result(T_OBJECT);
+ JavaCallArguments args;
+ args.push_long((jlong) (address) method());
+ JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_NULL);
+
+ return (oop)result.get_jobject();
+ }
+ return NULL;
+}
+
+oop CompilerToVM::get_jvmci_type(KlassHandle klass, TRAPS) {
+ if (klass() != NULL) {
+ JavaValue result(T_OBJECT);
+ JavaCallArguments args;
+ args.push_oop(klass->java_mirror());
+ JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedObjectTypeImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::klass_fromMetaspace_signature(), &args, CHECK_NULL);
+
+ return (oop)result.get_jobject();
+ }
+ return NULL;
+}
+
+extern "C" {
+extern VMStructEntry* gHotSpotVMStructs;
+extern uint64_t gHotSpotVMStructEntryTypeNameOffset;
+extern uint64_t gHotSpotVMStructEntryFieldNameOffset;
+extern uint64_t gHotSpotVMStructEntryTypeStringOffset;
+extern uint64_t gHotSpotVMStructEntryIsStaticOffset;
+extern uint64_t gHotSpotVMStructEntryOffsetOffset;
+extern uint64_t gHotSpotVMStructEntryAddressOffset;
+extern uint64_t gHotSpotVMStructEntryArrayStride;
+
+extern VMTypeEntry* gHotSpotVMTypes;
+extern uint64_t gHotSpotVMTypeEntryTypeNameOffset;
+extern uint64_t gHotSpotVMTypeEntrySuperclassNameOffset;
+extern uint64_t gHotSpotVMTypeEntryIsOopTypeOffset;
+extern uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset;
+extern uint64_t gHotSpotVMTypeEntryIsUnsignedOffset;
+extern uint64_t gHotSpotVMTypeEntrySizeOffset;
+extern uint64_t gHotSpotVMTypeEntryArrayStride;
+
+extern VMIntConstantEntry* gHotSpotVMIntConstants;
+extern uint64_t gHotSpotVMIntConstantEntryNameOffset;
+extern uint64_t gHotSpotVMIntConstantEntryValueOffset;
+extern uint64_t gHotSpotVMIntConstantEntryArrayStride;
+
+extern VMLongConstantEntry* gHotSpotVMLongConstants;
+extern uint64_t gHotSpotVMLongConstantEntryNameOffset;
+extern uint64_t gHotSpotVMLongConstantEntryValueOffset;
+extern uint64_t gHotSpotVMLongConstantEntryArrayStride;
+
+extern VMAddressEntry* gHotSpotVMAddresses;
+extern uint64_t gHotSpotVMAddressEntryNameOffset;
+extern uint64_t gHotSpotVMAddressEntryValueOffset;
+extern uint64_t gHotSpotVMAddressEntryArrayStride;
+}
+
+// FIXME This is only temporary until the GC code is changed.
+bool CompilerToVM::_supports_inline_contig_alloc;
+HeapWord** CompilerToVM::_heap_end_addr;
+HeapWord** CompilerToVM::_heap_top_addr;
+
+/**
+ * We put all gHotSpotVM values in an array so we can read them easily from Java.
+ */
+static uintptr_t ciHotSpotVMData[28];
+
+C2V_VMENTRY(jlong, initializeConfiguration, (JNIEnv *env, jobject))
+ ciHotSpotVMData[0] = (uintptr_t) gHotSpotVMStructs;
+ ciHotSpotVMData[1] = gHotSpotVMStructEntryTypeNameOffset;
+ ciHotSpotVMData[2] = gHotSpotVMStructEntryFieldNameOffset;
+ ciHotSpotVMData[3] = gHotSpotVMStructEntryTypeStringOffset;
+ ciHotSpotVMData[4] = gHotSpotVMStructEntryIsStaticOffset;
+ ciHotSpotVMData[5] = gHotSpotVMStructEntryOffsetOffset;
+ ciHotSpotVMData[6] = gHotSpotVMStructEntryAddressOffset;
+ ciHotSpotVMData[7] = gHotSpotVMStructEntryArrayStride;
+
+ ciHotSpotVMData[8] = (uintptr_t) gHotSpotVMTypes;
+ ciHotSpotVMData[9] = gHotSpotVMTypeEntryTypeNameOffset;
+ ciHotSpotVMData[10] = gHotSpotVMTypeEntrySuperclassNameOffset;
+ ciHotSpotVMData[11] = gHotSpotVMTypeEntryIsOopTypeOffset;
+ ciHotSpotVMData[12] = gHotSpotVMTypeEntryIsIntegerTypeOffset;
+ ciHotSpotVMData[13] = gHotSpotVMTypeEntryIsUnsignedOffset;
+ ciHotSpotVMData[14] = gHotSpotVMTypeEntrySizeOffset;
+ ciHotSpotVMData[15] = gHotSpotVMTypeEntryArrayStride;
+
+ ciHotSpotVMData[16] = (uintptr_t) gHotSpotVMIntConstants;
+ ciHotSpotVMData[17] = gHotSpotVMIntConstantEntryNameOffset;
+ ciHotSpotVMData[18] = gHotSpotVMIntConstantEntryValueOffset;
+ ciHotSpotVMData[19] = gHotSpotVMIntConstantEntryArrayStride;
+
+ ciHotSpotVMData[20] = (uintptr_t) gHotSpotVMLongConstants;
+ ciHotSpotVMData[21] = gHotSpotVMLongConstantEntryNameOffset;
+ ciHotSpotVMData[22] = gHotSpotVMLongConstantEntryValueOffset;
+ ciHotSpotVMData[23] = gHotSpotVMLongConstantEntryArrayStride;
+
+ ciHotSpotVMData[24] = (uintptr_t) gHotSpotVMAddresses;
+ ciHotSpotVMData[25] = gHotSpotVMAddressEntryNameOffset;
+ ciHotSpotVMData[26] = gHotSpotVMAddressEntryValueOffset;
+ ciHotSpotVMData[27] = gHotSpotVMAddressEntryArrayStride;
+
+ // FIXME This is only temporary until the GC code is changed.
+ CompilerToVM::_supports_inline_contig_alloc = Universe::heap()->supports_inline_contig_alloc();
+ CompilerToVM::_heap_end_addr = CompilerToVM::_supports_inline_contig_alloc ? Universe::heap()->end_addr() : (HeapWord**) -1;
+ CompilerToVM::_heap_top_addr = CompilerToVM::_supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord**) -1;
+
+ return (jlong) (address) &ciHotSpotVMData;
+C2V_END
+
+C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ ResourceMark rm;
+
+ int code_size = method->code_size();
+ typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
+
+ guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
+ // iterate over all bytecodes and replace non-Java bytecodes
+
+ for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
+ Bytecodes::Code code = s.code();
+ Bytecodes::Code raw_code = s.raw_code();
+ int bci = s.bci();
+ int len = s.instruction_size();
+
+ // Restore original byte code.
+ reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
+ if (len > 1) {
+ memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
+ }
+
+ if (len > 1) {
+ // Restore the big-endian constant pool indexes.
+ // Cf. Rewriter::scan_method
+ switch (code) {
+ case Bytecodes::_getstatic:
+ case Bytecodes::_putstatic:
+ case Bytecodes::_getfield:
+ case Bytecodes::_putfield:
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ case Bytecodes::_invokeinterface:
+ case Bytecodes::_invokehandle: {
+ int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+ Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+ break;
+ }
+
+ case Bytecodes::_invokedynamic:
+ int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
+ Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
+ break;
+ }
+
+ // Not all ldc byte code are rewritten.
+ switch (raw_code) {
+ case Bytecodes::_fast_aldc: {
+ int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
+ int cp_index = method->constants()->object_to_cp_index(cpc_index);
+ assert(cp_index < method->constants()->length(), "sanity check");
+ reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
+ break;
+ }
+
+ case Bytecodes::_fast_aldc_w: {
+ int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+ int cp_index = method->constants()->object_to_cp_index(cpc_index);
+ assert(cp_index < method->constants()->length(), "sanity check");
+ Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+ break;
+ }
+ }
+ }
+ }
+
+ return (jbyteArray) JNIHandles::make_local(THREAD, reconstituted_code);
+C2V_END
+
+C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv *, jobject, jobject jvmci_method))
+ ResourceMark rm;
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return method->exception_table_length();
+C2V_END
+
+C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv *, jobject, jobject jvmci_method))
+ ResourceMark rm;
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ if (method->exception_table_length() == 0) {
+ return 0L;
+ }
+ return (jlong) (address) method->exception_table_start();
+C2V_END
+
+C2V_VMENTRY(jobject, getResolvedJavaMethodAtSlot, (JNIEnv *, jobject, jclass holder_handle, jint slot))
+ oop java_class = JNIHandles::resolve(holder_handle);
+ Klass* holder = java_lang_Class::as_Klass(java_class);
+ methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot);
+ oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv *, jobject, jobject base, jlong offset))
+ methodHandle method;
+ oop base_object = JNIHandles::resolve(base);
+ if (base_object == NULL) {
+ method = *((Method**)(offset));
+ } else if (base_object->is_a(SystemDictionary::MemberName_klass())) {
+ method = (Method*) (intptr_t) base_object->long_field(offset);
+ } else if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+ method = *((Method**)(HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object) + offset));
+ } else {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Unexpected type: %s", base_object->klass()->external_name()));
+ }
+ assert (method.is_null() || method->is_method(), "invalid read");
+ oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject base, jlong offset))
+ constantPoolHandle cp;
+ oop base_object = JNIHandles::resolve(base);
+ jlong base_address = 0;
+ if (base_object != NULL) {
+ if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+ base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
+ } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
+ base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
+ } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+ base_address = (jlong) CompilerToVM::asKlass(base_object);
+ } else {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Unexpected type: %s", base_object->klass()->external_name()));
+ }
+ }
+ cp = *((ConstantPool**) (intptr_t) (base_address + offset));
+ if (!cp.is_null()) {
+ JavaValue method_result(T_OBJECT);
+ JavaCallArguments args;
+ args.push_long((jlong) (address) cp());
+ JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+ }
+ return NULL;
+}
+
+C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
+ KlassHandle klass;
+ oop base_object = JNIHandles::resolve(base);
+ jlong base_address = 0;
+ if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) {
+ klass = base_object->klass();
+ } else if (!compressed) {
+ if (base_object != NULL) {
+ if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+ base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
+ } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
+ base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
+ } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+ base_address = (jlong) CompilerToVM::asKlass(base_object);
+ } else if (base_object->is_a(SystemDictionary::Class_klass())) {
+ base_address = (jlong) (address) base_object;
+ } else {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+ }
+ }
+ klass = *((Klass**) (intptr_t) (base_address + offset));
+ } else {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+ }
+ assert (klass.is_null() || klass->is_klass(), "invalid read");
+ oop result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
+ ResourceMark rm;
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ KlassHandle holder = CompilerToVM::asKlass(jvmci_type);
+ if (holder->is_interface()) {
+ THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name()));
+ }
+
+ methodHandle ucm;
+ {
+ MutexLocker locker(Compile_lock);
+ ucm = Dependencies::find_unique_concrete_method(holder(), method());
+ }
+ oop result = CompilerToVM::get_jvmci_method(ucm, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
+ InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
+ oop implementor = CompilerToVM::get_jvmci_type(klass->implementor(), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, implementor);
+C2V_END
+
+C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return method->is_ignored_by_security_stack_walk();
+C2V_END
+
+C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
+C2V_END
+
+C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return CompilerOracle::should_inline(method) || method->force_inline();
+C2V_END
+
+C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve))
+ ResourceMark rm;
+ Handle name = JNIHandles::resolve(jname);
+ Symbol* class_name = java_lang_String::as_symbol(name, CHECK_0);
+ if (java_lang_String::length(name()) <= 1) {
+ THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
+ }
+
+ Klass* resolved_klass = NULL;
+ Handle class_loader;
+ Handle protection_domain;
+ if (JNIHandles::resolve(accessing_class) == NULL) {
+ THROW_0(vmSymbols::java_lang_NullPointerException());
+ }
+ Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
+ class_loader = accessing_klass->class_loader();
+ protection_domain = accessing_klass->protection_domain();
+
+ if (resolve) {
+ resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
+ } else {
+ if (class_name->byte_at(0) == 'L' &&
+ class_name->byte_at(class_name->utf8_length()-1) == ';') {
+ // This is a name from a signature. Strip off the trimmings.
+ // Call recursive to keep scope of strippedsym.
+ TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1,
+ class_name->utf8_length()-2,
+ CHECK_0);
+ resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0);
+ } else if (FieldType::is_array(class_name)) {
+ FieldArrayInfo fd;
+ // dimension and object_key in FieldArrayInfo are assigned as a side-effect
+ // of this call
+ BasicType t = FieldType::get_array_info(class_name, fd, CHECK_0);
+ if (t == T_OBJECT) {
+ TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
+ class_name->utf8_length()-2-fd.dimension(),
+ CHECK_0);
+ // naked oop "k" is OK here -- we assign back into it
+ resolved_klass = SystemDictionary::find(strippedsym,
+ class_loader,
+ protection_domain,
+ CHECK_0);
+ if (resolved_klass != NULL) {
+ resolved_klass = resolved_klass->array_klass(fd.dimension(), CHECK_0);
+ }
+ } else {
+ resolved_klass = Universe::typeArrayKlassObj(t);
+ resolved_klass = TypeArrayKlass::cast(resolved_klass)->array_klass(fd.dimension(), CHECK_0);
+ }
+ }
+ }
+ Handle result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ oop result = cp->resolve_constant_at(index, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ return cp->name_and_type_ref_index_at(index);
+C2V_END
+
+C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ Handle sym = java_lang_String::create_from_symbol(cp->name_ref_at(which), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ Handle sym = java_lang_String::create_from_symbol(cp->signature_ref_at(which), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ return cp->klass_ref_index_at(index);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ Klass* resolved_klass = cp->klass_at(index, CHECK_NULL);
+ Handle klass = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, klass());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ KlassHandle loading_klass(cp->pool_holder());
+ bool is_accessible = false;
+ KlassHandle klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass);
+ Symbol* symbol = NULL;
+ if (klass.is_null()) {
+ symbol = cp->klass_name_at(index);
+ }
+ Handle result;
+ if (!klass.is_null()) {
+ result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+ } else {
+ result = java_lang_String::create_from_symbol(symbol, CHECK_NULL);
+ }
+ return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
+ return JNIHandles::make_local(THREAD, appendix_oop);
+C2V_END
+
+C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ instanceKlassHandle pool_holder(cp->pool_holder());
+ Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+ methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder);
+ oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ return cp->remap_instruction_operand_from_cache(index);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode, jlongArray info_handle))
+ ResourceMark rm;
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
+ fieldDescriptor fd;
+ LinkInfo link_info(cp, index, CHECK_0);
+ LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
+ typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
+ assert(info != NULL && info->length() == 2, "must be");
+ info->long_at_put(0, (jlong) fd.access_flags().as_int());
+ info->long_at_put(1, (jlong) fd.offset());
+ oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, field_holder);
+C2V_END
+
+C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
+ ResourceMark rm;
+ Klass* klass = CompilerToVM::asKlass(jvmci_type);
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ if (klass->is_interface()) {
+ THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", klass->external_name()));
+ }
+ if (!method->method_holder()->is_interface()) {
+ THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+ }
+ if (!InstanceKlass::cast(klass)->is_initialized()) {
+ THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be initialized", klass->external_name()));
+ }
+ return LinkResolver::vtable_index_of_interface_method(klass, method);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
+ Klass* recv_klass = CompilerToVM::asKlass(receiver_jvmci_type);
+ Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type);
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+
+ if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) {
+ Klass* holder_klass = method->method_holder();
+ Symbol* method_name = method->name();
+ Symbol* method_signature = method->signature();
+
+ if (holder_klass->is_interface()) {
+ // do link-time resolution to check all access rules.
+ LinkInfo link_info(holder_klass, method_name, method_signature, caller_klass, true);
+ methodHandle resolved_method = LinkResolver::linktime_resolve_interface_method_or_null(link_info);
+ if (resolved_method.is_null() || resolved_method->is_private()) {
+ return NULL;
+ }
+ assert(recv_klass->is_subtype_of(holder_klass), "");
+ // do actual lookup
+ methodHandle sel_method = LinkResolver::lookup_instance_method_in_klasses(recv_klass, resolved_method->name(), resolved_method->signature(), CHECK_AND_CLEAR_0);
+ oop result = CompilerToVM::get_jvmci_method(sel_method, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+ } else {
+ // do link-time resolution to check all access rules.
+ LinkInfo link_info(holder_klass, method_name, method_signature, caller_klass, true);
+ methodHandle resolved_method = LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
+ if (resolved_method.is_null()) {
+ return NULL;
+ }
+ // do actual lookup (see LinkResolver::runtime_resolve_virtual_method)
+ int vtable_index = Method::invalid_vtable_index;
+ Method* selected_method;
+
+ if (resolved_method->method_holder()->is_interface()) { // miranda method
+ vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method);
+ assert(vtable_index >= 0 , "we should have valid vtable index at this point");
+
+ InstanceKlass* inst = InstanceKlass::cast(recv_klass);
+ selected_method = inst->method_at_vtable(vtable_index);
+ } else {
+ // at this point we are sure that resolved_method is virtual and not
+ // a miranda method; therefore, it must have a valid vtable index.
+ assert(!resolved_method->has_itable_index(), "");
+ vtable_index = resolved_method->vtable_index();
+ // We could get a negative vtable_index for final methods,
+ // because as an optimization they are they are never put in the vtable,
+ // unless they override an existing method.
+ // If we do get a negative, it means the resolved method is the the selected
+ // method, and it can never be changed by an override.
+ if (vtable_index == Method::nonvirtual_vtable_index) {
+ assert(resolved_method->can_be_statically_bound(), "cannot override this method");
+ selected_method = resolved_method();
+ } else {
+ // recv_klass might be an arrayKlassOop but all vtables start at
+ // the same place. The cast is to avoid virtual call and assertion.
+ InstanceKlass* inst = (InstanceKlass*)recv_klass;
+ selected_method = inst->method_at_vtable(vtable_index);
+ }
+ }
+ oop result = CompilerToVM::get_jvmci_method(selected_method, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+ }
+ }
+ return NULL;
+C2V_END
+
+C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type))
+ Klass* klass = CompilerToVM::asKlass(jvmci_type);
+ assert(klass != NULL, "method must not be called for primitive types");
+ return Dependencies::find_finalizable_subclass(klass) != NULL;
+C2V_END
+
+C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
+ InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
+ oop result = CompilerToVM::get_jvmci_method(klass->class_initializer(), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv*, jobject, jlong addr))
+ address target_addr = (address) addr;
+ if (target_addr != 0x0) {
+ int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
+ int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int));
+ return MAX2(ABS(off_low), ABS(off_high));
+ }
+ return -1;
+C2V_END
+
+C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ method->set_not_c1_compilable();
+ method->set_not_c2_compilable();
+ method->set_dont_inline(true);
+C2V_END
+
+C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject installed_code, jobject speculation_log))
+ ResourceMark rm;
+ HandleMark hm;
+ Handle target_handle = JNIHandles::resolve(target);
+ Handle compiled_code_handle = JNIHandles::resolve(compiled_code);
+ CodeBlob* cb = NULL;
+ Handle installed_code_handle = JNIHandles::resolve(installed_code);
+ Handle speculation_log_handle = JNIHandles::resolve(speculation_log);
+
+ JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR);
+
+ TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
+ CodeInstaller installer;
+ JVMCIEnv::CodeInstallResult result = installer.install(compiler, target_handle, compiled_code_handle, cb, installed_code_handle, speculation_log_handle);
+
+ if (PrintCodeCacheOnCompilation) {
+ stringStream s;
+ // Dump code cache into a buffer before locking the tty,
+ {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ CodeCache::print_summary(&s, false);
+ }
+ ttyLocker ttyl;
+ tty->print_raw_cr(s.as_string());
+ }
+
+ if (result != JVMCIEnv::ok) {
+ assert(cb == NULL, "should be");
+ } else {
+ if (!installed_code_handle.is_null()) {
+ assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
+ InstalledCode::set_address(installed_code_handle, (jlong) cb);
+ InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
+ if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
+ HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
+ HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
+ HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
+ }
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm != NULL && installed_code_handle->is_scavengable()) {
+ assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable");
+ if (!UseG1GC) {
+ assert(nm->on_scavenge_root_list(), "nm should be on scavengable list");
+ }
+ }
+ }
+ }
+ return result;
+C2V_END
+
+C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject metadata))
+ ResourceMark rm;
+ HandleMark hm;
+
+ Handle target_handle = JNIHandles::resolve(target);
+ Handle compiled_code_handle = JNIHandles::resolve(compiled_code);
+ Handle metadata_handle = JNIHandles::resolve(metadata);
+
+ HotSpotOopMap::klass()->initialize(thread);
+
+ CodeMetadata code_metadata;
+ CodeBlob *cb = NULL;
+ CodeInstaller installer;
+
+ JVMCIEnv::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata); //cb, pc_descs, nr_pc_descs, scopes_descs, scopes_size, reloc_buffer);
+ if (result != JVMCIEnv::ok) {
+ return result;
+ }
+
+ if (code_metadata.get_nr_pc_desc() > 0) {
+ typeArrayHandle pcArrayOop = oopFactory::new_byteArray(sizeof(PcDesc) * code_metadata.get_nr_pc_desc(), CHECK_(JVMCIEnv::cache_full));
+ memcpy(pcArrayOop->byte_at_addr(0), code_metadata.get_pc_desc(), sizeof(PcDesc) * code_metadata.get_nr_pc_desc());
+ HotSpotMetaData::set_pcDescBytes(metadata_handle, pcArrayOop());
+ }
+
+ if (code_metadata.get_scopes_size() > 0) {
+ typeArrayHandle scopesArrayOop = oopFactory::new_byteArray(code_metadata.get_scopes_size(), CHECK_(JVMCIEnv::cache_full));
+ memcpy(scopesArrayOop->byte_at_addr(0), code_metadata.get_scopes_desc(), code_metadata.get_scopes_size());
+ HotSpotMetaData::set_scopesDescBytes(metadata_handle, scopesArrayOop());
+ }
+
+ RelocBuffer* reloc_buffer = code_metadata.get_reloc_buffer();
+ typeArrayHandle relocArrayOop = oopFactory::new_byteArray((int) reloc_buffer->size(), CHECK_(JVMCIEnv::cache_full));
+ if (reloc_buffer->size() > 0) {
+ memcpy(relocArrayOop->byte_at_addr(0), reloc_buffer->begin(), reloc_buffer->size());
+ }
+ HotSpotMetaData::set_relocBytes(metadata_handle, relocArrayOop());
+
+ const OopMapSet* oopMapSet = installer.oopMapSet();
+ {
+ ResourceMark mark;
+ ImmutableOopMapBuilder builder(oopMapSet);
+ int oopmap_size = builder.heap_size();
+ typeArrayHandle oopMapArrayHandle = oopFactory::new_byteArray(oopmap_size, CHECK_(JVMCIEnv::cache_full));
+ builder.generate_into((address) oopMapArrayHandle->byte_at_addr(0));
+ HotSpotMetaData::set_oopMaps(metadata_handle, oopMapArrayHandle());
+ }
+
+ HotSpotMetaData::set_metadata(metadata_handle, NULL);
+
+ ExceptionHandlerTable* handler = code_metadata.get_exception_table();
+ int table_size = handler->size_in_bytes();
+ typeArrayHandle exceptionArrayOop = oopFactory::new_byteArray(table_size, CHECK_(JVMCIEnv::cache_full));
+
+ if (table_size > 0) {
+ handler->copy_bytes_to((address) exceptionArrayOop->byte_at_addr(0));
+ }
+ HotSpotMetaData::set_exceptionBytes(metadata_handle, exceptionArrayOop());
+
+ return result;
+C2V_END
+
+C2V_VMENTRY(void, notifyCompilationStatistics, (JNIEnv *jniEnv, jobject, jint id, jobject hotspot_method, jboolean osr, jint processedBytecodes, jlong time, jlong timeUnitsPerSecond, jobject installed_code))
+ JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
+ CompilerStatistics* stats = compiler->stats();
+
+ elapsedTimer timer = elapsedTimer(time, timeUnitsPerSecond);
+ if (osr) {
+ stats->_osr.update(timer, processedBytecodes);
+ } else {
+ stats->_standard.update(timer, processedBytecodes);
+ }
+ Handle installed_code_handle = JNIHandles::resolve(installed_code);
+ if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
+ stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
+ stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+ }
+
+ if (CITimeEach) {
+ methodHandle method = CompilerToVM::asMethod(hotspot_method);
+ float bytes_per_sec = 1.0 * processedBytecodes / timer.seconds();
+ tty->print_cr("%3d seconds: %f bytes/sec: %f (bytes %d)",
+ id, timer.seconds(), bytes_per_sec, processedBytecodes);
+ }
+C2V_END
+
+C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
+ JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
+ CompilerStatistics* stats = compiler->stats();
+ stats->_standard.reset();
+ stats->_osr.reset();
+C2V_END
+
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob))
+ ResourceMark rm;
+ HandleMark hm;
+
+ CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+ if (cb == NULL) {
+ return NULL;
+ }
+
+ // We don't want the stringStream buffer to resize during disassembly as it
+ // uses scoped resource memory. If a nested function called during disassembly uses
+ // a ResourceMark and the buffer expands within the scope of the mark,
+ // the buffer becomes garbage when that scope is exited. Experience shows that
+ // the disassembled code is typically about 10x the code size so a fixed buffer
+ // sized to 20x code size plus a fixed amount for header info should be sufficient.
+ int bufferSize = cb->code_size() * 20 + 1024;
+ char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize);
+ stringStream st(buffer, bufferSize);
+ if (cb->is_nmethod()) {
+ nmethod* nm = (nmethod*) cb;
+ if (!nm->is_alive()) {
+ return NULL;
+ }
+ Disassembler::decode(nm, &st);
+ } else {
+ Disassembler::decode(cb, &st);
+ }
+ if (st.size() <= 0) {
+ return NULL;
+ }
+
+ Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
+ return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv*, jobject, jobject jvmci_method, int bci))
+ ResourceMark rm;
+ HandleMark hm;
+
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, element);
+C2V_END
+
+C2V_VMENTRY(jobject, executeInstalledCode, (JNIEnv*, jobject, jobject args, jobject hotspotInstalledCode))
+ ResourceMark rm;
+ HandleMark hm;
+
+ jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
+ if (nmethodValue == 0L) {
+ THROW_NULL(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+ }
+ nmethod* nm = (nmethod*) (address) nmethodValue;
+ methodHandle mh = nm->method();
+ Symbol* signature = mh->signature();
+ JavaCallArguments jca(mh->size_of_parameters());
+
+ JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+ JavaValue result(jap.get_ret_type());
+ jca.set_alternative_target(nm);
+ JavaCalls::call(&result, mh, &jca, CHECK_NULL);
+
+ if (jap.get_ret_type() == T_VOID) {
+ return NULL;
+ } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
+ return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
+ } else {
+ jvalue *value = (jvalue *) result.get_value_addr();
+ // Narrow the value down if required (Important on big endian machines)
+ switch (jap.get_ret_type()) {
+ case T_BOOLEAN:
+ value->z = (jboolean) value->i;
+ break;
+ case T_BYTE:
+ value->b = (jbyte) value->i;
+ break;
+ case T_CHAR:
+ value->c = (jchar) value->i;
+ break;
+ case T_SHORT:
+ value->s = (jshort) value->i;
+ break;
+ }
+ oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, o);
+ }
+C2V_END
+
+C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv *, jobject, jobject jvmci_method))
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ if (!method->has_linenumber_table()) {
+ return NULL;
+ }
+ u2 num_entries = 0;
+ CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
+ while (streamForSize.read_pair()) {
+ num_entries++;
+ }
+
+ CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
+ typeArrayOop result = oopFactory::new_longArray(2 * num_entries, CHECK_NULL);
+
+ int i = 0;
+ jlong value;
+ while (stream.read_pair()) {
+ value = ((long) stream.bci());
+ result->long_at_put(i, value);
+ value = ((long) stream.line());
+ result->long_at_put(i + 1, value);
+ i += 2;
+ }
+
+ return (jlongArray) JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv *, jobject, jobject jvmci_method))
+ ResourceMark rm;
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ if (!method->has_localvariable_table()) {
+ return 0;
+ }
+ return (jlong) (address) method->localvariable_table_start();
+C2V_END
+
+C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv *, jobject, jobject jvmci_method))
+ ResourceMark rm;
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ return method->localvariable_table_length();
+C2V_END
+
+C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jobject jvmci_method))
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ MethodCounters* mcs = method->method_counters();
+ if (mcs != NULL) {
+ mcs->clear_counters();
+ }
+ NOT_PRODUCT(method->set_compiled_invocation_count(0));
+
+ nmethod* code = method->code();
+ if (code != NULL) {
+ code->make_not_entrant();
+ }
+
+ MethodData* method_data = method->method_data();
+ if (method_data == NULL) {
+ ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
+ method_data = MethodData::allocate(loader_data, method, CHECK);
+ method->set_method_data(method_data);
+ } else {
+ method_data->initialize();
+ }
+C2V_END
+
+
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject hotspotInstalledCode))
+ jlong nativeMethod = InstalledCode::address(hotspotInstalledCode);
+ nmethod* m = (nmethod*)nativeMethod;
+ if (m != NULL && !m->is_not_entrant()) {
+ m->mark_for_deoptimization();
+ VM_Deoptimize op;
+ VMThread::execute(&op);
+ }
+ InstalledCode::set_address(hotspotInstalledCode, 0);
+C2V_END
+
+C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr))
+ oop ret = oopDesc::load_decode_heap_oop((oop*)(address)addr);
+ return JNIHandles::make_local(THREAD, ret);
+C2V_END
+
+C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv*, jobject))
+ typeArrayOop arrayOop = oopFactory::new_longArray(JVMCICounterSize, CHECK_NULL);
+ JavaThread::collect_counters(arrayOop);
+ return (jlongArray) JNIHandles::make_local(THREAD, arrayOop);
+C2V_END
+
+C2V_VMENTRY(int, allocateCompileId, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci))
+ HandleMark hm;
+ ResourceMark rm;
+ if (JNIHandles::resolve(jvmci_method) == NULL) {
+ THROW_0(vmSymbols::java_lang_NullPointerException());
+ }
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ if (entry_bci >= method->code_size() || entry_bci < -1) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Unexpected bci %d", entry_bci));
+ }
+ return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
+C2V_END
+
+
+C2V_VMENTRY(jboolean, isMature, (JNIEnv*, jobject, jlong metaspace_method_data))
+ MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+ return mdo != NULL && mdo->is_mature();
+C2V_END
+
+C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci, int comp_level))
+ Method* method = CompilerToVM::asMethod(jvmci_method);
+ return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
+C2V_END
+
+C2V_VMENTRY(jobject, getSymbol, (JNIEnv*, jobject, jlong symbol))
+ Handle sym = java_lang_String::create_from_symbol((Symbol*)(address)symbol, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+bool matches(jobjectArray methods, Method* method) {
+ objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
+
+ for (int i = 0; i < methods_oop->length(); i++) {
+ if (CompilerToVM::asMethod(methods_oop->obj_at(i)) == method) {
+ return true;
+ }
+ }
+ return false;
+}
+
+C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject hs_frame, jobjectArray methods, jint initialSkip))
+ ResourceMark rm;
+
+ if (!thread->has_last_Java_frame()) return NULL;
+ Handle result = HotSpotStackFrameReference::klass()->allocate_instance(thread);
+ HotSpotStackFrameReference::klass()->initialize(thread);
+
+ StackFrameStream fst(thread);
+ if (hs_frame != NULL) {
+ // look for the correct stack frame if one is given
+ intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+ while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+ fst.next();
+ }
+ if (fst.current()->sp() != stack_pointer) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+ }
+ }
+
+ int frame_number = 0;
+ vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+ if (hs_frame != NULL) {
+ // look for the correct vframe within the stack frame if one is given
+ int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+ while (frame_number < last_frame_number) {
+ if (vf->is_top()) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+ }
+ vf = vf->sender();
+ frame_number ++;
+ }
+ // move one frame forward
+ if (vf->is_top()) {
+ if (fst.is_done()) {
+ return NULL;
+ }
+ fst.next();
+ vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+ frame_number = 0;
+ } else {
+ vf = vf->sender();
+ frame_number++;
+ }
+ }
+
+ while (true) {
+ // look for the given method
+ while (true) {
+ StackValueCollection* locals = NULL;
+ if (vf->is_compiled_frame()) {
+ // compiled method frame
+ compiledVFrame* cvf = compiledVFrame::cast(vf);
+ if (methods == NULL || matches(methods, cvf->method())) {
+ if (initialSkip > 0) {
+ initialSkip --;
+ } else {
+ ScopeDesc* scope = cvf->scope();
+ // native wrapper do not have a scope
+ if (scope != NULL && scope->objects() != NULL) {
+ bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), THREAD);
+ Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
+
+ GrowableArray<ScopeValue*>* local_values = scope->locals();
+ typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread);
+ for (int i = 0; i < local_values->length(); i++) {
+ ScopeValue* value = local_values->at(i);
+ if (value->is_object()) {
+ array->bool_at_put(i, true);
+ }
+ }
+ HotSpotStackFrameReference::set_localIsVirtual(result, array());
+ } else {
+ HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+ }
+
+ locals = cvf->locals();
+ HotSpotStackFrameReference::set_bci(result, cvf->bci());
+ oop method = CompilerToVM::get_jvmci_method(cvf->method(), CHECK_NULL);
+ HotSpotStackFrameReference::set_method(result, method);
+ }
+ }
+ } else if (vf->is_interpreted_frame()) {
+ // interpreted method frame
+ interpretedVFrame* ivf = interpretedVFrame::cast(vf);
+ if (methods == NULL || matches(methods, ivf->method())) {
+ if (initialSkip > 0) {
+ initialSkip --;
+ } else {
+ locals = ivf->locals();
+ HotSpotStackFrameReference::set_bci(result, ivf->bci());
+ oop method = CompilerToVM::get_jvmci_method(ivf->method(), CHECK_NULL);
+ HotSpotStackFrameReference::set_method(result, method);
+ HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+ }
+ }
+ }
+
+ // locals != NULL means that we found a matching frame and result is already partially initialized
+ if (locals != NULL) {
+ HotSpotStackFrameReference::set_compilerToVM(result, JNIHandles::resolve(compilerToVM));
+ HotSpotStackFrameReference::set_stackPointer(result, (jlong) fst.current()->sp());
+ HotSpotStackFrameReference::set_frameNumber(result, frame_number);
+
+ // initialize the locals array
+ objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread);
+ for (int i = 0; i < locals->size(); i++) {
+ StackValue* var = locals->at(i);
+ if (var->type() == T_OBJECT) {
+ array->obj_at_put(i, locals->at(i)->get_obj()());
+ }
+ }
+ HotSpotStackFrameReference::set_locals(result, array());
+
+ return JNIHandles::make_local(thread, result());
+ }
+
+ if (vf->is_top()) {
+ break;
+ }
+ frame_number++;
+ vf = vf->sender();
+ } // end of vframe loop
+
+ if (fst.is_done()) {
+ break;
+ }
+ fst.next();
+ vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+ frame_number = 0;
+ } // end of frame loop
+
+ // the end was reached without finding a matching method
+ return NULL;
+C2V_END
+
+C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ CallInfo callInfo;
+ LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokedynamic, CHECK);
+ ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
+ cp_cache_entry->set_dynamic_call(cp, callInfo);
+C2V_END
+
+C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+ constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+ CallInfo callInfo;
+ LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokehandle, CHECK);
+ ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
+ cp_cache_entry->set_method_handle(cp, callInfo);
+C2V_END
+
+C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
+ //see compute_recording_non_safepoints in debugInfroRec.cpp
+ if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
+ return true;
+ }
+ return DebugNonSafepoints;
+C2V_END
+
+// public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate))
+ ResourceMark rm;
+
+ if (hs_frame == NULL) {
+ THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
+ }
+
+ HotSpotStackFrameReference::klass()->initialize(thread);
+
+ // look for the given stack frame
+ StackFrameStream fst(thread);
+ intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+ while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+ fst.next();
+ }
+ if (fst.current()->sp() != stack_pointer) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+ }
+
+ if (invalidate) {
+ if (!fst.current()->is_compiled_frame()) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+ }
+ assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
+ ((nmethod*) fst.current()->cb())->make_not_entrant();
+ }
+ Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none);
+ // look for the frame again as it has been updated by deopt (pc, deopt state...)
+ StackFrameStream fstAfterDeopt(thread);
+ while (fstAfterDeopt.current()->sp() != stack_pointer && !fstAfterDeopt.is_done()) {
+ fstAfterDeopt.next();
+ }
+ if (fstAfterDeopt.current()->sp() != stack_pointer) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found after deopt")
+ }
+
+ vframe* vf = vframe::new_vframe(fstAfterDeopt.current(), fstAfterDeopt.register_map(), thread);
+ if (!vf->is_compiled_frame()) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+ }
+
+ GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
+ while (true) {
+ assert(vf->is_compiled_frame(), "Wrong frame type");
+ virtualFrames->push(compiledVFrame::cast(vf));
+ if (vf->is_top()) {
+ break;
+ }
+ vf = vf->sender();
+ }
+
+ int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+ if (last_frame_number >= virtualFrames->length()) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+ }
+
+ // Reallocate the non-escaping objects and restore their fields.
+ assert (virtualFrames->at(last_frame_number)->scope() != NULL,"invalid scope");
+ GrowableArray<ScopeValue*>* objects = virtualFrames->at(last_frame_number)->scope()->objects();
+
+ if (objects == NULL) {
+ // no objects to materialize
+ return;
+ }
+
+ bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, THREAD);
+ Deoptimization::reassign_fields(fstAfterDeopt.current(), fstAfterDeopt.register_map(), objects, realloc_failures, false);
+
+ for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
+ compiledVFrame* cvf = virtualFrames->at(frame_index);
+
+ GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
+ StackValueCollection* locals = cvf->locals();
+
+ if (locals != NULL) {
+ for (int i2 = 0; i2 < locals->size(); i2++) {
+ StackValue* var = locals->at(i2);
+ if (var->type() == T_OBJECT && scopeLocals->at(i2)->is_object()) {
+ jvalue val;
+ val.l = (jobject) locals->at(i2)->get_obj()();
+ cvf->update_local(T_OBJECT, i2, val);
+ }
+ }
+ }
+ }
+
+ // all locals are materialized by now
+ HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
+
+ // update the locals array
+ objArrayHandle array = HotSpotStackFrameReference::locals(hs_frame);
+ StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
+ for (int i = 0; i < locals->size(); i++) {
+ StackValue* var = locals->at(i);
+ if (var->type() == T_OBJECT) {
+ array->obj_at_put(i, locals->at(i)->get_obj()());
+ }
+ }
+C2V_END
+
+C2V_VMENTRY(void, writeDebugOutput, (JNIEnv*, jobject, jbyteArray bytes, jint offset, jint length))
+ if (bytes == NULL) {
+ THROW(vmSymbols::java_lang_NullPointerException());
+ }
+ typeArrayOop array = (typeArrayOop) JNIHandles::resolve(bytes);
+
+ // Check if offset and length are non negative.
+ if (offset < 0 || length < 0) {
+ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+ }
+ // Check if the range is valid.
+ if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array->length())) {
+ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+ }
+ while (length > 0) {
+ jbyte* start = array->byte_at_addr(offset);
+ tty->write((char*) start, MIN2(length, O_BUFLEN));
+ length -= O_BUFLEN;
+ offset += O_BUFLEN;
+ }
+C2V_END
+
+C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
+ tty->flush();
+C2V_END
+
+
+#define CC (char*) /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
+
+#define SPECULATION_LOG "Ljdk/vm/ci/meta/SpeculationLog;"
+#define STRING "Ljava/lang/String;"
+#define OBJECT "Ljava/lang/Object;"
+#define CLASS "Ljava/lang/Class;"
+#define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;"
+#define INSTALLED_CODE "Ljdk/vm/ci/code/InstalledCode;"
+#define TARGET_DESCRIPTION "Ljdk/vm/ci/code/TargetDescription;"
+#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;"
+#define HS_CONSTANT_POOL "Ljdk/vm/ci/hotspot/HotSpotConstantPool;"
+#define HS_COMPILED_CODE "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;"
+#define HS_METADATA "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
+#define HS_STACK_FRAME_REF "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
+#define METASPACE_METHOD_DATA "J"
+
+JNINativeMethod CompilerToVM::methods[] = {
+ {CC"getBytecode", CC"("HS_RESOLVED_METHOD")[B", FN_PTR(getBytecode)},
+ {CC"getExceptionTableStart", CC"("HS_RESOLVED_METHOD")J", FN_PTR(getExceptionTableStart)},
+ {CC"getExceptionTableLength", CC"("HS_RESOLVED_METHOD")I", FN_PTR(getExceptionTableLength)},
+ {CC"findUniqueConcreteMethod", CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD")"HS_RESOLVED_METHOD, FN_PTR(findUniqueConcreteMethod)},
+ {CC"getImplementor", CC"("HS_RESOLVED_KLASS")"HS_RESOLVED_KLASS, FN_PTR(getImplementor)},
+ {CC"getStackTraceElement", CC"("HS_RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
+ {CC"methodIsIgnoredBySecurityStackWalk", CC"("HS_RESOLVED_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
+ {CC"doNotInlineOrCompile", CC"("HS_RESOLVED_METHOD")V", FN_PTR(doNotInlineOrCompile)},
+ {CC"canInlineMethod", CC"("HS_RESOLVED_METHOD")Z", FN_PTR(canInlineMethod)},
+ {CC"shouldInlineMethod", CC"("HS_RESOLVED_METHOD")Z", FN_PTR(shouldInlineMethod)},
+ {CC"lookupType", CC"("STRING CLASS"Z)"HS_RESOLVED_KLASS, FN_PTR(lookupType)},
+ {CC"lookupNameInPool", CC"("HS_CONSTANT_POOL"I)"STRING, FN_PTR(lookupNameInPool)},
+ {CC"lookupNameAndTypeRefIndexInPool", CC"("HS_CONSTANT_POOL"I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)},
+ {CC"lookupSignatureInPool", CC"("HS_CONSTANT_POOL"I)"STRING, FN_PTR(lookupSignatureInPool)},
+ {CC"lookupKlassRefIndexInPool", CC"("HS_CONSTANT_POOL"I)I", FN_PTR(lookupKlassRefIndexInPool)},
+ {CC"lookupKlassInPool", CC"("HS_CONSTANT_POOL"I)Ljava/lang/Object;", FN_PTR(lookupKlassInPool)},
+ {CC"lookupAppendixInPool", CC"("HS_CONSTANT_POOL"I)"OBJECT, FN_PTR(lookupAppendixInPool)},
+ {CC"lookupMethodInPool", CC"("HS_CONSTANT_POOL"IB)"HS_RESOLVED_METHOD, FN_PTR(lookupMethodInPool)},
+ {CC"constantPoolRemapInstructionOperandFromCache", CC"("HS_CONSTANT_POOL"I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)},
+ {CC"resolveConstantInPool", CC"("HS_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolveConstantInPool)},
+ {CC"resolvePossiblyCachedConstantInPool", CC"("HS_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)},
+ {CC"resolveTypeInPool", CC"("HS_CONSTANT_POOL"I)"HS_RESOLVED_KLASS, FN_PTR(resolveTypeInPool)},
+ {CC"resolveFieldInPool", CC"("HS_CONSTANT_POOL"IB[J)"HS_RESOLVED_KLASS, FN_PTR(resolveFieldInPool)},
+ {CC"resolveInvokeDynamicInPool", CC"("HS_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeDynamicInPool)},
+ {CC"resolveInvokeHandleInPool", CC"("HS_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeHandleInPool)},
+ {CC"resolveMethod", CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS")"HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
+ {CC"getVtableIndexForInterfaceMethod", CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD")I", FN_PTR(getVtableIndexForInterfaceMethod)},
+ {CC"getClassInitializer", CC"("HS_RESOLVED_KLASS")"HS_RESOLVED_METHOD, FN_PTR(getClassInitializer)},
+ {CC"hasFinalizableSubclass", CC"("HS_RESOLVED_KLASS")Z", FN_PTR(hasFinalizableSubclass)},
+ {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)},
+ {CC"getResolvedJavaMethodAtSlot", CC"("CLASS"I)"HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethodAtSlot)},
+ {CC"getResolvedJavaMethod", CC"(Ljava/lang/Object;J)"HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethod)},
+ {CC"getConstantPool", CC"(Ljava/lang/Object;J)"HS_CONSTANT_POOL, FN_PTR(getConstantPool)},
+ {CC"getResolvedJavaType", CC"(Ljava/lang/Object;JZ)"HS_RESOLVED_KLASS, FN_PTR(getResolvedJavaType)},
+ {CC"initializeConfiguration", CC"()J", FN_PTR(initializeConfiguration)},
+ {CC"installCode", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode)},
+ {CC"getMetadata", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA")I", FN_PTR(getMetadata)},
+ {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)},
+ {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)},
+ {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)},
+ {CC"executeInstalledCode", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeInstalledCode)},
+ {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)},
+ {CC"getLocalVariableTableStart", CC"("HS_RESOLVED_METHOD")J", FN_PTR(getLocalVariableTableStart)},
+ {CC"getLocalVariableTableLength", CC"("HS_RESOLVED_METHOD")I", FN_PTR(getLocalVariableTableLength)},
+ {CC"reprofile", CC"("HS_RESOLVED_METHOD")V", FN_PTR(reprofile)},
+ {CC"invalidateInstalledCode", CC"("INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)},
+ {CC"readUncompressedOop", CC"(J)"OBJECT, FN_PTR(readUncompressedOop)},
+ {CC"collectCounters", CC"()[J", FN_PTR(collectCounters)},
+ {CC"allocateCompileId", CC"("HS_RESOLVED_METHOD"I)I", FN_PTR(allocateCompileId)},
+ {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)},
+ {CC"hasCompiledCodeForOSR", CC"("HS_RESOLVED_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)},
+ {CC"getSymbol", CC"(J)"STRING, FN_PTR(getSymbol)},
+ {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "["HS_RESOLVED_METHOD"I)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)},
+ {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)},
+ {CC"shouldDebugNonSafepoints", CC"()Z", FN_PTR(shouldDebugNonSafepoints)},
+ {CC"writeDebugOutput", CC"([BII)V", FN_PTR(writeDebugOutput)},
+ {CC"flushDebugOutput", CC"()V", FN_PTR(flushDebugOutput)},
+};
+
+int CompilerToVM::methods_count() {
+ return sizeof(methods) / sizeof(JNINativeMethod);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011, 2013, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
+#define SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
+
+#include "prims/jni.h"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+
+class CompilerToVM {
+public:
+ /**
+ * Tag bits used by lookupKlassInPool to distinguish the types in Java.
+ */
+ enum Tags {
+ KLASS_TAG = 0x0,
+ SYMBOL_TAG = 0x1
+ };
+
+ // FIXME This is only temporary until the GC code is changed.
+ static bool _supports_inline_contig_alloc;
+ static HeapWord** _heap_end_addr;
+ static HeapWord** _heap_top_addr;
+
+ static intptr_t tag_pointer(Klass* klass) {
+ return ((intptr_t) klass) | KLASS_TAG;
+ }
+
+ static intptr_t tag_pointer(Symbol* symbol) {
+ return ((intptr_t) symbol) | SYMBOL_TAG;
+ }
+
+ static JNINativeMethod methods[];
+ static int methods_count();
+
+ static inline Method* asMethod(jobject jvmci_method) {
+ return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+ }
+
+ static inline Method* asMethod(Handle jvmci_method) {
+ return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+ }
+
+ static inline Method* asMethod(oop jvmci_method) {
+ return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+ }
+
+ static inline ConstantPool* asConstantPool(jobject jvmci_constant_pool) {
+ return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+ }
+
+ static inline ConstantPool* asConstantPool(Handle jvmci_constant_pool) {
+ return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+ }
+
+ static inline ConstantPool* asConstantPool(oop jvmci_constant_pool) {
+ return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+ }
+
+ static inline Klass* asKlass(jobject jvmci_type) {
+ return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+ }
+
+ static inline Klass* asKlass(Handle jvmci_type) {
+ return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+ }
+
+ static inline Klass* asKlass(oop jvmci_type) {
+ return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+ }
+
+ static inline MethodData* asMethodData(jlong metaspaceMethodData) {
+ return (MethodData*) (address) metaspaceMethodData;
+ }
+
+ static oop get_jvmci_method(methodHandle method, TRAPS);
+
+ static oop get_jvmci_type(KlassHandle klass, TRAPS);
+};
+
+class JavaArgumentUnboxer : public SignatureIterator {
+ protected:
+ JavaCallArguments* _jca;
+ arrayOop _args;
+ int _index;
+
+ oop next_arg(BasicType expectedType) {
+ assert(_index < _args->length(), "out of bounds");
+ oop arg=((objArrayOop) (_args))->obj_at(_index++);
+ assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
+ return arg;
+ }
+
+ public:
+ JavaArgumentUnboxer(Symbol* signature, JavaCallArguments* jca, arrayOop args, bool is_static) : SignatureIterator(signature) {
+ this->_return_type = T_ILLEGAL;
+ _jca = jca;
+ _index = 0;
+ _args = args;
+ if (!is_static) {
+ _jca->push_oop(next_arg(T_OBJECT));
+ }
+ iterate();
+ assert(_index == args->length(), "arg count mismatch with signature");
+ }
+
+ inline void do_bool() { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); }
+ inline void do_char() { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); }
+ inline void do_short() { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); }
+ inline void do_byte() { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); }
+ inline void do_int() { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); }
+
+ inline void do_long() { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); }
+ inline void do_float() { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); }
+ inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); }
+
+ inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
+ inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+ inline void do_array(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+ inline void do_void() { }
+};
+
+#endif // SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 1999, 2011, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "classfile/javaAssertions.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/codeCache.hpp"
+#include "code/scopeDesc.hpp"
+#include "runtime/sweeper.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/compileLog.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/oopFactory.hpp"
+#include "memory/universe.inline.hpp"
+#include "oops/methodData.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/oop.inline.hpp"
+#include "prims/jvmtiExport.hpp"
+#include "runtime/init.hpp"
+#include "runtime/reflection.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/dtrace.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+
+JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter) {
+ _task = task;
+ _system_dictionary_modification_counter = system_dictionary_modification_counter;
+ {
+ // Get Jvmti capabilities under lock to get consistent values.
+ MutexLocker mu(JvmtiThreadState_lock);
+ _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
+ _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
+ _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
+ }
+}
+
+// ------------------------------------------------------------------
+// Note: the logic of this method should mirror the logic of
+// constantPoolOopDesc::verify_constant_pool_resolve.
+bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) {
+ if (accessing_klass->oop_is_objArray()) {
+ accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass();
+ }
+ if (!accessing_klass->oop_is_instance()) {
+ return true;
+ }
+
+ if (resolved_klass->oop_is_objArray()) {
+ // Find the element klass, if this is an array.
+ resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
+ }
+ if (resolved_klass->oop_is_instance()) {
+ return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+ }
+ return true;
+}
+
+// ------------------------------------------------------------------
+KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass,
+ constantPoolHandle& cpool,
+ Symbol* sym,
+ bool require_local) {
+ JVMCI_EXCEPTION_CONTEXT;
+
+ // Now we need to check the SystemDictionary
+ if (sym->byte_at(0) == 'L' &&
+ sym->byte_at(sym->utf8_length()-1) == ';') {
+ // This is a name from a signature. Strip off the trimmings.
+ // Call recursive to keep scope of strippedsym.
+ TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
+ sym->utf8_length()-2,
+ CHECK_(KlassHandle()));
+ return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);
+ }
+
+ Handle loader(THREAD, (oop)NULL);
+ Handle domain(THREAD, (oop)NULL);
+ if (!accessing_klass.is_null()) {
+ loader = Handle(THREAD, accessing_klass->class_loader());
+ domain = Handle(THREAD, accessing_klass->protection_domain());
+ }
+
+ KlassHandle found_klass;
+ {
+ ttyUnlocker ttyul; // release tty lock to avoid ordering problems
+ MutexLocker ml(Compile_lock);
+ Klass* kls;
+ if (!require_local) {
+ kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_(KlassHandle()));
+ } else {
+ kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_(KlassHandle()));
+ }
+ found_klass = KlassHandle(THREAD, kls);
+ }
+
+ // If we fail to find an array klass, look again for its element type.
+ // The element type may be available either locally or via constraints.
+ // In either case, if we can find the element type in the system dictionary,
+ // we must build an array type around it. The CI requires array klasses
+ // to be loaded if their element klasses are loaded, except when memory
+ // is exhausted.
+ if (sym->byte_at(0) == '[' &&
+ (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
+ // We have an unloaded array.
+ // Build it on the fly if the element class exists.
+ TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
+ sym->utf8_length()-1,
+ CHECK_(KlassHandle()));
+
+ // Get element Klass recursively.
+ KlassHandle elem_klass =
+ get_klass_by_name_impl(accessing_klass,
+ cpool,
+ elem_sym,
+ require_local);
+ if (!elem_klass.is_null()) {
+ // Now make an array for it
+ return elem_klass->array_klass(CHECK_(KlassHandle()));
+ }
+ }
+
+ if (found_klass.is_null() && !cpool.is_null() && cpool->has_preresolution()) {
+ // Look inside the constant pool for pre-resolved class entries.
+ for (int i = cpool->length() - 1; i >= 1; i--) {
+ if (cpool->tag_at(i).is_klass()) {
+ Klass* kls = cpool->resolved_klass_at(i);
+ if (kls->name() == sym) {
+ return kls;
+ }
+ }
+ }
+ }
+
+ return found_klass();
+}
+
+// ------------------------------------------------------------------
+KlassHandle JVMCIEnv::get_klass_by_name(KlassHandle& accessing_klass,
+ Symbol* klass_name,
+ bool require_local) {
+ ResourceMark rm;
+ constantPoolHandle cpool;
+ return get_klass_by_name_impl(accessing_klass,
+ cpool,
+ klass_name,
+ require_local);
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_klass_by_index.
+KlassHandle JVMCIEnv::get_klass_by_index_impl(constantPoolHandle& cpool,
+ int index,
+ bool& is_accessible,
+ KlassHandle& accessor) {
+ JVMCI_EXCEPTION_CONTEXT;
+ KlassHandle klass (THREAD, ConstantPool::klass_at_if_loaded(cpool, index));
+ Symbol* klass_name = NULL;
+ if (klass.is_null()) {
+ klass_name = cpool->klass_name_at(index);
+ }
+
+ if (klass.is_null()) {
+ // Not found in constant pool. Use the name to do the lookup.
+ KlassHandle k = get_klass_by_name_impl(accessor,
+ cpool,
+ klass_name,
+ false);
+ // Calculate accessibility the hard way.
+ if (k.is_null()) {
+ is_accessible = false;
+ } else if (k->class_loader() != accessor->class_loader() &&
+ get_klass_by_name_impl(accessor, cpool, k->name(), true).is_null()) {
+ // Loaded only remotely. Not linked yet.
+ is_accessible = false;
+ } else {
+ // Linked locally, and we must also check public/private, etc.
+ is_accessible = check_klass_accessibility(accessor, k);
+ }
+ if (!is_accessible) {
+ return KlassHandle();
+ }
+ return k;
+ }
+
+ // It is known to be accessible, since it was found in the constant pool.
+ is_accessible = true;
+ return klass;
+}
+
+// ------------------------------------------------------------------
+// Get a klass from the constant pool.
+KlassHandle JVMCIEnv::get_klass_by_index(constantPoolHandle& cpool,
+ int index,
+ bool& is_accessible,
+ KlassHandle& accessor) {
+ ResourceMark rm;
+ KlassHandle result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);
+ return result;
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_field_by_index.
+//
+// Implementation note: the results of field lookups are cached
+// in the accessor klass.
+void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle& klass, fieldDescriptor& field_desc,
+ int index) {
+ JVMCI_EXCEPTION_CONTEXT;
+
+ assert(klass->is_linked(), "must be linked before using its constant-pool");
+
+ constantPoolHandle cpool(thread, klass->constants());
+
+ // Get the field's name, signature, and type.
+ Symbol* name = cpool->name_ref_at(index);
+
+ int nt_index = cpool->name_and_type_ref_index_at(index);
+ int sig_index = cpool->signature_ref_index_at(nt_index);
+ Symbol* signature = cpool->symbol_at(sig_index);
+
+ // Get the field's declared holder.
+ int holder_index = cpool->klass_ref_index_at(index);
+ bool holder_is_accessible;
+ KlassHandle declared_holder = get_klass_by_index(cpool, holder_index,
+ holder_is_accessible,
+ klass);
+
+ // The declared holder of this field may not have been loaded.
+ // Bail out with partial field information.
+ if (!holder_is_accessible) {
+ return;
+ }
+
+
+ // Perform the field lookup.
+ Klass* canonical_holder =
+ InstanceKlass::cast(declared_holder())->find_field(name, signature, &field_desc);
+ if (canonical_holder == NULL) {
+ return;
+ }
+
+ assert(canonical_holder == field_desc.field_holder(), "just checking");
+}
+
+// ------------------------------------------------------------------
+// Get a field by index from a klass's constant pool.
+void JVMCIEnv::get_field_by_index(instanceKlassHandle& accessor, fieldDescriptor& fd, int index) {
+ ResourceMark rm;
+ return get_field_by_index_impl(accessor, fd, index);
+}
+
+// ------------------------------------------------------------------
+// Perform an appropriate method lookup based on accessor, holder,
+// name, signature, and bytecode.
+methodHandle JVMCIEnv::lookup_method(instanceKlassHandle& h_accessor,
+ instanceKlassHandle& h_holder,
+ Symbol* name,
+ Symbol* sig,
+ Bytecodes::Code bc) {
+ JVMCI_EXCEPTION_CONTEXT;
+ LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
+ methodHandle dest_method;
+ LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
+ switch (bc) {
+ case Bytecodes::_invokestatic:
+ dest_method =
+ LinkResolver::resolve_static_call_or_null(link_info);
+ break;
+ case Bytecodes::_invokespecial:
+ dest_method =
+ LinkResolver::resolve_special_call_or_null(link_info);
+ break;
+ case Bytecodes::_invokeinterface:
+ dest_method =
+ LinkResolver::linktime_resolve_interface_method_or_null(link_info);
+ break;
+ case Bytecodes::_invokevirtual:
+ dest_method =
+ LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
+ break;
+ default: ShouldNotReachHere();
+ }
+
+ return dest_method;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIEnv::get_method_by_index_impl(constantPoolHandle& cpool,
+ int index, Bytecodes::Code bc,
+ instanceKlassHandle& accessor) {
+ if (bc == Bytecodes::_invokedynamic) {
+ ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+ bool is_resolved = !cpce->is_f1_null();
+ if (is_resolved) {
+ // Get the invoker Method* from the constant pool.
+ // (The appendix argument, if any, will be noted in the method's signature.)
+ Method* adapter = cpce->f1_as_method();
+ return methodHandle(adapter);
+ }
+
+ return NULL;
+ }
+
+ int holder_index = cpool->klass_ref_index_at(index);
+ bool holder_is_accessible;
+ KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+
+ // Get the method's name and signature.
+ Symbol* name_sym = cpool->name_ref_at(index);
+ Symbol* sig_sym = cpool->signature_ref_at(index);
+
+ if (cpool->has_preresolution()
+ || (holder() == SystemDictionary::MethodHandle_klass() &&
+ MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
+ // Short-circuit lookups for JSR 292-related call sites.
+ // That is, do not rely only on name-based lookups, because they may fail
+ // if the names are not resolvable in the boot class loader (7056328).
+ switch (bc) {
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokeinterface:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ {
+ Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+ if (m != NULL) {
+ return m;
+ }
+ }
+ break;
+ }
+ }
+
+ if (holder_is_accessible) { // Our declared holder is loaded.
+ instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
+ methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
+ if (!m.is_null() &&
+ (bc == Bytecodes::_invokestatic
+ ? InstanceKlass::cast(m->method_holder())->is_not_initialized()
+ : !InstanceKlass::cast(m->method_holder())->is_loaded())) {
+ m = NULL;
+ }
+ if (!m.is_null()) {
+ // We found the method.
+ return m;
+ }
+ }
+
+ // Either the declared holder was not loaded, or the method could
+ // not be found.
+
+ return NULL;
+}
+
+// ------------------------------------------------------------------
+instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(KlassHandle& method_holder) {
+ // For the case of <array>.clone(), the method holder can be an ArrayKlass*
+ // instead of an InstanceKlass*. For that case simply pretend that the
+ // declared holder is Object.clone since that's where the call will bottom out.
+ if (method_holder->oop_is_instance()) {
+ return instanceKlassHandle(method_holder());
+ } else if (method_holder->oop_is_array()) {
+ return instanceKlassHandle(SystemDictionary::Object_klass());
+ } else {
+ ShouldNotReachHere();
+ }
+ return NULL;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIEnv::get_method_by_index(constantPoolHandle& cpool,
+ int index, Bytecodes::Code bc,
+ instanceKlassHandle& accessor) {
+ ResourceMark rm;
+ return get_method_by_index_impl(cpool, index, bc, accessor);
+}
+
+// ------------------------------------------------------------------
+// Check for changes to the system dictionary during compilation
+// class loads, evolution, breakpoints
+JVMCIEnv::CodeInstallResult JVMCIEnv::check_for_system_dictionary_modification(Dependencies* dependencies, Handle compiled_code,
+ JVMCIEnv* env, char** failure_detail) {
+ // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
+ if (env != NULL) {
+ if (!env->_jvmti_can_hotswap_or_post_breakpoint && JvmtiExport::can_hotswap_or_post_breakpoint()) {
+ *failure_detail = (char*) "Hotswapping or breakpointing was enabled during compilation";
+ return JVMCIEnv::dependencies_failed;
+ }
+ }
+
+ // Dependencies must be checked when the system dictionary changes
+ // or if we don't know whether it has changed (i.e., env == NULL).
+ // In debug mode, always check dependencies.
+ bool counter_changed = env != NULL && env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications();
+ bool verify_deps = env == NULL || trueInDebug || JavaAssertions::enabled(SystemDictionary::HotSpotInstalledCode_klass()->name()->as_C_string(), true);
+ if (!counter_changed && !verify_deps) {
+ return JVMCIEnv::ok;
+ }
+
+ for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
+ Klass* witness = deps.check_dependency();
+ if (witness != NULL) {
+ // Use a fixed size buffer to prevent the string stream from
+ // resizing in the context of an inner resource mark.
+ char* buffer = NEW_RESOURCE_ARRAY(char, O_BUFLEN);
+ stringStream st(buffer, O_BUFLEN);
+ deps.print_dependency(witness, true, &st);
+ *failure_detail = st.as_string();
+ if (env == NULL || counter_changed) {
+ return JVMCIEnv::dependencies_failed;
+ } else {
+ // The dependencies were invalid at the time of installation
+ // without any intervening modification of the system
+ // dictionary. That means they were invalidly constructed.
+ return JVMCIEnv::dependencies_invalid;
+ }
+ }
+ if (LogCompilation) {
+ deps.log_dependency();
+ }
+ }
+
+ return JVMCIEnv::ok;
+}
+
+// ------------------------------------------------------------------
+JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
+ methodHandle& method,
+ nmethod*& nm,
+ int entry_bci,
+ CodeOffsets* offsets,
+ int orig_pc_offset,
+ CodeBuffer* code_buffer,
+ int frame_words,
+ OopMapSet* oop_map_set,
+ ExceptionHandlerTable* handler_table,
+ AbstractCompiler* compiler,
+ DebugInformationRecorder* debug_info,
+ Dependencies* dependencies,
+ JVMCIEnv* env,
+ int compile_id,
+ bool has_unsafe_access,
+ bool has_wide_vector,
+ Handle installed_code,
+ Handle compiled_code,
+ Handle speculation_log) {
+ JVMCI_EXCEPTION_CONTEXT;
+ nm = NULL;
+ int comp_level = CompLevel_full_optimization;
+ char* failure_detail = NULL;
+ JVMCIEnv::CodeInstallResult result;
+ {
+ // To prevent compile queue updates.
+ MutexLocker locker(MethodCompileQueue_lock, THREAD);
+
+ // Prevent SystemDictionary::add_to_hierarchy from running
+ // and invalidating our dependencies until we install this method.
+ MutexLocker ml(Compile_lock);
+
+ // Encode the dependencies now, so we can check them right away.
+ dependencies->encode_content_bytes();
+
+ // Check for {class loads, evolution, breakpoints} during compilation
+ result = check_for_system_dictionary_modification(dependencies, compiled_code, env, &failure_detail);
+ if (result != JVMCIEnv::ok) {
+ // While not a true deoptimization, it is a preemptive decompile.
+ MethodData* mdp = method()->method_data();
+ if (mdp != NULL) {
+ mdp->inc_decompile_count();
+ if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
+ // TODO (chaeubl) enable this in the fastdebug build only once we are more stable
+ ResourceMark m;
+ tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
+ //ShouldNotReachHere();
+ }
+ }
+
+ // All buffers in the CodeBuffer are allocated in the CodeCache.
+ // If the code buffer is created on each compile attempt
+ // as in C2, then it must be freed.
+ //code_buffer->free_blob();
+ } else {
+ ImplicitExceptionTable implicit_tbl;
+ nm = nmethod::new_nmethod(method,
+ compile_id,
+ entry_bci,
+ offsets,
+ orig_pc_offset,
+ debug_info, dependencies, code_buffer,
+ frame_words, oop_map_set,
+ handler_table, &implicit_tbl,
+ compiler, comp_level, installed_code, speculation_log);
+
+ // Free codeBlobs
+ //code_buffer->free_blob();
+ if (nm == NULL) {
+ // The CodeCache is full. Print out warning and disable compilation.
+ {
+ MutexUnlocker ml(Compile_lock);
+ MutexUnlocker locker(MethodCompileQueue_lock);
+ CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level));
+ }
+ } else {
+ nm->set_has_unsafe_access(has_unsafe_access);
+ nm->set_has_wide_vectors(has_wide_vector);
+
+ // Record successful registration.
+ // (Put nm into the task handle *before* publishing to the Java heap.)
+ CompileTask* task = env == NULL ? NULL : env->task();
+ if (task != NULL) task->set_code(nm);
+
+ if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
+ if (entry_bci == InvocationEntryBci) {
+ if (TieredCompilation) {
+ // If there is an old version we're done with it
+ nmethod* old = method->code();
+ if (TraceMethodReplacement && old != NULL) {
+ ResourceMark rm;
+ char *method_name = method->name_and_sig_as_C_string();
+ tty->print_cr("Replacing method %s", method_name);
+ }
+ if (old != NULL ) {
+ old->make_not_entrant();
+ }
+ }
+ if (TraceNMethodInstalls) {
+ ResourceMark rm;
+ char *method_name = method->name_and_sig_as_C_string();
+ ttyLocker ttyl;
+ tty->print_cr("Installing method (%d) %s [entry point: %p]",
+ comp_level,
+ method_name, nm->entry_point());
+ }
+ // Allow the code to be executed
+ method->set_code(method, nm);
+ } else {
+ if (TraceNMethodInstalls ) {
+ ResourceMark rm;
+ char *method_name = method->name_and_sig_as_C_string();
+ ttyLocker ttyl;
+ tty->print_cr("Installing osr method (%d) %s @ %d",
+ comp_level,
+ method_name,
+ entry_bci);
+ }
+ InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
+ }
+ }
+ }
+ result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
+ }
+ }
+
+ // String creation must be done outside lock
+ if (failure_detail != NULL) {
+ // A failure to allocate the string is silently ignored.
+ Handle message = java_lang_String::create_from_str(failure_detail, THREAD);
+ HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
+ }
+
+ // JVMTI -- compiled method notification (must be done outside lock)
+ if (nm != NULL) {
+ nm->post_compiled_method_load_event();
+ }
+
+ return result;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1999, 2011, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCIENV_HPP
+#define SHARE_VM_JVMCI_JVMCIENV_HPP
+
+#include "classfile/systemDictionary.hpp"
+#include "code/debugInfoRec.hpp"
+#include "code/dependencies.hpp"
+#include "code/exceptionHandlerTable.hpp"
+#include "compiler/oopMap.hpp"
+#include "runtime/thread.hpp"
+
+class CompileTask;
+
+// Bring the JVMCI compiler thread into the VM state.
+#define JVMCI_VM_ENTRY_MARK \
+ JavaThread* thread = JavaThread::current(); \
+ ThreadInVMfromNative __tiv(thread); \
+ ResetNoHandleMark rnhm; \
+ HandleMarkCleaner __hm(thread); \
+ Thread* THREAD = thread; \
+ debug_only(VMNativeEntryWrapper __vew;)
+
+#define JVMCI_EXCEPTION_CONTEXT \
+ JavaThread* thread=JavaThread::current(); \
+ Thread* THREAD = thread;
+
+//
+// This class is the top level broker for requests from the compiler
+// to the VM.
+class JVMCIEnv : StackObj {
+ CI_PACKAGE_ACCESS_TO
+
+ friend class CompileBroker;
+ friend class Dependencies; // for get_object, during logging
+
+public:
+
+ enum CodeInstallResult {
+ ok,
+ dependencies_failed,
+ dependencies_invalid,
+ cache_full,
+ code_too_large
+ };
+
+ // Look up a klass by name from a particular class loader (the accessor's).
+ // If require_local, result must be defined in that class loader, or NULL.
+ // If !require_local, a result from remote class loader may be reported,
+ // if sufficient class loader constraints exist such that initiating
+ // a class loading request from the given loader is bound to return
+ // the class defined in the remote loader (or throw an error).
+ //
+ // Return an unloaded klass if !require_local and no class at all is found.
+ //
+ // The CI treats a klass as loaded if it is consistently defined in
+ // another loader, even if it hasn't yet been loaded in all loaders
+ // that could potentially see it via delegation.
+ static KlassHandle get_klass_by_name(KlassHandle& accessing_klass,
+ Symbol* klass_name,
+ bool require_local);
+
+ // Constant pool access.
+ static KlassHandle get_klass_by_index(constantPoolHandle& cpool,
+ int klass_index,
+ bool& is_accessible,
+ KlassHandle& loading_klass);
+ static void get_field_by_index(instanceKlassHandle& loading_klass, fieldDescriptor& fd,
+ int field_index);
+ static methodHandle get_method_by_index(constantPoolHandle& cpool,
+ int method_index, Bytecodes::Code bc,
+ instanceKlassHandle& loading_klass);
+
+ JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter);
+
+private:
+ CompileTask* _task;
+ int _system_dictionary_modification_counter;
+
+ // Cache JVMTI state
+ bool _jvmti_can_hotswap_or_post_breakpoint;
+ bool _jvmti_can_access_local_variables;
+ bool _jvmti_can_post_on_exceptions;
+
+ // Implementation methods for loading and constant pool access.
+ static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass,
+ constantPoolHandle& cpool,
+ Symbol* klass_name,
+ bool require_local);
+ static KlassHandle get_klass_by_index_impl(constantPoolHandle& cpool,
+ int klass_index,
+ bool& is_accessible,
+ KlassHandle& loading_klass);
+ static void get_field_by_index_impl(instanceKlassHandle& loading_klass, fieldDescriptor& fd,
+ int field_index);
+ static methodHandle get_method_by_index_impl(constantPoolHandle& cpool,
+ int method_index, Bytecodes::Code bc,
+ instanceKlassHandle& loading_klass);
+
+ // Helper methods
+ static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass);
+ static methodHandle lookup_method(instanceKlassHandle& accessor,
+ instanceKlassHandle& holder,
+ Symbol* name,
+ Symbol* sig,
+ Bytecodes::Code bc);
+
+ private:
+
+ // Is this thread currently in the VM state?
+ static bool is_in_vm();
+
+ // Helper routine for determining the validity of a compilation
+ // with respect to concurrent class loading.
+ static JVMCIEnv::CodeInstallResult check_for_system_dictionary_modification(Dependencies* target, Handle compiled_code,
+ JVMCIEnv* env, char** failure_detail);
+
+public:
+ CompileTask* task() { return _task; }
+
+ // Register the result of a compilation.
+ static JVMCIEnv::CodeInstallResult register_method(
+ methodHandle& target,
+ nmethod*& nm,
+ int entry_bci,
+ CodeOffsets* offsets,
+ int orig_pc_offset,
+ CodeBuffer* code_buffer,
+ int frame_words,
+ OopMapSet* oop_map_set,
+ ExceptionHandlerTable* handler_table,
+ AbstractCompiler* compiler,
+ DebugInformationRecorder* debug_info,
+ Dependencies* dependencies,
+ JVMCIEnv* env,
+ int compile_id,
+ bool has_unsafe_access,
+ bool has_wide_vector,
+ Handle installed_code,
+ Handle compiled_code,
+ Handle speculation_log);
+
+ // converts the Klass* representing the holder of a method into a
+ // InstanceKlass*. This is needed since the holder of a method in
+ // the bytecodes could be an array type. Basically this converts
+ // array types into java/lang/Object and other types stay as they are.
+ static instanceKlassHandle get_instance_klass_for_declared_method_holder(KlassHandle& klass);
+};
+
+#endif // SHARE_VM_JVMCI_JVMCIENV_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "runtime/jniHandles.hpp"
+#include "classfile/symbolTable.hpp"
+#include "memory/resourceArea.hpp"
+
+// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field.
+// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
+
+void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field) {
+ InstanceKlass* ik = InstanceKlass::cast(klass);
+ Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
+ Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
+ if (name_symbol == NULL || signature_symbol == NULL) {
+#ifndef PRODUCT
+ ik->print_on(tty);
+#endif
+ fatal(err_msg("symbol with name %s and signature %s was not found in symbol table (klass=%s)", name, signature, klass->name()->as_C_string()));
+ }
+
+ fieldDescriptor fd;
+ if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
+ ResourceMark rm;
+ fatal(err_msg("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name()));
+ }
+ guarantee(fd.is_static() == static_field, "static/instance mismatch");
+ dest_offset = fd.offset();
+ assert(dest_offset != 0, "must be valid offset");
+}
+
+// This piece of macro magic creates the contents of the jvmci_compute_offsets method that initializes the field indices of all the access classes.
+
+#define START_CLASS(name) { Klass* k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name "");
+
+#define END_CLASS }
+
+#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field);
+#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false)
+#define INT_FIELD(klass, name) FIELD(klass, name, "I", false)
+#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false)
+#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false)
+#define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false)
+#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false)
+#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true)
+#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", true)
+
+
+void JVMCIJavaClasses::compute_offsets() {
+ COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+ guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!");
+}
+
+#define EMPTY0
+#define EMPTY1(x)
+#define EMPTY2(x,y)
+#define FIELD2(klass, name) int klass::_##name##_offset = 0;
+#define FIELD3(klass, name, sig) FIELD2(klass, name)
+
+COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2)
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2011, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
+#define SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
+
+#include "classfile/systemDictionary.hpp"
+#include "oops/instanceMirrorKlass.hpp"
+
+class JVMCIJavaClasses : AllStatic {
+ public:
+ static void compute_offsets();
+};
+
+/* This macro defines the structure of the CompilationResult - classes.
+ * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles.
+ *
+ * The public interface of these classes will look like this:
+
+ * class StackSlot : AllStatic {
+ * public:
+ * static Klass* klass();
+ * static jint index(oop obj);
+ * static jint index(Handle obj);
+ * static jint index(jobject obj);
+ * static void set_index(oop obj, jint x);
+ * static void set_index(Handle obj, jint x);
+ * static void set_index(jobject obj, jint x);
+ * };
+ *
+ */
+
+#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, typeArrayOop_field, objArrayOop_field, static_oop_field, static_objArrayOop_field, static_int_field, static_boolean_field) \
+ start_class(Architecture) \
+ oop_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;") \
+ end_class \
+ start_class(TargetDescription) \
+ oop_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;") \
+ end_class \
+ start_class(HotSpotResolvedObjectTypeImpl) \
+ oop_field(HotSpotResolvedObjectTypeImpl, javaClass, "Ljava/lang/Class;") \
+ end_class \
+ start_class(HotSpotResolvedJavaMethodImpl) \
+ long_field(HotSpotResolvedJavaMethodImpl, metaspaceMethod) \
+ end_class \
+ start_class(InstalledCode) \
+ long_field(InstalledCode, address) \
+ long_field(InstalledCode, version) \
+ oop_field(InstalledCode, name, "Ljava/lang/String;") \
+ end_class \
+ start_class(HotSpotInstalledCode) \
+ int_field(HotSpotInstalledCode, size) \
+ long_field(HotSpotInstalledCode, codeStart) \
+ int_field(HotSpotInstalledCode, codeSize) \
+ end_class \
+ start_class(HotSpotNmethod) \
+ boolean_field(HotSpotNmethod, isDefault) \
+ end_class \
+ start_class(HotSpotCompiledCode) \
+ oop_field(HotSpotCompiledCode, name, "Ljava/lang/String;") \
+ objArrayOop_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/CompilationResult$Site;") \
+ objArrayOop_field(HotSpotCompiledCode, exceptionHandlers, "[Ljdk/vm/ci/code/CompilationResult$ExceptionHandler;") \
+ objArrayOop_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;") \
+ objArrayOop_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;") \
+ typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B") \
+ int_field(HotSpotCompiledCode, targetCodeSize) \
+ typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B") \
+ int_field(HotSpotCompiledCode, dataSectionAlignment) \
+ objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/CompilationResult$DataPatch;") \
+ boolean_field(HotSpotCompiledCode, isImmutablePIC) \
+ int_field(HotSpotCompiledCode, totalFrameSize) \
+ int_field(HotSpotCompiledCode, customStackAreaOffset) \
+ objArrayOop_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;") \
+ end_class \
+ start_class(HotSpotCompiledCode_Comment) \
+ oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;") \
+ int_field(HotSpotCompiledCode_Comment, pcOffset) \
+ end_class \
+ start_class(HotSpotCompiledNmethod) \
+ oop_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
+ oop_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;") \
+ int_field(HotSpotCompiledNmethod, entryBCI) \
+ int_field(HotSpotCompiledNmethod, id) \
+ long_field(HotSpotCompiledNmethod, jvmciEnv) \
+ boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess) \
+ end_class \
+ start_class(HotSpotJVMCIMetaAccessContext) \
+ static_objArrayOop_field(HotSpotJVMCIMetaAccessContext, allContexts, "[Ljava/lang/ref/WeakReference;") \
+ objArrayOop_field(HotSpotJVMCIMetaAccessContext, metadataRoots, "[Ljava/lang/Object;") \
+ end_class \
+ start_class(HotSpotForeignCallTarget) \
+ long_field(HotSpotForeignCallTarget, address) \
+ end_class \
+ start_class(Assumptions_NoFinalizableSubclass) \
+ oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ end_class \
+ start_class(Assumptions_ConcreteSubtype) \
+ oop_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ oop_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ end_class \
+ start_class(Assumptions_LeafType) \
+ oop_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ end_class \
+ start_class(Assumptions_ConcreteMethod) \
+ oop_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;") \
+ oop_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ oop_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;") \
+ end_class \
+ start_class(Assumptions_CallSiteTargetValue) \
+ oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljava/lang/invoke/CallSite;") \
+ oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljava/lang/invoke/MethodHandle;") \
+ end_class \
+ start_class(CompilationResult_Site) \
+ int_field(CompilationResult_Site, pcOffset) \
+ end_class \
+ start_class(CompilationResult_Call) \
+ oop_field(CompilationResult_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;") \
+ oop_field(CompilationResult_Call, debugInfo, "Ljdk/vm/ci/code/DebugInfo;") \
+ end_class \
+ start_class(CompilationResult_DataPatch) \
+ oop_field(CompilationResult_DataPatch, reference, "Ljdk/vm/ci/code/CompilationResult$Reference;") \
+ end_class \
+ start_class(CompilationResult_ConstantReference) \
+ oop_field(CompilationResult_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;") \
+ end_class \
+ start_class(CompilationResult_DataSectionReference) \
+ int_field(CompilationResult_DataSectionReference, offset) \
+ end_class \
+ start_class(InfopointReason) \
+ static_oop_field(InfopointReason, UNKNOWN, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, CALL, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, METHOD_START, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, METHOD_END, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, LINE_NUMBER, "Ljdk/vm/ci/code/InfopointReason;") \
+ static_oop_field(InfopointReason, METASPACE_ACCESS, "Ljdk/vm/ci/code/InfopointReason;") \
+ end_class \
+ start_class(CompilationResult_Infopoint) \
+ oop_field(CompilationResult_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;") \
+ oop_field(CompilationResult_Infopoint, reason, "Ljdk/vm/ci/code/InfopointReason;") \
+ end_class \
+ start_class(CompilationResult_ExceptionHandler) \
+ int_field(CompilationResult_ExceptionHandler, handlerPos) \
+ end_class \
+ start_class(CompilationResult_Mark) \
+ oop_field(CompilationResult_Mark, id, "Ljava/lang/Object;") \
+ end_class \
+ start_class(DebugInfo) \
+ oop_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;") \
+ oop_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;") \
+ oop_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;") \
+ objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;") \
+ end_class \
+ start_class(HotSpotReferenceMap) \
+ objArrayOop_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;") \
+ objArrayOop_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;") \
+ typeArrayOop_field(HotSpotReferenceMap, sizeInBytes, "[I") \
+ int_field(HotSpotReferenceMap, maxRegisterSize) \
+ end_class \
+ start_class(RegisterSaveLayout) \
+ objArrayOop_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;") \
+ typeArrayOop_field(RegisterSaveLayout, slots, "[I") \
+ end_class \
+ start_class(BytecodeFrame) \
+ objArrayOop_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;") \
+ objArrayOop_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;") \
+ int_field(BytecodeFrame, numLocals) \
+ int_field(BytecodeFrame, numStack) \
+ int_field(BytecodeFrame, numLocks) \
+ boolean_field(BytecodeFrame, rethrowException) \
+ boolean_field(BytecodeFrame, duringCall) \
+ static_int_field(BytecodeFrame, BEFORE_BCI) \
+ end_class \
+ start_class(BytecodePosition) \
+ oop_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;") \
+ oop_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;") \
+ int_field(BytecodePosition, bci) \
+ end_class \
+ start_class(JavaConstant) \
+ end_class \
+ start_class(PrimitiveConstant) \
+ oop_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;") \
+ long_field(PrimitiveConstant, primitive) \
+ end_class \
+ start_class(RawConstant) \
+ long_field(RawConstant, primitive) \
+ end_class \
+ start_class(NullConstant) \
+ end_class \
+ start_class(HotSpotCompressedNullConstant) \
+ end_class \
+ start_class(HotSpotObjectConstantImpl) \
+ oop_field(HotSpotObjectConstantImpl, object, "Ljava/lang/Object;") \
+ boolean_field(HotSpotObjectConstantImpl, compressed) \
+ end_class \
+ start_class(HotSpotMetaspaceConstantImpl) \
+ long_field(HotSpotMetaspaceConstantImpl, primitive) \
+ oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljava/lang/Object;") \
+ boolean_field(HotSpotMetaspaceConstantImpl, compressed) \
+ end_class \
+ start_class(HotSpotSentinelConstant) \
+ end_class \
+ start_class(JavaKind) \
+ char_field(JavaKind, typeChar) \
+ static_oop_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;"); \
+ static_oop_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;"); \
+ static_oop_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;"); \
+ static_oop_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;"); \
+ static_oop_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;"); \
+ static_oop_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;"); \
+ end_class \
+ start_class(LIRKind) \
+ oop_field(LIRKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;") \
+ int_field(LIRKind, referenceMask) \
+ end_class \
+ start_class(Value) \
+ oop_field(Value, lirKind, "Ljdk/vm/ci/meta/LIRKind;") \
+ static_oop_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;"); \
+ end_class \
+ start_class(RegisterValue) \
+ oop_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;") \
+ end_class \
+ start_class(code_Location) \
+ oop_field(code_Location, reg, "Ljdk/vm/ci/code/Register;") \
+ int_field(code_Location, offset) \
+ end_class \
+ start_class(code_Register) \
+ int_field(code_Register, number) \
+ int_field(code_Register, encoding) \
+ end_class \
+ start_class(StackSlot) \
+ int_field(StackSlot, offset) \
+ boolean_field(StackSlot, addFrameSize) \
+ end_class \
+ start_class(VirtualObject) \
+ int_field(VirtualObject, id) \
+ oop_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;") \
+ objArrayOop_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;") \
+ objArrayOop_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;") \
+ end_class \
+ start_class(StackLockValue) \
+ oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;") \
+ oop_field(StackLockValue, slot, "Ljdk/vm/ci/code/StackSlotValue;") \
+ boolean_field(StackLockValue, eliminated) \
+ end_class \
+ start_class(SpeculationLog) \
+ oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;") \
+ end_class \
+ start_class(HotSpotStackFrameReference) \
+ oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;") \
+ long_field(HotSpotStackFrameReference, stackPointer) \
+ int_field(HotSpotStackFrameReference, frameNumber) \
+ int_field(HotSpotStackFrameReference, bci) \
+ oop_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
+ objArrayOop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;") \
+ typeArrayOop_field(HotSpotStackFrameReference, localIsVirtual, "[Z") \
+ end_class \
+ start_class(HotSpotMetaData) \
+ typeArrayOop_field(HotSpotMetaData, pcDescBytes, "[B") \
+ typeArrayOop_field(HotSpotMetaData, scopesDescBytes, "[B") \
+ typeArrayOop_field(HotSpotMetaData, relocBytes, "[B") \
+ typeArrayOop_field(HotSpotMetaData, exceptionBytes, "[B") \
+ typeArrayOop_field(HotSpotMetaData, oopMaps, "[B") \
+ objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/String;") \
+ end_class \
+ start_class(HotSpotOopMap) \
+ int_field(HotSpotOopMap, offset) \
+ int_field(HotSpotOopMap, count) \
+ typeArrayOop_field(HotSpotOopMap, data, "[B") \
+ end_class \
+ start_class(HotSpotConstantPool) \
+ long_field(HotSpotConstantPool, metaspaceConstantPool) \
+ end_class \
+ /* end*/
+
+
+#define START_CLASS(name) \
+class name : AllStatic { \
+ private: \
+ friend class JVMCICompiler; \
+ static void check(oop obj, const char* field_name, int offset) { \
+ assert(obj != NULL, err_msg("NULL field access of %s.%s", #name, field_name)); \
+ assert(obj->is_a(SystemDictionary::name##_klass()), err_msg("wrong class, " #name " expected, found %s", obj->klass()->external_name())); \
+ assert(offset != 0, "must be valid offset"); \
+ } \
+ static void compute_offsets(); \
+ public: \
+ static InstanceKlass* klass() { return SystemDictionary::name##_klass() == NULL ? NULL : InstanceKlass::cast(SystemDictionary::name##_klass()); }
+
+#define END_CLASS };
+
+#define FIELD(name, type, accessor, cast) \
+ static int _##name##_offset; \
+ static type name(oop obj) { check(obj, #name, _##name##_offset); return cast obj->accessor(_##name##_offset); } \
+ static type name(Handle& obj) { check(obj(), #name, _##name##_offset); return cast obj->accessor(_##name##_offset); } \
+ static type name(jobject obj) { check(JNIHandles::resolve(obj), #name, _##name##_offset); return cast JNIHandles::resolve(obj)->accessor(_##name##_offset); } \
+ static void set_##name(oop obj, type x) { check(obj, #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); } \
+ static void set_##name(Handle& obj, type x) { check(obj(), #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); } \
+ static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj), #name, _##name##_offset); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); }
+
+#define EMPTY_CAST
+#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field, EMPTY_CAST)
+#define INT_FIELD(klass, name) FIELD(name, jint, int_field, EMPTY_CAST)
+#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field, EMPTY_CAST)
+#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field, EMPTY_CAST)
+#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field, EMPTY_CAST)
+#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field, EMPTY_CAST)
+#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(name, objArrayOop, obj_field, (objArrayOop))
+#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(name, typeArrayOop, obj_field, (typeArrayOop))
+#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
+#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
+#define STATIC_OOPISH_FIELD(klassName, name, type, signature) \
+ static int _##name##_offset; \
+ static type name() { \
+ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+ InstanceKlass* ik = klassName::klass(); \
+ address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+ if (UseCompressedOops) { \
+ return (type) oopDesc::load_decode_heap_oop((narrowOop *)addr); \
+ } else { \
+ return (type) oopDesc::load_decode_heap_oop((oop*)addr); \
+ } \
+ } \
+ static void set_##name(type x) { \
+ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+ assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName); \
+ InstanceKlass* ik = klassName::klass(); \
+ address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+ if (UseCompressedOops) { \
+ oop_store((narrowOop *)addr, x); \
+ } else { \
+ oop_store((oop*)addr, x); \
+ } \
+ }
+#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename) \
+ static int _##name##_offset; \
+ static jtypename name() { \
+ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+ InstanceKlass* ik = klassName::klass(); \
+ address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+ return *((jtypename *)addr); \
+ } \
+ static void set_##name(jtypename x) { \
+ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+ InstanceKlass* ik = klassName::klass(); \
+ address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+ *((jtypename *)addr) = x; \
+ }
+
+#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
+#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+
+COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+#undef START_CLASS
+#undef END_CLASS
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OOP_FIELD
+#undef TYPEARRAYOOP_FIELD
+#undef OBJARRAYOOP_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_OOP_FIELD
+#undef STATIC_OBJARRAYOOP_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field);
+
+#endif // SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+
+#include "precompiled.hpp"
+#include "asm/codeBuffer.hpp"
+#include "code/codeCache.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "prims/jvm.h"
+#include "runtime/biasedLocking.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/reflection.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/defaultStream.hpp"
+
+#if defined(_MSC_VER)
+#define strtoll _strtoi64
+#endif
+
+jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
+bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
+bool JVMCIRuntime::_well_known_classes_initialized = false;
+const char* JVMCIRuntime::_compiler = NULL;
+int JVMCIRuntime::_options_count = 0;
+SystemProperty** JVMCIRuntime::_options = NULL;
+bool JVMCIRuntime::_shutdown_called = false;
+
+static const char* OPTION_PREFIX = "jvmci.option.";
+static const size_t OPTION_PREFIX_LEN = strlen(OPTION_PREFIX);
+
+BasicType JVMCIRuntime::kindToBasicType(jchar ch) {
+ switch(ch) {
+ case 'z': return T_BOOLEAN;
+ case 'b': return T_BYTE;
+ case 's': return T_SHORT;
+ case 'c': return T_CHAR;
+ case 'i': return T_INT;
+ case 'f': return T_FLOAT;
+ case 'j': return T_LONG;
+ case 'd': return T_DOUBLE;
+ case 'a': return T_OBJECT;
+ case '-': return T_ILLEGAL;
+ default:
+ fatal(err_msg("unexpected Kind: %c", ch));
+ break;
+ }
+ return T_ILLEGAL;
+}
+
+// Simple helper to see if the caller of a runtime stub which
+// entered the VM has been deoptimized
+
+static bool caller_is_deopted() {
+ JavaThread* thread = JavaThread::current();
+ RegisterMap reg_map(thread, false);
+ frame runtime_frame = thread->last_frame();
+ frame caller_frame = runtime_frame.sender(®_map);
+ assert(caller_frame.is_compiled_frame(), "must be compiled");
+ return caller_frame.is_deoptimized_frame();
+}
+
+// Stress deoptimization
+static void deopt_caller() {
+ if ( !caller_is_deopted()) {
+ JavaThread* thread = JavaThread::current();
+ RegisterMap reg_map(thread, false);
+ frame runtime_frame = thread->last_frame();
+ frame caller_frame = runtime_frame.sender(®_map);
+ Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
+ assert(caller_is_deopted(), "Must be deoptimized");
+ }
+}
+
+JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass))
+ JRT_BLOCK;
+ assert(klass->is_klass(), "not a class");
+ instanceKlassHandle h(thread, klass);
+ h->check_valid_for_instantiation(true, CHECK);
+ // make sure klass is initialized
+ h->initialize(CHECK);
+ // allocate instance and return via TLS
+ oop obj = h->allocate_instance(CHECK);
+ thread->set_vm_result(obj);
+ JRT_BLOCK_END;
+
+ if (ReduceInitialCardMarks) {
+ new_store_pre_barrier(thread);
+ }
+JRT_END
+
+JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length))
+ JRT_BLOCK;
+ // Note: no handle for klass needed since they are not used
+ // anymore after new_objArray() and no GC can happen before.
+ // (This may have to change if this code changes!)
+ assert(array_klass->is_klass(), "not a class");
+ oop obj;
+ if (array_klass->oop_is_typeArray()) {
+ BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
+ obj = oopFactory::new_typeArray(elt_type, length, CHECK);
+ } else {
+ Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
+ obj = oopFactory::new_objArray(elem_klass, length, CHECK);
+ }
+ thread->set_vm_result(obj);
+ // This is pretty rare but this runtime patch is stressful to deoptimization
+ // if we deoptimize here so force a deopt to stress the path.
+ if (DeoptimizeALot) {
+ static int deopts = 0;
+ // Alternate between deoptimizing and raising an error (which will also cause a deopt)
+ if (deopts++ % 2 == 0) {
+ ResourceMark rm(THREAD);
+ THROW(vmSymbols::java_lang_OutOfMemoryError());
+ } else {
+ deopt_caller();
+ }
+ }
+ JRT_BLOCK_END;
+
+ if (ReduceInitialCardMarks) {
+ new_store_pre_barrier(thread);
+ }
+JRT_END
+
+void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) {
+ // After any safepoint, just before going back to compiled code,
+ // we inform the GC that we will be doing initializing writes to
+ // this object in the future without emitting card-marks, so
+ // GC may take any compensating steps.
+ // NOTE: Keep this code consistent with GraphKit::store_barrier.
+
+ oop new_obj = thread->vm_result();
+ if (new_obj == NULL) return;
+
+ assert(Universe::heap()->can_elide_tlab_store_barriers(),
+ "compiler must check this first");
+ // GC may decide to give back a safer copy of new_obj.
+ new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
+ thread->set_vm_result(new_obj);
+}
+
+JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
+ assert(klass->is_klass(), "not a class");
+ assert(rank >= 1, "rank must be nonzero");
+ oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
+ thread->set_vm_result(obj);
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length))
+ oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
+ thread->set_vm_result(obj);
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror))
+ instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(type_mirror));
+
+ if (klass == NULL) {
+ ResourceMark rm(THREAD);
+ THROW(vmSymbols::java_lang_InstantiationException());
+ }
+
+ // Create new instance (the receiver)
+ klass->check_valid_for_instantiation(false, CHECK);
+
+ // Make sure klass gets initialized
+ klass->initialize(CHECK);
+
+ oop obj = klass->allocate_instance(CHECK);
+ thread->set_vm_result(obj);
+JRT_END
+
+extern void vm_exit(int code);
+
+// Enter this method from compiled code handler below. This is where we transition
+// to VM mode. This is done as a helper routine so that the method called directly
+// from compiled code does not have to transition to VM. This allows the entry
+// method to see if the nmethod that we have just looked up a handler for has
+// been deoptimized while we were in the vm. This simplifies the assembly code
+// cpu directories.
+//
+// We are entering here from exception stub (via the entry method below)
+// If there is a compiled exception handler in this method, we will continue there;
+// otherwise we will unwind the stack and continue at the caller of top frame method
+// Note: we enter in Java using a special JRT wrapper. This wrapper allows us to
+// control the area where we can allow a safepoint. After we exit the safepoint area we can
+// check to see if the handler we are going to return is now in a nmethod that has
+// been deoptimized. If that is the case we return the deopt blob
+// unpack_with_exception entry instead. This makes life for the exception blob easier
+// because making that same check and diverting is painful from assembly language.
+JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm))
+ // Reset method handle flag.
+ thread->set_is_method_handle_return(false);
+
+ Handle exception(thread, ex);
+ nm = CodeCache::find_nmethod(pc);
+ assert(nm != NULL, "this is not a compiled method");
+ // Adjust the pc as needed/
+ if (nm->is_deopt_pc(pc)) {
+ RegisterMap map(thread, false);
+ frame exception_frame = thread->last_frame().sender(&map);
+ // if the frame isn't deopted then pc must not correspond to the caller of last_frame
+ assert(exception_frame.is_deoptimized_frame(), "must be deopted");
+ pc = exception_frame.pc();
+ }
+#ifdef ASSERT
+ assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
+ assert(exception->is_oop(), "just checking");
+ // Check that exception is a subclass of Throwable, otherwise we have a VerifyError
+ if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
+ if (ExitVMOnVerifyError) vm_exit(-1);
+ ShouldNotReachHere();
+ }
+#endif
+
+ // Check the stack guard pages and reenable them if necessary and there is
+ // enough space on the stack to do so. Use fast exceptions only if the guard
+ // pages are enabled.
+ bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+ if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
+
+ if (JvmtiExport::can_post_on_exceptions()) {
+ // To ensure correct notification of exception catches and throws
+ // we have to deoptimize here. If we attempted to notify the
+ // catches and throws during this exception lookup it's possible
+ // we could deoptimize on the way out of the VM and end back in
+ // the interpreter at the throw site. This would result in double
+ // notifications since the interpreter would also notify about
+ // these same catches and throws as it unwound the frame.
+
+ RegisterMap reg_map(thread);
+ frame stub_frame = thread->last_frame();
+ frame caller_frame = stub_frame.sender(®_map);
+
+ // We don't really want to deoptimize the nmethod itself since we
+ // can actually continue in the exception handler ourselves but I
+ // don't see an easy way to have the desired effect.
+ Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
+ assert(caller_is_deopted(), "Must be deoptimized");
+
+ return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+ }
+
+ // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions
+ if (guard_pages_enabled) {
+ address fast_continuation = nm->handler_for_exception_and_pc(exception, pc);
+ if (fast_continuation != NULL) {
+ // Set flag if return address is a method handle call site.
+ thread->set_is_method_handle_return(nm->is_method_handle_return(pc));
+ return fast_continuation;
+ }
+ }
+
+ // If the stack guard pages are enabled, check whether there is a handler in
+ // the current method. Otherwise (guard pages disabled), force an unwind and
+ // skip the exception cache update (i.e., just leave continuation==NULL).
+ address continuation = NULL;
+ if (guard_pages_enabled) {
+
+ // New exception handling mechanism can support inlined methods
+ // with exception handlers since the mappings are from PC to PC
+
+ // debugging support
+ // tracing
+ if (TraceExceptions) {
+ ttyLocker ttyl;
+ ResourceMark rm;
+ tty->print_cr("Exception <%s> (" INTPTR_FORMAT ") thrown in compiled method <%s> at PC " INTPTR_FORMAT " for thread " INTPTR_FORMAT "",
+ exception->print_value_string(), p2i((address)exception()), nm->method()->print_value_string(), p2i(pc), p2i(thread));
+ }
+ // for AbortVMOnException flag
+ NOT_PRODUCT(Exceptions::debug_check_abort(exception));
+
+ // Clear out the exception oop and pc since looking up an
+ // exception handler can cause class loading, which might throw an
+ // exception and those fields are expected to be clear during
+ // normal bytecode execution.
+ thread->clear_exception_oop_and_pc();
+
+ continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false);
+ // If an exception was thrown during exception dispatch, the exception oop may have changed
+ thread->set_exception_oop(exception());
+ thread->set_exception_pc(pc);
+
+ // the exception cache is used only by non-implicit exceptions
+ if (continuation != NULL && !SharedRuntime::deopt_blob()->contains(continuation)) {
+ nm->add_handler_for_exception_and_pc(exception, pc, continuation);
+ }
+ }
+
+ // Set flag if return address is a method handle call site.
+ thread->set_is_method_handle_return(nm->is_method_handle_return(pc));
+
+ if (TraceExceptions) {
+ ttyLocker ttyl;
+ ResourceMark rm;
+ tty->print_cr("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT " for exception thrown at PC " PTR_FORMAT,
+ p2i(thread), p2i(continuation), p2i(pc));
+ }
+
+ return continuation;
+JRT_END
+
+// Enter this method from compiled code only if there is a Java exception handler
+// in the method handling the exception.
+// We are entering here from exception stub. We don't do a normal VM transition here.
+// We do it in a helper. This is so we can check to see if the nmethod we have just
+// searched for an exception handler has been deoptimized in the meantime.
+address JVMCIRuntime::exception_handler_for_pc(JavaThread* thread) {
+ oop exception = thread->exception_oop();
+ address pc = thread->exception_pc();
+ // Still in Java mode
+ DEBUG_ONLY(ResetNoHandleMark rnhm);
+ nmethod* nm = NULL;
+ address continuation = NULL;
+ {
+ // Enter VM mode by calling the helper
+ ResetNoHandleMark rnhm;
+ continuation = exception_handler_for_pc_helper(thread, exception, pc, nm);
+ }
+ // Back in JAVA, use no oops DON'T safepoint
+
+ // Now check to see if the compiled method we were called from is now deoptimized.
+ // If so we must return to the deopt blob and deoptimize the nmethod
+ if (nm != NULL && caller_is_deopted()) {
+ continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+ }
+
+ assert(continuation != NULL, "no handler found");
+ return continuation;
+}
+
+JRT_ENTRY(void, JVMCIRuntime::create_null_exception(JavaThread* thread))
+ SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_NullPointerException());
+ thread->set_vm_result(PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::create_out_of_bounds_exception(JavaThread* thread, jint index))
+ char message[jintAsStringSize];
+ sprintf(message, "%d", index);
+ SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message);
+ thread->set_vm_result(PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+JRT_END
+
+JRT_ENTRY_NO_ASYNC(void, JVMCIRuntime::monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+ IF_TRACE_jvmci_3 {
+ char type[O_BUFLEN];
+ obj->klass()->name()->as_C_string(type, O_BUFLEN);
+ markOop mark = obj->mark();
+ TRACE_jvmci_3("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(mark), p2i(lock));
+ tty->flush();
+ }
+#ifdef ASSERT
+ if (PrintBiasedLockingStatistics) {
+ Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
+ }
+#endif
+ Handle h_obj(thread, obj);
+ assert(h_obj()->is_oop(), "must be NULL or an object");
+ if (UseBiasedLocking) {
+ // Retry fast entry if bias is revoked to avoid unnecessary inflation
+ ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
+ } else {
+ if (JVMCIUseFastLocking) {
+ // When using fast locking, the compiled code has already tried the fast case
+ ObjectSynchronizer::slow_enter(h_obj, lock, THREAD);
+ } else {
+ ObjectSynchronizer::fast_enter(h_obj, lock, false, THREAD);
+ }
+ }
+ TRACE_jvmci_3("%s: exiting locking slow with obj=" INTPTR_FORMAT, thread->name(), p2i(obj));
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+ assert(thread == JavaThread::current(), "threads must correspond");
+ assert(thread->last_Java_sp(), "last_Java_sp must be set");
+ // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
+ EXCEPTION_MARK;
+
+#ifdef DEBUG
+ if (!obj->is_oop()) {
+ ResetNoHandleMark rhm;
+ nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
+ if (method != NULL) {
+ tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), p2i(obj));
+ }
+ thread->print_stack_on(tty);
+ assert(false, "invalid lock object pointer dected");
+ }
+#endif
+
+ if (JVMCIUseFastLocking) {
+ // When using fast locking, the compiled code has already tried the fast case
+ ObjectSynchronizer::slow_exit(obj, lock, THREAD);
+ } else {
+ ObjectSynchronizer::fast_exit(obj, lock, THREAD);
+ }
+ IF_TRACE_jvmci_3 {
+ char type[O_BUFLEN];
+ obj->klass()->name()->as_C_string(type, O_BUFLEN);
+ TRACE_jvmci_3("%s: exited locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(obj->mark()), p2i(lock));
+ tty->flush();
+ }
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
+ bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING);
+ bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS);
+ bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE);
+ if (!string) {
+ if (!addr && obj->is_oop_or_null(true)) {
+ char buf[O_BUFLEN];
+ tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj));
+ } else {
+ tty->print(INTPTR_FORMAT, p2i(obj));
+ }
+ } else {
+ ResourceMark rm;
+ assert(obj != NULL && java_lang_String::is_instance(obj), "must be");
+ char *buf = java_lang_String::as_utf8_string(obj);
+ tty->print_raw(buf);
+ }
+ if (newline) {
+ tty->cr();
+ }
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
+ thread->satb_mark_queue().enqueue(obj);
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
+ thread->dirty_card_queue().enqueue(card_addr);
+JRT_END
+
+JRT_LEAF(jboolean, JVMCIRuntime::validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child))
+ bool ret = true;
+ if(!Universe::heap()->is_in_closed_subset(parent)) {
+ tty->print_cr("Parent Object " INTPTR_FORMAT " not in heap", p2i(parent));
+ parent->print();
+ ret=false;
+ }
+ if(!Universe::heap()->is_in_closed_subset(child)) {
+ tty->print_cr("Child Object " INTPTR_FORMAT " not in heap", p2i(child));
+ child->print();
+ ret=false;
+ }
+ return (jint)ret;
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::vm_error(JavaThread* thread, jlong where, jlong format, jlong value))
+ ResourceMark rm;
+ const char *error_msg = where == 0L ? "<internal JVMCI error>" : (char*) (address) where;
+ char *detail_msg = NULL;
+ if (format != 0L) {
+ const char* buf = (char*) (address) format;
+ size_t detail_msg_length = strlen(buf) * 2;
+ detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
+ jio_snprintf(detail_msg, detail_msg_length, buf, value);
+ }
+ report_vm_error(__FILE__, __LINE__, error_msg, detail_msg);
+JRT_END
+
+JRT_LEAF(oopDesc*, JVMCIRuntime::load_and_clear_exception(JavaThread* thread))
+ oop exception = thread->exception_oop();
+ assert(exception != NULL, "npe");
+ thread->set_exception_oop(NULL);
+ thread->set_exception_pc(0);
+ return exception;
+JRT_END
+
+PRAGMA_DIAG_PUSH
+PRAGMA_FORMAT_NONLITERAL_IGNORED
+JRT_LEAF(void, JVMCIRuntime::log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3))
+ ResourceMark rm;
+ assert(format != NULL && java_lang_String::is_instance(format), "must be");
+ char *buf = java_lang_String::as_utf8_string(format);
+ tty->print((const char*)buf, v1, v2, v3);
+JRT_END
+PRAGMA_DIAG_POP
+
+static void decipher(jlong v, bool ignoreZero) {
+ if (v != 0 || !ignoreZero) {
+ void* p = (void *)(address) v;
+ CodeBlob* cb = CodeCache::find_blob(p);
+ if (cb) {
+ if (cb->is_nmethod()) {
+ char buf[O_BUFLEN];
+ tty->print("%s [" INTPTR_FORMAT "+" JLONG_FORMAT "]", cb->as_nmethod_or_null()->method()->name_and_sig_as_C_string(buf, O_BUFLEN), p2i(cb->code_begin()), (jlong)((address)v - cb->code_begin()));
+ return;
+ }
+ cb->print_value_on(tty);
+ return;
+ }
+ if (Universe::heap()->is_in(p)) {
+ oop obj = oop(p);
+ obj->print_value_on(tty);
+ return;
+ }
+ tty->print(INTPTR_FORMAT " [long: " JLONG_FORMAT ", double %lf, char %c]",p2i((void *)v), (jlong)v, (jdouble)v, (char)v);
+ }
+}
+
+PRAGMA_DIAG_PUSH
+PRAGMA_FORMAT_NONLITERAL_IGNORED
+JRT_LEAF(void, JVMCIRuntime::vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3))
+ ResourceMark rm;
+ const char *buf = (const char*) (address) format;
+ if (vmError) {
+ if (buf != NULL) {
+ fatal(err_msg(buf, v1, v2, v3));
+ } else {
+ fatal("<anonymous error>");
+ }
+ } else if (buf != NULL) {
+ tty->print(buf, v1, v2, v3);
+ } else {
+ assert(v2 == 0, "v2 != 0");
+ assert(v3 == 0, "v3 != 0");
+ decipher(v1, false);
+ }
+JRT_END
+PRAGMA_DIAG_POP
+
+JRT_LEAF(void, JVMCIRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+ union {
+ jlong l;
+ jdouble d;
+ jfloat f;
+ } uu;
+ uu.l = value;
+ switch (typeChar) {
+ case 'z': tty->print(value == 0 ? "false" : "true"); break;
+ case 'b': tty->print("%d", (jbyte) value); break;
+ case 'c': tty->print("%c", (jchar) value); break;
+ case 's': tty->print("%d", (jshort) value); break;
+ case 'i': tty->print("%d", (jint) value); break;
+ case 'f': tty->print("%f", uu.f); break;
+ case 'j': tty->print(JLONG_FORMAT, value); break;
+ case 'd': tty->print("%lf", uu.d); break;
+ default: assert(false, "unknown typeChar"); break;
+ }
+ if (newline) {
+ tty->cr();
+ }
+JRT_END
+
+JRT_ENTRY(jint, JVMCIRuntime::identity_hash_code(JavaThread* thread, oopDesc* obj))
+ return (jint) obj->identity_hash();
+JRT_END
+
+JRT_ENTRY(jboolean, JVMCIRuntime::thread_is_interrupted(JavaThread* thread, oopDesc* receiver, jboolean clear_interrupted))
+ // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.
+ // This locking requires thread_in_vm which is why this method cannot be JRT_LEAF.
+ Handle receiverHandle(thread, receiver);
+ MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock);
+ JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
+ if (receiverThread == NULL) {
+ // The other thread may exit during this process, which is ok so return false.
+ return JNI_FALSE;
+ } else {
+ return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+ }
+JRT_END
+
+JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
+ deopt_caller();
+ return value;
+JRT_END
+
+// private static JVMCIRuntime JVMCI.initializeRuntime()
+JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+ if (!EnableJVMCI) {
+ THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+ }
+ JVMCIRuntime::initialize_HotSpotJVMCIRuntime(CHECK_NULL);
+ jobject ret = JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(CHECK_NULL);
+ return ret;
+JVM_END
+
+Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, const char* signature, JavaCallArguments* args, TRAPS) {
+ guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime");
+
+ TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_(Handle()));
+ KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, CHECK_(Handle()));
+ TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_(Handle()));
+ TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_(Handle()));
+ JavaValue result(T_OBJECT);
+ if (args == NULL) {
+ JavaCalls::call_static(&result, klass, runtime, sig, CHECK_(Handle()));
+ } else {
+ JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_(Handle()));
+ }
+ return Handle((oop)result.get_jobject());
+}
+
+static bool jvmci_options_file_exists() {
+ const char* home = Arguments::get_java_home();
+ size_t path_len = strlen(home) + strlen("/lib/jvmci/options") + 1;
+ char path[JVM_MAXPATHLEN];
+ char sep = os::file_separator()[0];
+ jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci%coptions", home, sep, sep, sep);
+ struct stat st;
+ return os::stat(path, &st) == 0;
+}
+
+void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
+ if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
+#ifdef ASSERT
+ // This should only be called in the context of the JVMCI class being initialized
+ TempNewSymbol name = SymbolTable::new_symbol("jdk/vm/ci/runtime/JVMCI", CHECK);
+ Klass* k = SystemDictionary::resolve_or_null(name, CHECK);
+ instanceKlassHandle klass = InstanceKlass::cast(k);
+ assert(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD),
+ "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
+#endif
+
+ bool parseOptionsFile = jvmci_options_file_exists();
+ if (_options != NULL || parseOptionsFile) {
+ JavaCallArguments args;
+ objArrayOop options;
+ if (_options != NULL) {
+ options = oopFactory::new_objArray(SystemDictionary::String_klass(), _options_count * 2, CHECK);
+ for (int i = 0; i < _options_count; i++) {
+ SystemProperty* prop = _options[i];
+ oop name = java_lang_String::create_oop_from_str(prop->key() + OPTION_PREFIX_LEN, CHECK);
+ oop value = java_lang_String::create_oop_from_str(prop->value(), CHECK);
+ options->obj_at_put(i * 2, name);
+ options->obj_at_put((i * 2) + 1, value);
+ }
+ } else {
+ options = NULL;
+ }
+ args.push_oop(options);
+ args.push_int(parseOptionsFile);
+ callStatic("jdk/vm/ci/options/OptionsParser",
+ "parseOptionsFromVM",
+ "([Ljava/lang/String;Z)Ljava/lang/Boolean;", &args, CHECK);
+ }
+
+ if (_compiler != NULL) {
+ JavaCallArguments args;
+ oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK);
+ args.push_oop(compiler);
+ callStatic("jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig",
+ "selectCompiler",
+ "(Ljava/lang/String;)Ljava/lang/Boolean;", &args, CHECK);
+ }
+
+ Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
+ "runtime",
+ "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
+ _HotSpotJVMCIRuntime_initialized = true;
+ _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result());
+ }
+}
+
+void JVMCIRuntime::initialize_JVMCI(TRAPS) {
+ if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
+ callStatic("jdk/vm/ci/runtime/JVMCI",
+ "getRuntime",
+ "()Ljdk/vm/ci/runtime/JVMCIRuntime;", NULL, CHECK);
+ }
+ assert(_HotSpotJVMCIRuntime_initialized == true, "what?");
+}
+
+void JVMCIRuntime::initialize_well_known_classes(TRAPS) {
+ if (JVMCIRuntime::_well_known_classes_initialized == false) {
+ SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
+ SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK);
+ JVMCIJavaClasses::compute_offsets();
+ JVMCIRuntime::_well_known_classes_initialized = true;
+ }
+}
+
+void JVMCIRuntime::metadata_do(void f(Metadata*)) {
+ // For simplicity, the existence of HotSpotJVMCIMetaAccessContext in
+ // the SystemDictionary well known classes should ensure the other
+ // classes have already been loaded, so make sure their order in the
+ // table enforces that.
+ assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) <
+ SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+ assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotConstantPool) <
+ SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+ assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl) <
+ SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+
+ if (HotSpotJVMCIMetaAccessContext::klass() == NULL ||
+ !HotSpotJVMCIMetaAccessContext::klass()->is_linked()) {
+ // Nothing could be registered yet
+ return;
+ }
+
+ // WeakReference<HotSpotJVMCIMetaAccessContext>[]
+ objArrayOop allContexts = HotSpotJVMCIMetaAccessContext::allContexts();
+ if (allContexts == NULL) {
+ return;
+ }
+
+ // These must be loaded at this point but the linking state doesn't matter.
+ assert(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass() != NULL, "must be loaded");
+ assert(SystemDictionary::HotSpotConstantPool_klass() != NULL, "must be loaded");
+ assert(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass() != NULL, "must be loaded");
+
+ for (int i = 0; i < allContexts->length(); i++) {
+ oop ref = allContexts->obj_at(i);
+ if (ref != NULL) {
+ oop referent = java_lang_ref_Reference::referent(ref);
+ if (referent != NULL) {
+ // Chunked Object[] with last element pointing to next chunk
+ objArrayOop metadataRoots = HotSpotJVMCIMetaAccessContext::metadataRoots(referent);
+ while (metadataRoots != NULL) {
+ for (int typeIndex = 0; typeIndex < metadataRoots->length() - 1; typeIndex++) {
+ oop reference = metadataRoots->obj_at(typeIndex);
+ if (reference == NULL) {
+ continue;
+ }
+ oop metadataRoot = java_lang_ref_Reference::referent(reference);
+ if (metadataRoot == NULL) {
+ continue;
+ }
+ if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+ Method* method = CompilerToVM::asMethod(metadataRoot);
+ f(method);
+ } else if (metadataRoot->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
+ ConstantPool* constantPool = CompilerToVM::asConstantPool(metadataRoot);
+ f(constantPool);
+ } else if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+ Klass* klass = CompilerToVM::asKlass(metadataRoot);
+ f(klass);
+ } else {
+ metadataRoot->print();
+ ShouldNotReachHere();
+ }
+ }
+ metadataRoots = (objArrayOop)metadataRoots->obj_at(metadataRoots->length() - 1);
+ assert(metadataRoots == NULL || metadataRoots->is_objArray(), "wrong type");
+ }
+ }
+ }
+ }
+}
+
+// private static void CompilerToVM.registerNatives()
+JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
+ if (!EnableJVMCI) {
+ THROW_MSG(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled");
+ }
+
+#ifdef _LP64
+ uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
+ uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
+ guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+#else
+ fatal("check TLAB allocation code for address space conflicts");
+#endif
+
+ JVMCIRuntime::initialize_well_known_classes(CHECK);
+
+ {
+ ThreadToNativeFromVM trans(thread);
+
+ // Ensure _non_oop_bits is initialized
+ Universe::non_oop_word();
+
+ env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count());
+ }
+JVM_END
+
+/**
+ * Closure for parsing a line from a *.properties file in jre/lib/jvmci/properties.
+ * The line must match the regular expression "[^=]+=.*". That is one or more
+ * characters other than '=' followed by '=' followed by zero or more characters.
+ * Everything before the '=' is the property name and everything after '=' is the value.
+ * Lines that start with '#' are treated as comments and ignored.
+ * No special processing of whitespace or any escape characters is performed.
+ * The last definition of a property "wins" (i.e., it overrides all earlier
+ * definitions of the property).
+ */
+class JVMCIPropertiesFileClosure : public ParseClosure {
+ SystemProperty** _plist;
+public:
+ JVMCIPropertiesFileClosure(SystemProperty** plist) : _plist(plist) {}
+ void do_line(char* line) {
+ if (line[0] == '#') {
+ // skip comment
+ return;
+ }
+ size_t len = strlen(line);
+ char* sep = strchr(line, '=');
+ if (sep == NULL) {
+ warn_and_abort("invalid format: could not find '=' character");
+ return;
+ }
+ if (sep == line) {
+ warn_and_abort("invalid format: name cannot be empty");
+ return;
+ }
+ *sep = '\0';
+ const char* name = line;
+ char* value = sep + 1;
+ Arguments::PropertyList_unique_add(_plist, name, value);
+ }
+};
+
+void JVMCIRuntime::init_system_properties(SystemProperty** plist) {
+ char jvmciDir[JVM_MAXPATHLEN];
+ const char* fileSep = os::file_separator();
+ jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci",
+ Arguments::get_java_home(), fileSep, fileSep, fileSep);
+ DIR* dir = os::opendir(jvmciDir);
+ if (dir != NULL) {
+ struct dirent *entry;
+ char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal);
+ JVMCIPropertiesFileClosure closure(plist);
+ const unsigned suffix_len = (unsigned)strlen(".properties");
+ while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) {
+ const char* name = entry->d_name;
+ if (strlen(name) > suffix_len && strcmp(name + strlen(name) - suffix_len, ".properties") == 0) {
+ char propertiesFilePath[JVM_MAXPATHLEN];
+ jio_snprintf(propertiesFilePath, sizeof(propertiesFilePath), "%s%s%s",jvmciDir, fileSep, name);
+ JVMCIRuntime::parse_lines(propertiesFilePath, &closure, false);
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, dbuf);
+ os::closedir(dir);
+ }
+}
+
+#define CHECK_WARN_ABORT_(message) THREAD); \
+ if (HAS_PENDING_EXCEPTION) { \
+ warning(message); \
+ char buf[512]; \
+ jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+ JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+ return; \
+ } \
+ (void)(0
+
+void JVMCIRuntime::save_compiler(const char* compiler) {
+ assert(compiler != NULL, "npe");
+ assert(_compiler == NULL, "cannot reassign JVMCI compiler");
+ _compiler = compiler;
+}
+
+jint JVMCIRuntime::save_options(SystemProperty* props) {
+ int count = 0;
+ SystemProperty* first = NULL;
+ for (SystemProperty* p = props; p != NULL; p = p->next()) {
+ if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) {
+ if (p->value() == NULL || strlen(p->value()) == 0) {
+ jio_fprintf(defaultStream::output_stream(), "JVMCI option %s must have non-zero length value\n", p->key());
+ return JNI_ERR;
+ }
+ if (first == NULL) {
+ first = p;
+ }
+ count++;
+ }
+ }
+ if (count != 0) {
+ _options_count = count;
+ _options = NEW_C_HEAP_ARRAY(SystemProperty*, count, mtCompiler);
+ _options[0] = first;
+ SystemProperty** insert_pos = _options + 1;
+ for (SystemProperty* p = first->next(); p != NULL; p = p->next()) {
+ if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) {
+ *insert_pos = p;
+ insert_pos++;
+ }
+ }
+ assert (insert_pos - _options == count, "must be");
+ }
+ return JNI_OK;
+}
+
+void JVMCIRuntime::shutdown() {
+ if (_HotSpotJVMCIRuntime_instance != NULL) {
+ _shutdown_called = true;
+ JavaThread* THREAD = JavaThread::current();
+ HandleMark hm(THREAD);
+ Handle receiver = get_HotSpotJVMCIRuntime(CHECK_ABORT);
+ JavaValue result(T_VOID);
+ JavaCallArguments args;
+ args.push_oop(receiver);
+ JavaCalls::call_special(&result, receiver->klass(), vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, CHECK_ABORT);
+ }
+}
+
+void JVMCIRuntime::call_printStackTrace(Handle exception, Thread* thread) {
+ assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected");
+ JavaValue result(T_VOID);
+ JavaCalls::call_virtual(&result,
+ exception,
+ KlassHandle(thread,
+ SystemDictionary::Throwable_klass()),
+ vmSymbols::printStackTrace_name(),
+ vmSymbols::void_method_signature(),
+ thread);
+}
+
+void JVMCIRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) {
+ Thread* THREAD = Thread::current();
+ CLEAR_PENDING_EXCEPTION;
+ tty->print_raw_cr(message);
+ call_printStackTrace(exception, THREAD);
+
+ // Give other aborting threads to also print their stack traces.
+ // This can be very useful when debugging class initialization
+ // failures.
+ os::sleep(THREAD, 200, false);
+
+ vm_abort(dump_core);
+}
+
+void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) {
+ struct stat st;
+ if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
+ int file_handle = os::open(path, 0, 0);
+ if (file_handle != -1) {
+ char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal);
+ int num_read;
+ num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
+ if (num_read == -1) {
+ warning("Error reading file %s due to %s", path, strerror(errno));
+ } else if (num_read != st.st_size) {
+ warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
+ }
+ os::close(file_handle);
+ closure->set_filename(path);
+ if (num_read == st.st_size) {
+ buffer[num_read] = '\0';
+
+ char* line = buffer;
+ while (line - buffer < num_read && !closure->is_aborted()) {
+ // find line end (\r, \n or \r\n)
+ char* nextline = NULL;
+ char* cr = strchr(line, '\r');
+ char* lf = strchr(line, '\n');
+ if (cr != NULL && lf != NULL) {
+ char* min = MIN2(cr, lf);
+ *min = '\0';
+ if (lf == cr + 1) {
+ nextline = lf + 1;
+ } else {
+ nextline = min + 1;
+ }
+ } else if (cr != NULL) {
+ *cr = '\0';
+ nextline = cr + 1;
+ } else if (lf != NULL) {
+ *lf = '\0';
+ nextline = lf + 1;
+ }
+ // trim left
+ while (*line == ' ' || *line == '\t') line++;
+ char* end = line + strlen(line);
+ // trim right
+ while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--;
+ *end = '\0';
+ // skip comments and empty lines
+ if (*line != '#' && strlen(line) > 0) {
+ closure->parse_line(line);
+ }
+ if (nextline != NULL) {
+ line = nextline;
+ } else {
+ // File without newline at the end
+ break;
+ }
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, buffer);
+ } else {
+ warning("Error opening file %s due to %s", path, strerror(errno));
+ }
+ } else if (warnStatFailure) {
+ warning("Could not stat file %s due to %s", path, strerror(errno));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
+#define SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
+
+#include "interpreter/interpreter.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/deoptimization.hpp"
+
+class ParseClosure : public StackObj {
+ int _lineNo;
+ char* _filename;
+ bool _abort;
+protected:
+ void abort() { _abort = true; }
+ void warn_and_abort(const char* message) {
+ warn(message);
+ abort();
+ }
+ void warn(const char* message) {
+ warning("Error at line %d while parsing %s: %s", _lineNo, _filename == NULL ? "?" : _filename, message);
+ }
+ public:
+ ParseClosure() : _lineNo(0), _filename(NULL), _abort(false) {}
+ void parse_line(char* line) {
+ _lineNo++;
+ do_line(line);
+ }
+ virtual void do_line(char* line) = 0;
+ int lineNo() { return _lineNo; }
+ bool is_aborted() { return _abort; }
+ void set_filename(char* path) {_filename = path; _lineNo = 0;}
+};
+
+#define CHECK_ABORT THREAD); \
+ if (HAS_PENDING_EXCEPTION) { \
+ char buf[256]; \
+ jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+ JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+ return; \
+ } \
+ (void)(0
+
+#define CHECK_ABORT_(result) THREAD); \
+ if (HAS_PENDING_EXCEPTION) { \
+ char buf[256]; \
+ jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+ JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+ return result; \
+ } \
+ (void)(0
+
+class JVMCIRuntime: public AllStatic {
+ private:
+ static jobject _HotSpotJVMCIRuntime_instance;
+ static bool _HotSpotJVMCIRuntime_initialized;
+ static bool _well_known_classes_initialized;
+ static const char* _compiler;
+ static int _options_count;
+ static SystemProperty** _options;
+
+ static bool _shutdown_called;
+
+ /**
+ * Instantiates a service object, calls its default constructor and returns it.
+ *
+ * @param name the name of a class implementing jdk.vm.ci.service.Service
+ */
+ static Handle create_Service(const char* name, TRAPS);
+
+ public:
+
+ /**
+ * Parses *.properties files in jre/lib/jvmci/ and adds the properties to plist.
+ */
+ static void init_system_properties(SystemProperty** plist);
+
+ /**
+ * Saves the value of the "jvmci.compiler" system property for processing
+ * when JVMCI is initialized.
+ */
+ static void save_compiler(const char* compiler);
+
+ /**
+ * Saves the value of the system properties starting with "jvmci.option." for processing
+ * when JVMCI is initialized.
+ *
+ * @param props the head of the system property list
+ * @return JNI_ERR if a JVMCI option has a zero length value, JNI_OK otherwise
+ */
+ static jint save_options(SystemProperty* props);
+
+ static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; }
+
+ /**
+ * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
+ */
+ static Handle get_HotSpotJVMCIRuntime(TRAPS) {
+ initialize_JVMCI(CHECK_(Handle()));
+ return Handle(JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance));
+ }
+
+ static jobject get_HotSpotJVMCIRuntime_jobject(TRAPS) {
+ initialize_JVMCI(CHECK_NULL);
+ assert(_HotSpotJVMCIRuntime_initialized, "must be");
+ return _HotSpotJVMCIRuntime_instance;
+ }
+
+ static Handle callStatic(const char* className, const char* methodName, const char* returnType, JavaCallArguments* args, TRAPS);
+
+ /**
+ * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
+ */
+ static void initialize_JVMCI(TRAPS);
+
+ /**
+ * Explicitly initialize HotSpotJVMCIRuntime itself
+ */
+ static void initialize_HotSpotJVMCIRuntime(TRAPS);
+
+ static void initialize_well_known_classes(TRAPS);
+
+ static void metadata_do(void f(Metadata*));
+
+ static void shutdown();
+
+ static bool shutdown_called() {
+ return _shutdown_called;
+ }
+
+ static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure);
+
+ /**
+ * Aborts the VM due to an unexpected exception.
+ */
+ static void abort_on_pending_exception(Handle exception, const char* message, bool dump_core = false);
+
+ /**
+ * Calls Throwable.printStackTrace() on a given exception.
+ */
+ static void call_printStackTrace(Handle exception, Thread* thread);
+
+ static BasicType kindToBasicType(jchar ch);
+
+ // The following routines are all called from compiled JVMCI code
+
+ static void new_instance(JavaThread* thread, Klass* klass);
+ static void new_array(JavaThread* thread, Klass* klass, jint length);
+ static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims);
+ static void dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length);
+ static void dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror);
+ static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupted);
+ static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
+ static jint identity_hash_code(JavaThread* thread, oopDesc* obj);
+ static address exception_handler_for_pc(JavaThread* thread);
+ static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
+ static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+ static void create_null_exception(JavaThread* thread);
+ static void create_out_of_bounds_exception(JavaThread* thread, jint index);
+ static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
+ static oopDesc* load_and_clear_exception(JavaThread* thread);
+ static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
+ static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+ // Note: Must be kept in sync with constants in com.oracle.graal.replacements.Log
+ enum {
+ LOG_OBJECT_NEWLINE = 0x01,
+ LOG_OBJECT_STRING = 0x02,
+ LOG_OBJECT_ADDRESS = 0x04
+ };
+ static void log_object(JavaThread* thread, oopDesc* msg, jint flags);
+ static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
+ static void write_barrier_post(JavaThread* thread, void* card);
+ static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
+ static void new_store_pre_barrier(JavaThread* thread);
+
+ // Test only function
+ static int test_deoptimize_call_int(JavaThread* thread, int value);
+};
+
+// Tracing macros.
+
+#define IF_TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1)) ; else
+#define IF_TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2)) ; else
+#define IF_TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3)) ; else
+#define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else
+#define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else
+
+#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print("JVMCITrace-1: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print(" JVMCITrace-2: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print(" JVMCITrace-3: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print(" JVMCITrace-4: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print(" JVMCITrace-5: "), true))) ; else tty->print_cr
+
+#endif // SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2000, 2015, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/jvmci_globals.hpp"
+
+JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+ MATERIALIZE_PD_DEVELOPER_FLAG, \
+ MATERIALIZE_PRODUCT_FLAG, \
+ MATERIALIZE_PD_PRODUCT_FLAG, \
+ MATERIALIZE_DIAGNOSTIC_FLAG, \
+ MATERIALIZE_EXPERIMENTAL_FLAG, \
+ MATERIALIZE_NOTPRODUCT_FLAG,
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2000, 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCIGLOBALS_HPP
+#define SHARE_VM_JVMCI_JVMCIGLOBALS_HPP
+
+#include "runtime/globals.hpp"
+
+//
+// Defines all global flags used by the JVMCI compiler. Only flags that need
+// to be accessible to the JVMCI C++ code should be defined here. All other
+// JVMCI flags should be defined in JVMCIOptions.java.
+//
+#define JVMCI_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, range, constraint) \
+ \
+ experimental(bool, EnableJVMCI, false, \
+ "Enable JVMCI") \
+ \
+ experimental(bool, UseJVMCICompiler, false, \
+ "Use JVMCI as the default compiler") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(bool, BootstrapJVMCI, false, \
+ "Bootstrap JVMCI before running Java main method") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(bool, PrintBootstrap, true, \
+ "Print JVMCI bootstrap progress and summary") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(intx, JVMCIThreads, 1, \
+ "Force number of JVMCI compiler threads to use") \
+ range(1, max_jint) \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(intx, JVMCIHostThreads, 1, \
+ "Force number of compiler threads for JVMCI host compiler") \
+ range(1, max_jint) \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(bool, CodeInstallSafepointChecks, true, \
+ "Perform explicit safepoint checks while installing code") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ NOT_COMPILER2(product(intx, MaxVectorSize, 64, \
+ "Max vector size in bytes, " \
+ "actual size could be less depending on elements type")) \
+ \
+ NOT_COMPILER2(product(bool, ReduceInitialCardMarks, true, \
+ "Defer write barriers of young objects")) \
+ \
+ experimental(intx, JVMCITraceLevel, 0, \
+ "Trace level for JVMCI: " \
+ "1 means emit a message for each CompilerToVM call," \
+ "levels greater than 1 provide progressively greater detail") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(intx, JVMCICounterSize, 0, \
+ "Reserved size for benchmark counters") \
+ range(0, max_jint) \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(bool, JVMCICountersExcludeCompiler, true, \
+ "Exclude JVMCI compiler threads from benchmark counters") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ develop(bool, JVMCIUseFastLocking, true, \
+ "Use fast inlined locking code") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \
+ "Maximum size of a compiled method.") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ \
+ develop(bool, TraceUncollectedSpeculations, false, \
+ "Print message when a failed speculation was not collected") \
+ constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+
+
+// Read default values for JVMCI globals
+
+JVMCI_FLAGS(DECLARE_DEVELOPER_FLAG, \
+ DECLARE_PD_DEVELOPER_FLAG, \
+ DECLARE_PRODUCT_FLAG, \
+ DECLARE_PD_PRODUCT_FLAG, \
+ DECLARE_DIAGNOSTIC_FLAG, \
+ DECLARE_EXPERIMENTAL_FLAG, \
+ DECLARE_NOTPRODUCT_FLAG, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+
+#endif // SHARE_VM_JVMCI_JVMCIGLOBALS_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
+#define SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
+
+#if !INCLUDE_JVMCI
+#define JVMCI_WK_KLASSES_DO(do_klass)
+#else
+#define JVMCI_WK_KLASSES_DO(do_klass) \
+ /* JVMCI classes. These are loaded on-demand. */ \
+ do_klass(HotSpotCompiledCode_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode, Jvmci) \
+ do_klass(HotSpotCompiledCode_Comment_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment, Jvmci) \
+ do_klass(HotSpotCompiledNmethod_klass, jdk_vm_ci_hotspot_HotSpotCompiledNmethod, Jvmci) \
+ do_klass(HotSpotForeignCallTarget_klass, jdk_vm_ci_hotspot_HotSpotForeignCallTarget, Jvmci) \
+ do_klass(HotSpotReferenceMap_klass, jdk_vm_ci_hotspot_HotSpotReferenceMap, Jvmci) \
+ do_klass(HotSpotInstalledCode_klass, jdk_vm_ci_hotspot_HotSpotInstalledCode, Jvmci) \
+ do_klass(HotSpotNmethod_klass, jdk_vm_ci_hotspot_HotSpotNmethod, Jvmci) \
+ do_klass(HotSpotResolvedJavaMethodImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, Jvmci) \
+ do_klass(HotSpotResolvedObjectTypeImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, Jvmci) \
+ do_klass(HotSpotCompressedNullConstant_klass, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, Jvmci) \
+ do_klass(HotSpotObjectConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl, Jvmci) \
+ do_klass(HotSpotMetaspaceConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl, Jvmci) \
+ do_klass(HotSpotSentinelConstant_klass, jdk_vm_ci_hotspot_HotSpotSentinelConstant, Jvmci) \
+ do_klass(HotSpotStackFrameReference_klass, jdk_vm_ci_hotspot_HotSpotStackFrameReference, Jvmci) \
+ do_klass(HotSpotMetaData_klass, jdk_vm_ci_hotspot_HotSpotMetaData, Jvmci) \
+ do_klass(HotSpotOopMap_klass, jdk_vm_ci_hotspot_HotSpotOopMap, Jvmci) \
+ do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool, Jvmci) \
+ do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, Jvmci) \
+ do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod, Jvmci) \
+ do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, Jvmci) \
+ do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype, Jvmci) \
+ do_klass(Assumptions_LeafType_klass, jdk_vm_ci_meta_Assumptions_LeafType, Jvmci) \
+ do_klass(Assumptions_CallSiteTargetValue_klass, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue, Jvmci) \
+ do_klass(Architecture_klass, jdk_vm_ci_code_Architecture, Jvmci) \
+ do_klass(TargetDescription_klass, jdk_vm_ci_code_TargetDescription, Jvmci) \
+ do_klass(BytecodePosition_klass, jdk_vm_ci_code_BytecodePosition, Jvmci) \
+ do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo, Jvmci) \
+ do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout, Jvmci) \
+ do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame, Jvmci) \
+ do_klass(CompilationResult_Call_klass, jdk_vm_ci_code_CompilationResult_Call, Jvmci) \
+ do_klass(CompilationResult_ConstantReference_klass, jdk_vm_ci_code_CompilationResult_ConstantReference, Jvmci) \
+ do_klass(CompilationResult_DataPatch_klass, jdk_vm_ci_code_CompilationResult_DataPatch, Jvmci) \
+ do_klass(CompilationResult_DataSectionReference_klass, jdk_vm_ci_code_CompilationResult_DataSectionReference, Jvmci) \
+ do_klass(CompilationResult_ExceptionHandler_klass, jdk_vm_ci_code_CompilationResult_ExceptionHandler, Jvmci) \
+ do_klass(CompilationResult_Mark_klass, jdk_vm_ci_code_CompilationResult_Mark, Jvmci) \
+ do_klass(CompilationResult_Infopoint_klass, jdk_vm_ci_code_CompilationResult_Infopoint, Jvmci) \
+ do_klass(CompilationResult_Site_klass, jdk_vm_ci_code_CompilationResult_Site, Jvmci) \
+ do_klass(InfopointReason_klass, jdk_vm_ci_code_InfopointReason, Jvmci) \
+ do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode, Jvmci) \
+ do_klass(code_Location_klass, jdk_vm_ci_code_Location, Jvmci) \
+ do_klass(code_Register_klass, jdk_vm_ci_code_Register, Jvmci) \
+ do_klass(RegisterValue_klass, jdk_vm_ci_code_RegisterValue, Jvmci) \
+ do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot, Jvmci) \
+ do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue, Jvmci) \
+ do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject, Jvmci) \
+ do_klass(SpeculationLog_klass, jdk_vm_ci_meta_SpeculationLog, Jvmci) \
+ do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant, Jvmci) \
+ do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant, Jvmci) \
+ do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant, Jvmci) \
+ do_klass(NullConstant_klass, jdk_vm_ci_meta_NullConstant, Jvmci) \
+ do_klass(ExceptionHandler_klass, jdk_vm_ci_meta_ExceptionHandler, Jvmci) \
+ do_klass(JavaKind_klass, jdk_vm_ci_meta_JavaKind, Jvmci) \
+ do_klass(LIRKind_klass, jdk_vm_ci_meta_LIRKind, Jvmci) \
+ do_klass(Value_klass, jdk_vm_ci_meta_Value, Jvmci)
+#endif
+
+#endif // SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
+#define SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
+
+#include "compiler/abstractCompiler.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+
+#define VM_STRUCTS_JVMCI(nonstatic_field, static_field) \
+ nonstatic_field(JavaThread, _pending_deoptimization, int) \
+ nonstatic_field(JavaThread, _pending_failed_speculation, oop) \
+ nonstatic_field(JavaThread, _pending_transfer_to_interpreter, bool) \
+ nonstatic_field(JavaThread, _jvmci_counters, jlong*) \
+ nonstatic_field(MethodData, _jvmci_ir_size, int) \
+ nonstatic_field(JVMCIEnv, _task, CompileTask*) \
+ nonstatic_field(JVMCIEnv, _jvmti_can_hotswap_or_post_breakpoint, bool) \
+ nonstatic_field(DeoptimizationBlob, _uncommon_trap_offset, int) \
+ \
+ static_field(CompilerToVM, _supports_inline_contig_alloc, bool) \
+ static_field(CompilerToVM, _heap_end_addr, HeapWord**) \
+ static_field(CompilerToVM, _heap_top_addr, HeapWord**)
+
+#define VM_TYPES_JVMCI(declare_type, declare_toplevel_type) \
+ declare_toplevel_type(CompilerToVM) \
+ declare_toplevel_type(JVMCIEnv) \
+
+#define VM_INT_CONSTANTS_JVMCI(declare_constant, declare_preprocessor_constant) \
+ declare_constant(Deoptimization::Reason_unreached0) \
+ declare_constant(Deoptimization::Reason_type_checked_inlining) \
+ declare_constant(Deoptimization::Reason_optimized_type_check) \
+ declare_constant(Deoptimization::Reason_aliasing) \
+ declare_constant(Deoptimization::Reason_transfer_to_interpreter) \
+ declare_constant(Deoptimization::Reason_not_compiled_exception_handler) \
+ declare_constant(Deoptimization::Reason_unresolved) \
+ declare_constant(Deoptimization::Reason_jsr_mismatch) \
+ declare_constant(JVMCIEnv::ok) \
+ declare_constant(JVMCIEnv::dependencies_failed) \
+ declare_constant(JVMCIEnv::dependencies_invalid) \
+ declare_constant(JVMCIEnv::cache_full) \
+ declare_constant(JVMCIEnv::code_too_large) \
+ \
+ declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \
+ declare_preprocessor_constant("JVM_RECOGNIZED_FIELD_MODIFIERS", JVM_RECOGNIZED_FIELD_MODIFIERS) \
+ \
+ declare_constant(CompilerToVM::KLASS_TAG) \
+ declare_constant(CompilerToVM::SYMBOL_TAG) \
+ \
+ declare_constant(CodeInstaller::VERIFIED_ENTRY) \
+ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \
+ declare_constant(CodeInstaller::OSR_ENTRY) \
+ declare_constant(CodeInstaller::EXCEPTION_HANDLER_ENTRY) \
+ declare_constant(CodeInstaller::DEOPT_HANDLER_ENTRY) \
+ declare_constant(CodeInstaller::INVOKEINTERFACE) \
+ declare_constant(CodeInstaller::INVOKEVIRTUAL) \
+ declare_constant(CodeInstaller::INVOKESTATIC) \
+ declare_constant(CodeInstaller::INVOKESPECIAL) \
+ declare_constant(CodeInstaller::INLINE_INVOKE) \
+ declare_constant(CodeInstaller::POLL_NEAR) \
+ declare_constant(CodeInstaller::POLL_RETURN_NEAR) \
+ declare_constant(CodeInstaller::POLL_FAR) \
+ declare_constant(CodeInstaller::POLL_RETURN_FAR) \
+ declare_constant(CodeInstaller::CARD_TABLE_ADDRESS) \
+ declare_constant(CodeInstaller::HEAP_TOP_ADDRESS) \
+ declare_constant(CodeInstaller::HEAP_END_ADDRESS) \
+ declare_constant(CodeInstaller::NARROW_KLASS_BASE_ADDRESS) \
+ declare_constant(CodeInstaller::CRC_TABLE_ADDRESS) \
+ declare_constant(CodeInstaller::INVOKE_INVALID) \
+ \
+ declare_constant(Method::invalid_vtable_index) \
+
+#define VM_ADDRESSES_JVMCI(declare_address, declare_preprocessor_address, declare_function) \
+ declare_function(JVMCIRuntime::new_instance) \
+ declare_function(JVMCIRuntime::new_array) \
+ declare_function(JVMCIRuntime::new_multi_array) \
+ declare_function(JVMCIRuntime::dynamic_new_array) \
+ declare_function(JVMCIRuntime::dynamic_new_instance) \
+ \
+ declare_function(JVMCIRuntime::thread_is_interrupted) \
+ declare_function(JVMCIRuntime::vm_message) \
+ declare_function(JVMCIRuntime::identity_hash_code) \
+ declare_function(JVMCIRuntime::exception_handler_for_pc) \
+ declare_function(JVMCIRuntime::monitorenter) \
+ declare_function(JVMCIRuntime::monitorexit) \
+ declare_function(JVMCIRuntime::create_null_exception) \
+ declare_function(JVMCIRuntime::create_out_of_bounds_exception) \
+ declare_function(JVMCIRuntime::log_primitive) \
+ declare_function(JVMCIRuntime::log_object) \
+ declare_function(JVMCIRuntime::log_printf) \
+ declare_function(JVMCIRuntime::vm_error) \
+ declare_function(JVMCIRuntime::load_and_clear_exception) \
+ declare_function(JVMCIRuntime::write_barrier_pre) \
+ declare_function(JVMCIRuntime::write_barrier_post) \
+ declare_function(JVMCIRuntime::validate_object) \
+ \
+ declare_function(JVMCIRuntime::test_deoptimize_call_int)
+
+#endif // SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
+#define SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
+
+
+#if !INCLUDE_JVMCI
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias)
+#else
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias) \
+ template(jdk_vm_ci_hotspot_HotSpotCompiledCode, "jdk/vm/ci/hotspot/HotSpotCompiledCode") \
+ template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment, "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment") \
+ template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod, "jdk/vm/ci/hotspot/HotSpotCompiledNmethod") \
+ template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget, "jdk/vm/ci/hotspot/HotSpotForeignCallTarget") \
+ template(jdk_vm_ci_hotspot_HotSpotReferenceMap, "jdk/vm/ci/hotspot/HotSpotReferenceMap") \
+ template(jdk_vm_ci_hotspot_CompilerToVM, "jdk/vm/ci/hotspot/CompilerToVM") \
+ template(jdk_vm_ci_hotspot_HotSpotInstalledCode, "jdk/vm/ci/hotspot/HotSpotInstalledCode") \
+ template(jdk_vm_ci_hotspot_HotSpotNmethod, "jdk/vm/ci/hotspot/HotSpotNmethod") \
+ template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl") \
+ template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl") \
+ template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant") \
+ template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl, "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl") \
+ template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl, "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl") \
+ template(jdk_vm_ci_hotspot_HotSpotSentinelConstant, "jdk/vm/ci/hotspot/HotSpotSentinelConstant") \
+ template(jdk_vm_ci_hotspot_HotSpotStackFrameReference, "jdk/vm/ci/hotspot/HotSpotStackFrameReference") \
+ template(jdk_vm_ci_hotspot_HotSpotMetaData, "jdk/vm/ci/hotspot/HotSpotMetaData") \
+ template(jdk_vm_ci_hotspot_HotSpotOopMap, "jdk/vm/ci/hotspot/HotSpotOopMap") \
+ template(jdk_vm_ci_hotspot_HotSpotConstantPool, "jdk/vm/ci/hotspot/HotSpotConstantPool") \
+ template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext") \
+ template(jdk_vm_ci_meta_JavaConstant, "jdk/vm/ci/meta/JavaConstant") \
+ template(jdk_vm_ci_meta_PrimitiveConstant, "jdk/vm/ci/meta/PrimitiveConstant") \
+ template(jdk_vm_ci_meta_RawConstant, "jdk/vm/ci/meta/RawConstant") \
+ template(jdk_vm_ci_meta_NullConstant, "jdk/vm/ci/meta/NullConstant") \
+ template(jdk_vm_ci_meta_ExceptionHandler, "jdk/vm/ci/meta/ExceptionHandler") \
+ template(jdk_vm_ci_meta_JavaKind, "jdk/vm/ci/meta/JavaKind") \
+ template(jdk_vm_ci_meta_LIRKind, "jdk/vm/ci/meta/LIRKind") \
+ template(jdk_vm_ci_meta_Value, "jdk/vm/ci/meta/Value") \
+ template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype, "jdk/vm/ci/meta/Assumptions$ConcreteSubtype") \
+ template(jdk_vm_ci_meta_Assumptions_LeafType, "jdk/vm/ci/meta/Assumptions$LeafType") \
+ template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass") \
+ template(jdk_vm_ci_meta_Assumptions_ConcreteMethod, "jdk/vm/ci/meta/Assumptions$ConcreteMethod") \
+ template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue, "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue") \
+ template(jdk_vm_ci_meta_SpeculationLog, "jdk/vm/ci/meta/SpeculationLog") \
+ template(jdk_vm_ci_code_Architecture, "jdk/vm/ci/code/Architecture") \
+ template(jdk_vm_ci_code_TargetDescription, "jdk/vm/ci/code/TargetDescription") \
+ template(jdk_vm_ci_code_CompilationResult_Call, "jdk/vm/ci/code/CompilationResult$Call") \
+ template(jdk_vm_ci_code_CompilationResult_ConstantReference, "jdk/vm/ci/code/CompilationResult$ConstantReference") \
+ template(jdk_vm_ci_code_CompilationResult_DataPatch, "jdk/vm/ci/code/CompilationResult$DataPatch") \
+ template(jdk_vm_ci_code_CompilationResult_DataSectionReference, "jdk/vm/ci/code/CompilationResult$DataSectionReference") \
+ template(jdk_vm_ci_code_CompilationResult_ExceptionHandler, "jdk/vm/ci/code/CompilationResult$ExceptionHandler") \
+ template(jdk_vm_ci_code_CompilationResult_Mark, "jdk/vm/ci/code/CompilationResult$Mark") \
+ template(jdk_vm_ci_code_CompilationResult_Infopoint, "jdk/vm/ci/code/CompilationResult$Infopoint") \
+ template(jdk_vm_ci_code_CompilationResult_Site, "jdk/vm/ci/code/CompilationResult$Site") \
+ template(jdk_vm_ci_code_InfopointReason, "jdk/vm/ci/code/InfopointReason") \
+ template(jdk_vm_ci_code_InstalledCode, "jdk/vm/ci/code/InstalledCode") \
+ template(jdk_vm_ci_code_BytecodeFrame, "jdk/vm/ci/code/BytecodeFrame") \
+ template(jdk_vm_ci_code_BytecodePosition, "jdk/vm/ci/code/BytecodePosition") \
+ template(jdk_vm_ci_code_DebugInfo, "jdk/vm/ci/code/DebugInfo") \
+ template(jdk_vm_ci_code_Location, "jdk/vm/ci/code/Location") \
+ template(jdk_vm_ci_code_Register, "jdk/vm/ci/code/Register") \
+ template(jdk_vm_ci_code_RegisterValue, "jdk/vm/ci/code/RegisterValue") \
+ template(jdk_vm_ci_code_StackSlot, "jdk/vm/ci/code/StackSlot") \
+ template(jdk_vm_ci_code_StackLockValue, "jdk/vm/ci/code/StackLockValue") \
+ template(jdk_vm_ci_code_VirtualObject, "jdk/vm/ci/code/VirtualObject") \
+ template(jdk_vm_ci_code_RegisterSaveLayout, "jdk/vm/ci/code/RegisterSaveLayout") \
+ template(jdk_vm_ci_code_InvalidInstalledCodeException, "jdk/vm/ci/code/InvalidInstalledCodeException") \
+ template(compileMethod_name, "compileMethod") \
+ template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)V") \
+ template(fromMetaspace_name, "fromMetaspace") \
+ template(method_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
+ template(constantPool_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;") \
+ template(klass_fromMetaspace_signature, "(Ljava/lang/Class;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
+ template(jdk_vm_ci_hotspot_Stable_signature, "Ljdk/vm/ci/hotspot/Stable;")
+#endif
+
+#endif // SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/memory/universe.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -143,6 +143,10 @@
// Heap
int Universe::_verify_count = 0;
+// Oop verification (see MacroAssembler::verify_oop)
+uintptr_t Universe::_verify_oop_mask = 0;
+uintptr_t Universe::_verify_oop_bits = (uintptr_t) -1;
+
int Universe::_base_vtable_size = 0;
bool Universe::_bootstrapping = false;
bool Universe::_fully_initialized = false;
@@ -1171,17 +1175,9 @@
_verify_in_progress = false;
}
-// Oop verification (see MacroAssembler::verify_oop)
-
-static uintptr_t _verify_oop_data[2] = {0, (uintptr_t)-1};
-static uintptr_t _verify_klass_data[2] = {0, (uintptr_t)-1};
-
#ifndef PRODUCT
-
-static void calculate_verify_data(uintptr_t verify_data[2],
- HeapWord* low_boundary,
- HeapWord* high_boundary) {
+void Universe::calculate_verify_data(HeapWord* low_boundary, HeapWord* high_boundary) {
assert(low_boundary < high_boundary, "bad interval");
// decide which low-order bits we require to be clear:
@@ -1206,28 +1202,25 @@
// require address alignment, too:
mask |= (alignSize - 1);
- if (!(verify_data[0] == 0 && verify_data[1] == (uintptr_t)-1)) {
- assert(verify_data[0] == mask && verify_data[1] == bits, "mask stability");
+ if (!(_verify_oop_mask == 0 && _verify_oop_bits == (uintptr_t)-1)) {
+ assert(_verify_oop_mask == mask && _verify_oop_bits == bits, "mask stability");
}
- verify_data[0] = mask;
- verify_data[1] = bits;
+ _verify_oop_mask = mask;
+ _verify_oop_bits = bits;
}
// Oop verification (see MacroAssembler::verify_oop)
uintptr_t Universe::verify_oop_mask() {
MemRegion m = heap()->reserved_region();
- calculate_verify_data(_verify_oop_data,
- m.start(),
- m.end());
- return _verify_oop_data[0];
+ calculate_verify_data(m.start(), m.end());
+ return _verify_oop_mask;
}
-
-
uintptr_t Universe::verify_oop_bits() {
- verify_oop_mask();
- return _verify_oop_data[1];
+ MemRegion m = heap()->reserved_region();
+ calculate_verify_data(m.start(), m.end());
+ return _verify_oop_bits;
}
uintptr_t Universe::verify_mark_mask() {
--- a/hotspot/src/share/vm/memory/universe.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/memory/universe.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -248,9 +248,14 @@
// Debugging
static int _verify_count; // number of verifies done
+
// True during call to verify(). Should only be set/cleared in verify().
static bool _verify_in_progress;
+ static uintptr_t _verify_oop_mask;
+ static uintptr_t _verify_oop_bits;
+
+ static void calculate_verify_data(HeapWord* low_boundary, HeapWord* high_boundary) PRODUCT_RETURN;
static void compute_verify_oop_data();
public:
--- a/hotspot/src/share/vm/oops/constantPool.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -662,6 +662,8 @@
int klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, false); }
int name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, false); }
+ int remap_instruction_operand_from_cache(int operand); // operand must be biased by CPCACHE_INDEX_TAG
+
// Lookup for entries consisting of (name_index, signature_index)
int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt)
int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt)
@@ -783,8 +785,6 @@
int impl_klass_ref_index_at(int which, bool uncached);
int impl_name_and_type_ref_index_at(int which, bool uncached);
- int remap_instruction_operand_from_cache(int operand); // operand must be biased by CPCACHE_INDEX_TAG
-
// Used while constructing constant pool (only by ClassFileParser)
jint klass_index_at(int which) {
assert(tag_at(which).is_klass_index(), "Corrupted constant pool");
--- a/hotspot/src/share/vm/oops/method.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -220,7 +220,7 @@
Thread* myThread = Thread::current();
methodHandle h_this(myThread, this);
-#ifdef ASSERT
+#if defined(ASSERT) && !INCLUDE_JVMCI
bool has_capability = myThread->is_VM_thread() ||
myThread->is_ConcurrentGC_thread() ||
myThread->is_GC_task_thread();
@@ -1373,7 +1373,7 @@
// These two methods are static since a GC may move the Method
bool Method::load_signature_classes(methodHandle m, TRAPS) {
- if (THREAD->is_Compiler_thread()) {
+ if (!THREAD->can_call_java()) {
// There is nothing useful this routine can do from within the Compile thread.
// Hopefully, the signature contains only well-known classes.
// We could scan for this and return true/false, but the caller won't care.
@@ -1491,14 +1491,20 @@
void Method::print_name(outputStream* st) {
Thread *thread = Thread::current();
ResourceMark rm(thread);
- SignatureTypePrinter sig(signature(), st);
st->print("%s ", is_static() ? "static" : "virtual");
- sig.print_returntype();
- st->print(" %s.", method_holder()->internal_name());
- name()->print_symbol_on(st);
- st->print("(");
- sig.print_parameters();
- st->print(")");
+ if (WizardMode) {
+ st->print("%s.", method_holder()->internal_name());
+ name()->print_symbol_on(st);
+ signature()->print_symbol_on(st);
+ } else {
+ SignatureTypePrinter sig(signature(), st);
+ sig.print_returntype();
+ st->print(" %s.", method_holder()->internal_name());
+ name()->print_symbol_on(st);
+ st->print("(");
+ sig.print_parameters();
+ st->print(")");
+ }
}
#endif // !PRODUCT || INCLUDE_JVMTI
--- a/hotspot/src/share/vm/oops/method.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/oops/method.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -685,8 +685,10 @@
TRAPS);
static Klass* check_non_bcp_klass(Klass* klass);
- // How many extra stack entries for invokedynamic when it's enabled
- static const int extra_stack_entries_for_jsr292 = 1;
+ enum {
+ // How many extra stack entries for invokedynamic
+ extra_stack_entries_for_jsr292 = 1
+ };
// this operates only on invoke methods:
// presize interpreter frames for extra interpreter stack entries, if needed
--- a/hotspot/src/share/vm/oops/methodData.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/oops/methodData.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -413,13 +413,39 @@
}
}
+#if INCLUDE_JVMCI
+void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+ ReceiverTypeData::clean_weak_klass_links(is_alive_cl);
+ for (uint row = 0; row < method_row_limit(); row++) {
+ Method* p = method(row);
+ if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) {
+ clear_method_row(row);
+ }
+ }
+}
+
+void VirtualCallData::clean_weak_method_links() {
+ ReceiverTypeData::clean_weak_method_links();
+ for (uint row = 0; row < method_row_limit(); row++) {
+ Method* p = method(row);
+ if (p != NULL && !p->on_stack()) {
+ clear_method_row(row);
+ }
+ }
+}
+#endif // INCLUDE_JVMCI
+
void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
uint row;
int entries = 0;
for (row = 0; row < row_limit(); row++) {
if (receiver(row) != NULL) entries++;
}
+#if INCLUDE_JVMCI
+ st->print_cr("count(%u) nonprofiled_count(%u) entries(%u)", count(), nonprofiled_count(), entries);
+#else
st->print_cr("count(%u) entries(%u)", count(), entries);
+#endif
int total = count();
for (row = 0; row < row_limit(); row++) {
if (receiver(row) != NULL) {
@@ -438,9 +464,36 @@
print_shared(st, "ReceiverTypeData", extra);
print_receiver_data_on(st);
}
+
+#if INCLUDE_JVMCI
+void VirtualCallData::print_method_data_on(outputStream* st) const {
+ uint row;
+ int entries = 0;
+ for (row = 0; row < method_row_limit(); row++) {
+ if (method(row) != NULL) entries++;
+ }
+ tab(st);
+ st->print_cr("method_entries(%u)", entries);
+ int total = count();
+ for (row = 0; row < method_row_limit(); row++) {
+ if (method(row) != NULL) {
+ total += method_count(row);
+ }
+ }
+ for (row = 0; row < method_row_limit(); row++) {
+ if (method(row) != NULL) {
+ tab(st);
+ method(row)->print_value_on(st);
+ st->print_cr("(%u %4.2f)", method_count(row), (float) method_count(row) / (float) total);
+ }
+ }
+}
+#endif // INCLUDE_JVMCI
+
void VirtualCallData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "VirtualCallData", extra);
print_receiver_data_on(st);
+ print_method_data_on(st);
}
// ==================================================================
@@ -665,7 +718,7 @@
}
int MethodData::bytecode_cell_count(Bytecodes::Code code) {
-#if defined(COMPILER1) && !defined(COMPILER2)
+#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
return no_profile_data;
#else
switch (code) {
@@ -797,6 +850,26 @@
}
int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) {
+#if INCLUDE_JVMCI
+ if (ProfileTraps) {
+ // Assume that up to 30% of the possibly trapping BCIs with no MDP will need to allocate one.
+ int extra_data_count = MIN2(empty_bc_count, MAX2(4, (empty_bc_count * 30) / 100));
+
+ // Make sure we have a minimum number of extra data slots to
+ // allocate SpeculativeTrapData entries. We would want to have one
+ // entry per compilation that inlines this method and for which
+ // some type speculation assumption fails. So the room we need for
+ // the SpeculativeTrapData entries doesn't directly depend on the
+ // size of the method. Because it's hard to estimate, we reserve
+ // space for an arbitrary number of entries.
+ int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) *
+ (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells());
+
+ return MAX2(extra_data_count, spec_data_count);
+ } else {
+ return 0;
+ }
+#else // INCLUDE_JVMCI
if (ProfileTraps) {
// Assume that up to 3% of BCIs with no MDP will need to allocate one.
int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1;
@@ -822,6 +895,7 @@
} else {
return 0;
}
+#endif // INCLUDE_JVMCI
}
// Compute the size of the MethodData* necessary to store
@@ -835,7 +909,7 @@
while ((c = stream.next()) >= 0) {
int size_in_bytes = compute_data_size(&stream);
data_size += size_in_bytes;
- if (size_in_bytes == 0) empty_bc_count += 1;
+ if (size_in_bytes == 0 JVMCI_ONLY(&& Bytecodes::can_trap(c))) empty_bc_count += 1;
needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c);
}
int object_size = in_bytes(data_offset()) + data_size;
@@ -869,7 +943,7 @@
// the segment in bytes.
int MethodData::initialize_data(BytecodeStream* stream,
int data_index) {
-#if defined(COMPILER1) && !defined(COMPILER2)
+#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
return 0;
#else
int cell_count = -1;
@@ -1060,10 +1134,14 @@
MethodData::MethodData(methodHandle method, int size, TRAPS)
: _extra_data_lock(Monitor::leaf, "MDO extra data lock"),
_parameters_type_data_di(parameters_uninitialized) {
+ // Set the method back-pointer.
+ _method = method();
+ initialize();
+}
+
+void MethodData::initialize() {
No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC
ResourceMark rm;
- // Set the method back-pointer.
- _method = method();
init();
set_creation_mileage(mileage_of(method()));
@@ -1073,13 +1151,13 @@
int data_size = 0;
int empty_bc_count = 0; // number of bytecodes lacking data
_data[0] = 0; // apparently not set below.
- BytecodeStream stream(method);
+ BytecodeStream stream(method());
Bytecodes::Code c;
bool needs_speculative_traps = false;
while ((c = stream.next()) >= 0) {
int size_in_bytes = initialize_data(&stream, data_size);
data_size += size_in_bytes;
- if (size_in_bytes == 0) empty_bc_count += 1;
+ if (size_in_bytes == 0 JVMCI_ONLY(&& Bytecodes::can_trap(c))) empty_bc_count += 1;
needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c);
}
_data_size = data_size;
@@ -1097,7 +1175,7 @@
// the code for traps cells works.
DataLayout *dp = data_layout_at(data_size + extra_size);
- int arg_size = method->size_of_parameters();
+ int arg_size = method()->size_of_parameters();
dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
@@ -1126,6 +1204,7 @@
post_initialize(&stream);
+ assert(object_size == compute_allocation_size_in_bytes(methodHandle(_method)), "MethodData: computed size != initialized size");
set_size(object_size);
}
@@ -1146,6 +1225,10 @@
_num_blocks = 0;
_would_profile = unknown;
+#if INCLUDE_JVMCI
+ _jvmci_ir_size = 0;
+#endif
+
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM; // No RTM lock eliding by default
if (UseRTMLocking &&
--- a/hotspot/src/share/vm/oops/methodData.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/oops/methodData.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -539,7 +539,11 @@
enum {
// null_seen:
// saw a null operand (cast/aastore/instanceof)
- null_seen_flag = DataLayout::first_flag + 0
+ null_seen_flag = DataLayout::first_flag + 0
+#if INCLUDE_JVMCI
+ // bytecode threw any exception
+ , exception_seen_flag = null_seen_flag + 1
+#endif
};
enum { bit_cell_count = 0 }; // no additional data fields needed.
public:
@@ -563,6 +567,11 @@
bool null_seen() { return flag_at(null_seen_flag); }
void set_null_seen() { set_flag_at(null_seen_flag); }
+#if INCLUDE_JVMCI
+ // true if an exception was thrown at the specific BCI
+ bool exception_seen() { return flag_at(exception_seen_flag); }
+ void set_exception_seen() { set_flag_at(exception_seen_flag); }
+#endif
// Code generation support
static int null_seen_byte_constant() {
@@ -1166,7 +1175,22 @@
class ReceiverTypeData : public CounterData {
protected:
enum {
+#if INCLUDE_JVMCI
+ // Description of the different counters
+ // ReceiverTypeData for instanceof/checkcast/aastore:
+ // C1/C2: count is incremented on type overflow and decremented for failed type checks
+ // JVMCI: count decremented for failed type checks and nonprofiled_count is incremented on type overflow
+ // TODO (chaeubl): in fact, JVMCI should also increment the count for failed type checks to mimic the C1/C2 behavior
+ // VirtualCallData for invokevirtual/invokeinterface:
+ // C1/C2: count is incremented on type overflow
+ // JVMCI: count is incremented on type overflow, nonprofiled_count is incremented on method overflow
+
+ // JVMCI is interested in knowing the percentage of type checks involving a type not explicitly in the profile
+ nonprofiled_count_off_set = counter_cell_count,
+ receiver0_offset,
+#else
receiver0_offset = counter_cell_count,
+#endif
count0_offset,
receiver_type_row_cell_count = (count0_offset + 1) - receiver0_offset
};
@@ -1181,7 +1205,7 @@
virtual bool is_ReceiverTypeData() const { return true; }
static int static_cell_count() {
- return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count;
+ return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count JVMCI_ONLY(+ 1);
}
virtual int cell_count() const {
@@ -1243,6 +1267,13 @@
set_count(0);
set_receiver(row, NULL);
set_receiver_count(row, 0);
+#if INCLUDE_JVMCI
+ if (!this->is_VirtualCallData()) {
+ // if this is a ReceiverTypeData for JVMCI, the nonprofiled_count
+ // must also be reset (see "Description of the different counters" above)
+ set_nonprofiled_count(0);
+ }
+#endif
}
// Code generation support
@@ -1252,6 +1283,17 @@
static ByteSize receiver_count_offset(uint row) {
return cell_offset(receiver_count_cell_index(row));
}
+#if INCLUDE_JVMCI
+ static ByteSize nonprofiled_receiver_count_offset() {
+ return cell_offset(nonprofiled_count_off_set);
+ }
+ uint nonprofiled_count() const {
+ return uint_at(nonprofiled_count_off_set);
+ }
+ void set_nonprofiled_count(uint count) {
+ set_uint_at(nonprofiled_count_off_set, count);
+ }
+#endif // INCLUDE_JVMCI
static ByteSize receiver_type_data_size() {
return cell_offset(static_cell_count());
}
@@ -1316,7 +1358,7 @@
static int static_cell_count() {
// At this point we could add more profile state, e.g., for arguments.
// But for now it's the same size as the base record type.
- return ReceiverTypeData::static_cell_count();
+ return ReceiverTypeData::static_cell_count() JVMCI_ONLY(+ (uint) MethodProfileWidth * receiver_type_row_cell_count);
}
virtual int cell_count() const {
@@ -1338,6 +1380,62 @@
}
#endif // CC_INTERP
+#if INCLUDE_JVMCI
+ static ByteSize method_offset(uint row) {
+ return cell_offset(method_cell_index(row));
+ }
+ static ByteSize method_count_offset(uint row) {
+ return cell_offset(method_count_cell_index(row));
+ }
+ static int method_cell_index(uint row) {
+ return receiver0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+ }
+ static int method_count_cell_index(uint row) {
+ return count0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+ }
+ static uint method_row_limit() {
+ return MethodProfileWidth;
+ }
+
+ Method* method(uint row) const {
+ assert(row < method_row_limit(), "oob");
+
+ Method* method = (Method*)intptr_at(method_cell_index(row));
+ assert(method == NULL || method->is_method(), "must be");
+ return method;
+ }
+
+ uint method_count(uint row) const {
+ assert(row < method_row_limit(), "oob");
+ return uint_at(method_count_cell_index(row));
+ }
+
+ void set_method(uint row, Method* m) {
+ assert((uint)row < method_row_limit(), "oob");
+ set_intptr_at(method_cell_index(row), (uintptr_t)m);
+ }
+
+ void set_method_count(uint row, uint count) {
+ assert(row < method_row_limit(), "oob");
+ set_uint_at(method_count_cell_index(row), count);
+ }
+
+ void clear_method_row(uint row) {
+ assert(row < method_row_limit(), "oob");
+ // Clear total count - indicator of polymorphic call site (see comment for clear_row() in ReceiverTypeData).
+ set_nonprofiled_count(0);
+ set_method(row, NULL);
+ set_method_count(row, 0);
+ }
+
+ // GC support
+ virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+
+ // Redefinition support
+ virtual void clean_weak_method_links();
+#endif // INCLUDE_JVMCI
+
+ void print_method_data_on(outputStream* st) const NOT_JVMCI_RETURN;
void print_data_on(outputStream* st, const char* extra = NULL) const;
};
@@ -2053,10 +2151,11 @@
MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData
bool is_methodData() const volatile { return true; }
+ void initialize();
// Whole-method sticky bits and flags
enum {
- _trap_hist_limit = 22, // decoupled from Deoptimization::Reason_LIMIT
+ _trap_hist_limit = 22 JVMCI_ONLY(+5), // decoupled from Deoptimization::Reason_LIMIT
_trap_hist_mask = max_jubyte,
_extra_data_count = 4 // extra DataLayout headers, for trap history
}; // Public flag values
@@ -2104,6 +2203,11 @@
enum WouldProfile {unknown, no_profile, profile};
WouldProfile _would_profile;
+#if INCLUDE_JVMCI
+ // Support for HotSpotMethodData.setCompiledIRSize(int)
+ int _jvmci_ir_size;
+#endif
+
// Size of _data array in bytes. (Excludes header and extra_data fields.)
int _data_size;
@@ -2382,7 +2486,7 @@
// Return (uint)-1 for overflow.
uint trap_count(int reason) const {
- assert((uint)reason < _trap_hist_limit, "oob");
+ assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob");
return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1;
}
// For loops:
@@ -2391,17 +2495,13 @@
uint inc_trap_count(int reason) {
// Count another trap, anywhere in this method.
assert(reason >= 0, "must be single trap");
- if ((uint)reason < _trap_hist_limit) {
- uint cnt1 = 1 + _trap_hist._array[reason];
- if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow...
- _trap_hist._array[reason] = cnt1;
- return cnt1;
- } else {
- return _trap_hist_mask + (++_nof_overflow_traps);
- }
+ assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob");
+ uint cnt1 = 1 + _trap_hist._array[reason];
+ if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow...
+ _trap_hist._array[reason] = cnt1;
+ return cnt1;
} else {
- // Could not represent the count in the histogram.
- return (++_nof_overflow_traps);
+ return _trap_hist_mask + (++_nof_overflow_traps);
}
}
@@ -2446,6 +2546,10 @@
return byte_offset_of(MethodData, _data[0]);
}
+ static ByteSize trap_history_offset() {
+ return byte_offset_of(MethodData, _trap_hist._array);
+ }
+
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodData, _invocation_counter);
}
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -2254,6 +2254,8 @@
if (failing()) return;
}
}
+ // Ensure that major progress is now clear
+ C->clear_major_progress();
{
// Verify that all previous optimizations produced a valid graph
--- a/hotspot/src/share/vm/opto/node.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/opto/node.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -47,6 +47,10 @@
#ifndef PRODUCT
extern int nodes_created;
#endif
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
#ifdef ASSERT
@@ -456,6 +460,10 @@
_in[6] = n6; if (n6 != NULL) n6->add_out((Node *)this);
}
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
//------------------------------clone------------------------------------------
// Clone a Node.
--- a/hotspot/src/share/vm/opto/output.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/opto/output.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -856,7 +856,9 @@
assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI");
assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest");
// Now we can describe the scope.
- debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+ methodHandle null_mh;
+ bool rethrow_exception = false;
+ debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
} // End jvms loop
// Mark the end of the scope set.
@@ -939,7 +941,8 @@
JVMState* jvms = youngest_jvms->of_depth(depth);
ciMethod* method = jvms->has_method() ? jvms->method() : NULL;
assert(!jvms->should_reexecute() || depth==max_depth, "reexecute allowed only for the youngest");
- debug_info->describe_scope(pc_offset, method, jvms->bci(), jvms->should_reexecute());
+ methodHandle null_mh;
+ debug_info->describe_scope(pc_offset, null_mh, method, jvms->bci(), jvms->should_reexecute());
}
// Mark the end of the scope set.
--- a/hotspot/src/share/vm/opto/superword.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/opto/superword.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -200,6 +200,31 @@
static const SWNodeInfo initial;
};
+// JVMCI: OrderedPair is moved up to deal with compilation issues on Windows
+//------------------------------OrderedPair---------------------------
+// Ordered pair of Node*.
+class OrderedPair VALUE_OBJ_CLASS_SPEC {
+ protected:
+ Node* _p1;
+ Node* _p2;
+ public:
+ OrderedPair() : _p1(NULL), _p2(NULL) {}
+ OrderedPair(Node* p1, Node* p2) {
+ if (p1->_idx < p2->_idx) {
+ _p1 = p1; _p2 = p2;
+ } else {
+ _p1 = p2; _p2 = p1;
+ }
+ }
+
+ bool operator==(const OrderedPair &rhs) {
+ return _p1 == rhs._p1 && _p2 == rhs._p2;
+ }
+ void print() { tty->print(" (%d, %d)", _p1->_idx, _p2->_idx); }
+
+ static const OrderedPair initial;
+};
+
// -----------------------------SuperWord---------------------------------
// Transforms scalar operations into packed (superword) operations.
class SuperWord : public ResourceObj {
@@ -634,29 +659,4 @@
#endif
};
-
-//------------------------------OrderedPair---------------------------
-// Ordered pair of Node*.
-class OrderedPair VALUE_OBJ_CLASS_SPEC {
- protected:
- Node* _p1;
- Node* _p2;
- public:
- OrderedPair() : _p1(NULL), _p2(NULL) {}
- OrderedPair(Node* p1, Node* p2) {
- if (p1->_idx < p2->_idx) {
- _p1 = p1; _p2 = p2;
- } else {
- _p1 = p2; _p2 = p1;
- }
- }
-
- bool operator==(const OrderedPair &rhs) {
- return _p1 == rhs._p1 && _p2 == rhs._p2;
- }
- void print() { tty->print(" (%d, %d)", _p1->_idx, _p2->_idx); }
-
- static const OrderedPair initial;
-};
-
#endif // SHARE_VM_OPTO_SUPERWORD_HPP
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -290,6 +290,9 @@
# include "c1/c1_ValueType.hpp"
# include "c1/c1_globals.hpp"
#endif // COMPILER1
+#if INCLUDE_JVMCI
+# include "jvmci/jvmci_globals.hpp"
+#endif // INCLUDE_JVMCI
#if INCLUDE_ALL_GCS
# include "gc/cms/compactibleFreeListSpace.hpp"
# include "gc/cms/concurrentMarkSweepGeneration.hpp"
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -81,6 +81,10 @@
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
static jint CurrentVersion = JNI_VERSION_1_8;
@@ -3986,6 +3990,19 @@
*vm = (JavaVM *)(&main_vm);
*(JNIEnv**)penv = thread->jni_environment();
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ if (UseJVMCICompiler) {
+ // JVMCI is initialized on a CompilerThread
+ if (BootstrapJVMCI) {
+ JavaThread* THREAD = thread;
+ JVMCICompiler* compiler = JVMCICompiler::instance(CATCH);
+ compiler->bootstrap();
+ }
+ }
+ }
+#endif
+
// Tracks the time application was running before GC
RuntimeService::record_application_start();
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -424,6 +424,8 @@
const char* compiler_name = "HotSpot " CSIZE "Client Compiler";
#elif defined(COMPILER2)
const char* compiler_name = "HotSpot " CSIZE "Server Compiler";
+#elif INCLUDE_JVMCI
+ #error "INCLUDE_JVMCI should imply TIERED"
#else
const char* compiler_name = "";
#endif // compilers
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -266,7 +266,7 @@
address scopes_data = nm->scopes_data_begin();
for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
- ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
+ ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->rethrow_exception(), pcd->return_oop());
ScopeDesc *sd = &sc0;
while( !sd->is_top() ) { sd = sd->sender(); }
int bci = sd->bci();
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -345,7 +345,7 @@
Symbol* MethodHandles::signature_polymorphic_intrinsic_name(vmIntrinsics::ID iid) {
- assert(is_signature_polymorphic_intrinsic(iid), err_msg("iid=%d", iid));
+ assert(is_signature_polymorphic_intrinsic(iid), err_msg("%d %s", iid, vmIntrinsics::name_at(iid)));
switch (iid) {
case vmIntrinsics::_invokeBasic: return vmSymbols::invokeBasic_name();
case vmIntrinsics::_linkToVirtual: return vmSymbols::linkToVirtual_name();
@@ -353,7 +353,7 @@
case vmIntrinsics::_linkToSpecial: return vmSymbols::linkToSpecial_name();
case vmIntrinsics::_linkToInterface: return vmSymbols::linkToInterface_name();
}
- assert(false, "");
+ fatal(err_msg("unexpected intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
return 0;
}
@@ -365,7 +365,7 @@
case vmIntrinsics::_linkToSpecial: return JVM_REF_invokeSpecial;
case vmIntrinsics::_linkToInterface: return JVM_REF_invokeInterface;
}
- assert(false, err_msg("iid=%d", iid));
+ fatal(err_msg("unexpected intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
return 0;
}
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -111,6 +111,10 @@
void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
+#if INCLUDE_JVMCI
+ jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
+ void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
+#endif
}
#define CC (char*) /* cast a literal from (const char*) */
@@ -121,6 +125,10 @@
{ CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
{ CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) },
{ CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) },
+#if INCLUDE_JVMCI
+ { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", NULL, FN_PTR(JVM_GetJVMCIRuntime) },
+ { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", NULL, FN_PTR(JVM_RegisterJVMCINatives) },
+#endif
};
static address lookup_special_native(char* jni_name) {
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1025,7 +1025,7 @@
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
- result = env->NewObjectArray(4, clazz, NULL);
+ result = env->NewObjectArray(5, clazz, NULL);
if (result == NULL) {
return result;
}
@@ -1047,6 +1047,10 @@
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetObjectArrayElement(result, 3, id);
+ jobject address = longBox(thread, env, (jlong) code);
+ CHECK_JNI_EXCEPTION_(env, NULL);
+ env->SetObjectArrayElement(result, 4, address);
+
return result;
WB_END
@@ -1133,6 +1137,13 @@
return codeBlob2objectArray(thread, env, &stub);
WB_END
+WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
+ jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+ CHECK_JNI_EXCEPTION_(env, 0);
+ methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
+ return (jlong) mh->method_data();
+WB_END
+
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
return (jlong) Thread::current()->stack_size();
WB_END
@@ -1142,6 +1153,7 @@
return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong) StackShadowPages * os::vm_page_size();
WB_END
+
int WhiteBox::array_bytes_to_length(size_t bytes) {
return Array<u1>::bytes_to_length(bytes);
}
@@ -1218,6 +1230,11 @@
VMThread::execute(&force_safepoint_op);
WB_END
+WB_ENTRY(long, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
+ instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
+ return (long) ikh->constants();
+WB_END
+
template <typename T>
static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
assert(value != NULL, "sanity");
@@ -1509,12 +1526,15 @@
{CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
{CC"getCompilationActivityMode",
CC"()I", (void*)&WB_GetCompilationActivityMode},
+ {CC"getMethodData0", CC"(Ljava/lang/reflect/Executable;)J",
+ (void*)&WB_GetMethodData },
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
+ {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool },
{CC"getMethodBooleanOption",
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
(void*)&WB_GetMethodBooleaneOption},
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, 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
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
+#include "compiler/compileTask.hpp"
#include "runtime/advancedThresholdPolicy.hpp"
#include "runtime/simpleThresholdPolicy.inline.hpp"
@@ -162,6 +163,9 @@
// Called with the queue locked and with at least one element
CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
+#if INCLUDE_JVMCI
+ CompileTask *max_non_jvmci_task = NULL;
+#endif
CompileTask *max_task = NULL;
Method* max_method = NULL;
jlong t = os::javaTimeMillis();
@@ -179,6 +183,7 @@
if (PrintTieredEvents) {
print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
}
+ task->log_task_dequeued("stale");
compile_queue->remove_and_mark_stale(task);
method->clear_queued_for_compilation();
task = next_task;
@@ -194,6 +199,15 @@
task = next_task;
}
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ if (max_non_jvmci_task != NULL) {
+ max_task = max_non_jvmci_task;
+ max_method = max_task->method();
+ }
+ }
+#endif
+
if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile
&& is_method_profiled(max_method)) {
max_task->set_comp_level(CompLevel_limited_profile);
@@ -354,6 +368,14 @@
if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
} else if ((this->*p)(i, b, cur_level, method)) {
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ // Since JVMCI takes a while to warm up, its queue inevitably backs up during
+ // early VM execution.
+ next_level = CompLevel_full_profile;
+ break;
+ }
+#endif
// C1-generated fully profiled code is about 30% slower than the limited profile
// code that has only invocation and backedge counters. The observation is that
// if C2 queue is large enough we can spend too much time in the fully profiled code
@@ -362,7 +384,7 @@
// we choose to compile a limited profiled version and then recompile with full profiling
// when the load on C2 goes down.
if (!disable_feedback && CompileBroker::queue_size(CompLevel_full_optimization) >
- Tier3DelayOn * compiler_count(CompLevel_full_optimization)) {
+ Tier3DelayOn * compiler_count(CompLevel_full_optimization)) {
next_level = CompLevel_limited_profile;
} else {
next_level = CompLevel_full_profile;
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -50,6 +50,9 @@
#include "utilities/defaultStream.hpp"
#include "utilities/macros.hpp"
#include "utilities/stringUtils.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
#if INCLUDE_ALL_GCS
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
@@ -213,6 +216,8 @@
// Set OS specific system properties values
os::init_system_properties_values();
+
+ JVMCI_ONLY(JVMCIRuntime::init_system_properties(&_system_properties);)
}
// Update/Initialize System properties after JDK version number is known
@@ -1374,7 +1379,7 @@
}
}
-#if defined(COMPILER2) || defined(_LP64) || !INCLUDE_CDS
+#if defined(COMPILER2) || INCLUDE_JVMCI || defined(_LP64) || !INCLUDE_CDS
// Conflict: required to use shared spaces (-Xshare:on), but
// incompatible command line options were chosen.
@@ -1834,7 +1839,7 @@
void Arguments::set_ergonomics_flags() {
select_gc();
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
// Shared spaces work fine with other GCs but causes bytecode rewriting
// to be disabled, which hurts interpreter performance and decreases
// server performance. When -server is specified, keep the default off
@@ -1918,7 +1923,7 @@
void Arguments::set_g1_gc_flags() {
assert(UseG1GC, "Error");
-#ifdef COMPILER1
+#if defined(COMPILER1) || INCLUDE_JVMCI
FastTLABRefill = false;
#endif
FLAG_SET_DEFAULT(ParallelGCThreads, Abstract_VM_Version::parallel_worker_threads());
@@ -2495,6 +2500,22 @@
}
#endif
}
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ if (!ScavengeRootsInCode) {
+ warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
+ ScavengeRootsInCode = 1;
+ }
+ if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
+ TypeProfileLevel = 0;
+ }
+ if (UseJVMCICompiler) {
+ if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
+ TypeProfileWidth = 8;
+ }
+ }
+ }
+#endif
// Check lower bounds of the code cache
// Template Interpreter code is approximately 3X larger in debug builds.
@@ -3463,6 +3484,37 @@
const char* fileSep = os::file_separator();
sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
+#if INCLUDE_JVMCI
+ jint res = JVMCIRuntime::save_options(_system_properties);
+ if (res != JNI_OK) {
+ return res;
+ }
+
+ if (EnableJVMCI) {
+ // Append lib/jvmci/*.jar to boot class path
+ char jvmciDir[JVM_MAXPATHLEN];
+ const char* fileSep = os::file_separator();
+ jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", Arguments::get_java_home(), fileSep, fileSep);
+ DIR* dir = os::opendir(jvmciDir);
+ if (dir != NULL) {
+ struct dirent *entry;
+ char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal);
+ while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+ const char* name = entry->d_name;
+ const char* ext = name + strlen(name) - 4;
+ if (ext > name && strcmp(ext, ".jar") == 0) {
+ char fileName[JVM_MAXPATHLEN];
+ jio_snprintf(fileName, sizeof(fileName), "%s%s%s", jvmciDir, fileSep, name);
+ scp_p->add_suffix(fileName);
+ scp_assembly_required = true;
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, dbuf);
+ os::closedir(dir);
+ }
+ }
+#endif // INCLUDE_JVMCI
+
if (CheckEndorsedAndExtDirs) {
int nonEmptyDirs = 0;
// check endorsed directory
@@ -3521,7 +3573,7 @@
FLAG_SET_ERGO(uintx, InitialTenuringThreshold, MaxTenuringThreshold);
}
-#ifndef COMPILER2
+#if !defined(COMPILER2) && !INCLUDE_JVMCI
// Don't degrade server performance for footprint
if (FLAG_IS_DEFAULT(UseLargePages) &&
MaxHeapSize < LargePageHeapSizeThreshold) {
@@ -3531,7 +3583,7 @@
FLAG_SET_DEFAULT(UseLargePages, false);
}
-#else
+#elif defined(COMPILER2)
if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) {
FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1);
}
@@ -4279,6 +4331,9 @@
#ifdef COMPILER1
|| !UseFastLocking
#endif // COMPILER1
+#if INCLUDE_JVMCI
+ || !JVMCIUseFastLocking
+#endif
) {
if (!FLAG_IS_DEFAULT(UseBiasedLocking) && UseBiasedLocking) {
// flag set to true on command line; warn the user that they
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -33,6 +33,9 @@
#include "runtime/commandLineFlagConstraintsRuntime.hpp"
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
+#endif
class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
CommandLineFlagConstraintFunc_bool _constraint;
@@ -251,6 +254,18 @@
IGNORE_RANGE,
EMIT_CONSTRAINT_CHECK));
+#if INCLUDE_JVMCI
+ emit_constraint_no(NULL JVMCI_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+ EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+ EMIT_CONSTRAINT_PRODUCT_FLAG,
+ EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+ EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+ EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+ EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+ IGNORE_RANGE,
+ EMIT_CONSTRAINT_CHECK));
+#endif // INCLUDE_JVMCI
+
#ifdef COMPILER1
emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -58,7 +58,7 @@
*/
Flag::Error CICompilerCountConstraintFunc(intx value, bool verbose) {
int min_number_of_compiler_threads = 0;
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
// case 1
#else
if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -309,6 +309,18 @@
EMIT_RANGE_CHECK,
IGNORE_CONSTRAINT));
+#if INCLUDE_JVMCI
+ emit_range_no(NULL JVMCI_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+ EMIT_RANGE_PD_DEVELOPER_FLAG,
+ EMIT_RANGE_PRODUCT_FLAG,
+ EMIT_RANGE_PD_PRODUCT_FLAG,
+ EMIT_RANGE_DIAGNOSTIC_FLAG,
+ EMIT_RANGE_EXPERIMENTAL_FLAG,
+ EMIT_RANGE_NOTPRODUCT_FLAG,
+ EMIT_RANGE_CHECK,
+ IGNORE_CONSTRAINT));
+#endif // INCLUDE_JVMCI
+
#ifdef COMPILER1
emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
EMIT_RANGE_PD_DEVELOPER_FLAG,
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,6 +37,7 @@
#include "memory/resourceArea.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/fieldStreams.hpp"
#include "oops/verifyOopClosure.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/biasedLocking.hpp"
@@ -55,6 +56,12 @@
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
+
+
bool DeoptimizationMarker::_is_active = false;
Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame,
@@ -132,6 +139,9 @@
// handler. Note this fact before we start generating temporary frames
// that can confuse an asynchronous stack walker. This counter is
// decremented at the end of unpack_frames().
+ if (TraceDeoptimization) {
+ tty->print_cr("Deoptimizing thread " INTPTR_FORMAT, thread);
+ }
thread->inc_in_deopt_handler();
return fetch_unroll_info_helper(thread);
@@ -159,6 +169,7 @@
// Set the deoptee nmethod
assert(thread->deopt_nmethod() == NULL, "Pending deopt!");
thread->set_deopt_nmethod(deoptee.cb()->as_nmethod_or_null());
+ bool skip_internal = thread->deopt_nmethod() != NULL && !thread->deopt_nmethod()->compiler()->is_jvmci();
if (VerifyStack) {
thread->validate_frame_layout();
@@ -179,11 +190,13 @@
bool realloc_failures = false;
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
// Reallocate the non-escaping objects and restore their fields. Then
// relock objects if synchronization on them was eliminated.
+#ifndef INCLUDE_JVMCI
if (DoEscapeAnalysis || EliminateNestedLocks) {
if (EliminateAllocations) {
+#endif // INCLUDE_JVMCI
assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
@@ -213,7 +226,7 @@
JRT_BLOCK
realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
JRT_END
- reassign_fields(&deoptee, &map, objects, realloc_failures);
+ reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
#ifndef PRODUCT
if (TraceDeoptimization) {
ttyLocker ttyl;
@@ -226,8 +239,10 @@
// Restore result.
deoptee.set_saved_oop_result(&map, return_value());
}
+#ifndef INCLUDE_JVMCI
}
if (EliminateLocks) {
+#endif // INCLUDE_JVMCI
#ifndef PRODUCT
bool first = true;
#endif
@@ -238,7 +253,7 @@
if (monitors->is_nonempty()) {
relock_objects(monitors, thread, realloc_failures);
#ifndef PRODUCT
- if (TraceDeoptimization) {
+ if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
for (int j = 0; j < monitors->length(); j++) {
MonitorInfo* mi = monitors->at(j);
@@ -256,19 +271,22 @@
}
}
}
-#endif
+#endif // !PRODUCT
}
}
+#ifndef INCLUDE_JVMCI
}
}
-#endif // COMPILER2
+#endif // INCLUDE_JVMCI
+#endif // COMPILER2 || INCLUDE_JVMCI
+
// Ensure that no safepoint is taken after pointers have been stored
// in fields of rematerialized objects. If a safepoint occurs from here on
// out the java state residing in the vframeArray will be missed.
No_Safepoint_Verifier no_safepoint;
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (realloc_failures) {
pop_frames_failed_reallocs(thread, array);
}
@@ -318,7 +336,11 @@
unpack_sp = deoptee.unextended_sp();
#ifdef ASSERT
- assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking");
+ assert(cb->is_deoptimization_stub() ||
+ cb->is_uncommon_trap_stub() ||
+ strcmp("Stub<DeoptimizationStub.deoptimizationHandler>", cb->name()) == 0 ||
+ strcmp("Stub<UncommonTrapStub.uncommonTrapHandler>", cb->name()) == 0,
+ err_msg("unexpected code blob: %s", cb->name()));
#endif
#else
intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp();
@@ -721,7 +743,7 @@
Deoptimization::DeoptAction Deoptimization::_unloaded_action
= Deoptimization::Action_reinterpret;
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
Handle pending_exception(thread->pending_exception());
const char* exception_file = thread->exception_file();
@@ -769,77 +791,6 @@
return failures;
}
-// This assumes that the fields are stored in ObjectValue in the same order
-// they are yielded by do_nonstatic_fields.
-class FieldReassigner: public FieldClosure {
- frame* _fr;
- RegisterMap* _reg_map;
- ObjectValue* _sv;
- InstanceKlass* _ik;
- oop _obj;
-
- int _i;
-public:
- FieldReassigner(frame* fr, RegisterMap* reg_map, ObjectValue* sv, oop obj) :
- _fr(fr), _reg_map(reg_map), _sv(sv), _obj(obj), _i(0) {}
-
- int i() const { return _i; }
-
-
- void do_field(fieldDescriptor* fd) {
- intptr_t val;
- StackValue* value =
- StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(i()));
- int offset = fd->offset();
- switch (fd->field_type()) {
- case T_OBJECT: case T_ARRAY:
- assert(value->type() == T_OBJECT, "Agreement.");
- _obj->obj_field_put(offset, value->get_obj()());
- break;
-
- case T_LONG: case T_DOUBLE: {
- assert(value->type() == T_INT, "Agreement.");
- StackValue* low =
- StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(++_i));
-#ifdef _LP64
- jlong res = (jlong)low->get_int();
-#else
-#ifdef SPARC
- // For SPARC we have to swap high and low words.
- jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
-#else
- jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
-#endif //SPARC
-#endif
- _obj->long_field_put(offset, res);
- break;
- }
- // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
- case T_INT: case T_FLOAT: // 4 bytes.
- assert(value->type() == T_INT, "Agreement.");
- val = value->get_int();
- _obj->int_field_put(offset, (jint)*((jint*)&val));
- break;
-
- case T_SHORT: case T_CHAR: // 2 bytes
- assert(value->type() == T_INT, "Agreement.");
- val = value->get_int();
- _obj->short_field_put(offset, (jshort)*((jint*)&val));
- break;
-
- case T_BOOLEAN: case T_BYTE: // 1 byte
- assert(value->type() == T_INT, "Agreement.");
- val = value->get_int();
- _obj->bool_field_put(offset, (jboolean)*((jint*)&val));
- break;
-
- default:
- ShouldNotReachHere();
- }
- _i++;
- }
-};
-
// restore elements of an eliminated type array
void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) {
int index = 0;
@@ -867,11 +818,43 @@
}
// Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
- case T_INT: case T_FLOAT: // 4 bytes.
+ case T_INT: case T_FLOAT: { // 4 bytes.
assert(value->type() == T_INT, "Agreement.");
- val = value->get_int();
- obj->int_at_put(index, (jint)*((jint*)&val));
+ bool big_value = false;
+ if (i + 1 < sv->field_size() && type == T_INT) {
+ if (sv->field_at(i)->is_location()) {
+ Location::Type type = ((LocationValue*) sv->field_at(i))->location().type();
+ if (type == Location::dbl || type == Location::lng) {
+ big_value = true;
+ }
+ } else if (sv->field_at(i)->is_constant_int()) {
+ ScopeValue* next_scope_field = sv->field_at(i + 1);
+ if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+ big_value = true;
+ }
+ }
+ }
+
+ if (big_value) {
+ StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
+ #ifdef _LP64
+ jlong res = (jlong)low->get_int();
+ #else
+ #ifdef SPARC
+ // For SPARC we have to swap high and low words.
+ jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+ #else
+ jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+ #endif //SPARC
+ #endif
+ obj->int_at_put(index, (jint)*((jint*)&res));
+ obj->int_at_put(++index, (jint)*(((jint*)&res) + 1));
+ } else {
+ val = value->get_int();
+ obj->int_at_put(index, (jint)*((jint*)&val));
+ }
break;
+ }
case T_SHORT: case T_CHAR: // 2 bytes
assert(value->type() == T_INT, "Agreement.");
@@ -902,22 +885,135 @@
}
}
+class ReassignedField {
+public:
+ int _offset;
+ BasicType _type;
+public:
+ ReassignedField() {
+ _offset = 0;
+ _type = T_ILLEGAL;
+ }
+};
+
+int compare(ReassignedField* left, ReassignedField* right) {
+ return left->_offset - right->_offset;
+}
+
+// Restore fields of an eliminated instance object using the same field order
+// returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true)
+static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal) {
+ if (klass->superklass() != NULL) {
+ svIndex = reassign_fields_by_klass(klass->superklass(), fr, reg_map, sv, svIndex, obj, skip_internal);
+ }
+
+ GrowableArray<ReassignedField>* fields = new GrowableArray<ReassignedField>();
+ for (AllFieldStream fs(klass); !fs.done(); fs.next()) {
+ if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
+ ReassignedField field;
+ field._offset = fs.offset();
+ field._type = FieldType::basic_type(fs.signature());
+ fields->append(field);
+ }
+ }
+ fields->sort(compare);
+ for (int i = 0; i < fields->length(); i++) {
+ intptr_t val;
+ ScopeValue* scope_field = sv->field_at(svIndex);
+ StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field);
+ int offset = fields->at(i)._offset;
+ BasicType type = fields->at(i)._type;
+ switch (type) {
+ case T_OBJECT: case T_ARRAY:
+ assert(value->type() == T_OBJECT, "Agreement.");
+ obj->obj_field_put(offset, value->get_obj()());
+ break;
+
+ // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
+ case T_INT: case T_FLOAT: { // 4 bytes.
+ assert(value->type() == T_INT, "Agreement.");
+ bool big_value = false;
+ if (i+1 < fields->length() && fields->at(i+1)._type == T_INT) {
+ if (scope_field->is_location()) {
+ Location::Type type = ((LocationValue*) scope_field)->location().type();
+ if (type == Location::dbl || type == Location::lng) {
+ big_value = true;
+ }
+ }
+ if (scope_field->is_constant_int()) {
+ ScopeValue* next_scope_field = sv->field_at(svIndex + 1);
+ if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+ big_value = true;
+ }
+ }
+ }
+
+ if (big_value) {
+ i++;
+ assert(i < fields->length(), "second T_INT field needed");
+ assert(fields->at(i)._type == T_INT, "T_INT field needed");
+ } else {
+ val = value->get_int();
+ obj->int_field_put(offset, (jint)*((jint*)&val));
+ break;
+ }
+ }
+ /* no break */
+
+ case T_LONG: case T_DOUBLE: {
+ assert(value->type() == T_INT, "Agreement.");
+ StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++svIndex));
+#ifdef _LP64
+ jlong res = (jlong)low->get_int();
+#else
+#ifdef SPARC
+ // For SPARC we have to swap high and low words.
+ jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+#else
+ jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+#endif //SPARC
+#endif
+ obj->long_field_put(offset, res);
+ break;
+ }
+
+ case T_SHORT: case T_CHAR: // 2 bytes
+ assert(value->type() == T_INT, "Agreement.");
+ val = value->get_int();
+ obj->short_field_put(offset, (jshort)*((jint*)&val));
+ break;
+
+ case T_BOOLEAN: case T_BYTE: // 1 byte
+ assert(value->type() == T_INT, "Agreement.");
+ val = value->get_int();
+ obj->bool_field_put(offset, (jboolean)*((jint*)&val));
+ break;
+
+ default:
+ ShouldNotReachHere();
+ }
+ svIndex++;
+ }
+ return svIndex;
+}
// restore fields of all eliminated objects and arrays
-void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
+void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal) {
for (int i = 0; i < objects->length(); i++) {
ObjectValue* sv = (ObjectValue*) objects->at(i);
KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
Handle obj = sv->value();
assert(obj.not_null() || realloc_failures, "reallocation was missed");
+ if (PrintDeoptimizationDetails) {
+ tty->print_cr("reassign fields for object of type %s!", k->name()->as_C_string());
+ }
if (obj.is_null()) {
continue;
}
if (k->oop_is_instance()) {
InstanceKlass* ik = InstanceKlass::cast(k());
- FieldReassigner reassign(fr, reg_map, sv, obj());
- ik->do_nonstatic_fields(&reassign);
+ reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
} else if (k->oop_is_typeArray()) {
TypeArrayKlass* ak = TypeArrayKlass::cast(k());
reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());
@@ -982,13 +1078,13 @@
}
}
#endif
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp());
#ifndef PRODUCT
- if (TraceDeoptimization) {
+ if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
tty->print("DEOPT PACKING thread " INTPTR_FORMAT " ", thread);
fr.print_on(tty);
@@ -1033,7 +1129,7 @@
assert(array->structural_compare(thread, chunk), "just checking");
#ifndef PRODUCT
- if (TraceDeoptimization) {
+ if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
tty->print_cr(" Created vframeArray " INTPTR_FORMAT, array);
}
@@ -1042,7 +1138,7 @@
return array;
}
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
// Reallocation of some scalar replaced objects failed. Record
// that we need to pop all the interpreter frames for the
@@ -1150,17 +1246,38 @@
}
-void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr) {
+void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deoptimization::DeoptReason reason) {
assert(fr.can_be_deoptimized(), "checking frame type");
- gather_statistics(Reason_constraint, Action_none, Bytecodes::_illegal);
+ gather_statistics(reason, Action_none, Bytecodes::_illegal);
+
+ if (LogCompilation && xtty != NULL) {
+ nmethod* nm = fr.cb()->as_nmethod_or_null();
+ assert(nm != NULL, "only compiled methods can deopt");
- // Patch the nmethod so that when execution returns to it we will
+ ttyLocker ttyl;
+ xtty->begin_head("deoptimized thread='" UINTX_FORMAT "'", thread->osthread()->thread_id());
+ nm->log_identity(xtty);
+ xtty->end_head();
+ for (ScopeDesc* sd = nm->scope_desc_at(fr.pc()); ; sd = sd->sender()) {
+ xtty->begin_elem("jvms bci='%d'", sd->bci());
+ xtty->method(sd->method());
+ xtty->end_elem();
+ if (sd->is_top()) break;
+ }
+ xtty->tail("deoptimized");
+ }
+
+ // Patch the compiled method so that when execution returns to it we will
// deopt the execution state and return to the interpreter.
fr.deoptimize(thread);
}
void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map) {
+ deoptimize(thread, fr, map, Reason_constraint);
+}
+
+void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) {
// Deoptimize only if the frame comes from compile code.
// Do not deoptimize the frame which is already patched
// during the execution of the loops below.
@@ -1172,12 +1289,12 @@
if (UseBiasedLocking) {
revoke_biases_of_monitors(thread, fr, map);
}
- deoptimize_single_frame(thread, fr);
+ deoptimize_single_frame(thread, fr, reason);
}
-void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason) {
assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"can only deoptimize other thread at a safepoint");
// Compute frame and register map based on thread and sp.
@@ -1186,19 +1303,22 @@
while (fr.id() != id) {
fr = fr.sender(®_map);
}
- deoptimize(thread, fr, ®_map);
+ deoptimize(thread, fr, ®_map, reason);
}
-void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason) {
if (thread == Thread::current()) {
- Deoptimization::deoptimize_frame_internal(thread, id);
+ Deoptimization::deoptimize_frame_internal(thread, id, reason);
} else {
- VM_DeoptimizeFrame deopt(thread, id);
+ VM_DeoptimizeFrame deopt(thread, id, reason);
VMThread::execute(&deopt);
}
}
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+ deoptimize_frame(thread, id, Reason_constraint);
+}
// JVMTI PopFrame support
JRT_LEAF(void, Deoptimization::popframe_preserve_args(JavaThread* thread, int bytes_to_save, void* start_address))
@@ -1225,7 +1345,7 @@
return mdo;
}
-#if defined(COMPILER2) || defined(SHARK)
+#if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
// in case of an unresolved klass entry, load the class.
if (constant_pool->tag_at(index).is_unresolved_klass()) {
@@ -1288,7 +1408,12 @@
thread->inc_in_deopt_handler();
// We need to update the map if we have biased locking.
+#if INCLUDE_JVMCI
+ // JVMCI might need to get an exception from the stack, which in turn requires the register map to be valid
+ RegisterMap reg_map(thread, true);
+#else
RegisterMap reg_map(thread, UseBiasedLocking);
+#endif
frame stub_frame = thread->last_frame();
frame fr = stub_frame.sender(®_map);
// Make sure the calling nmethod is not getting deoptimized and removed
@@ -1296,8 +1421,8 @@
nmethodLocker nl(fr.pc());
// Log a message
- Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT,
- trap_request, fr.pc());
+ Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT " relative=" INTPTR_FORMAT,
+ trap_request, fr.pc(), fr.pc() - fr.cb()->code_begin());
{
ResourceMark rm;
@@ -1307,6 +1432,9 @@
DeoptReason reason = trap_request_reason(trap_request);
DeoptAction action = trap_request_action(trap_request);
+#if INCLUDE_JVMCI
+ int debug_id = trap_request_debug_id(trap_request);
+#endif
jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1
vframe* vf = vframe::new_vframe(&fr, ®_map, thread);
@@ -1315,10 +1443,71 @@
nmethod* nm = cvf->code();
ScopeDesc* trap_scope = cvf->scope();
+
+ if (TraceDeoptimization) {
+ ttyLocker ttyl;
+ tty->print_cr(" bci=%d pc=" INTPTR_FORMAT ", relative_pc=%d, method=%s" JVMCI_ONLY(", debug_id=%d"), trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name_and_sig_as_C_string()
+#if INCLUDE_JVMCI
+ , debug_id
+#endif
+ );
+ }
+
methodHandle trap_method = trap_scope->method();
int trap_bci = trap_scope->bci();
+#if INCLUDE_JVMCI
+ oop speculation = thread->pending_failed_speculation();
+ if (nm->is_compiled_by_jvmci()) {
+ if (speculation != NULL) {
+ oop speculation_log = nm->speculation_log();
+ if (speculation_log != NULL) {
+ if (TraceDeoptimization || TraceUncollectedSpeculations) {
+ if (SpeculationLog::lastFailed(speculation_log) != NULL) {
+ tty->print_cr("A speculation that was not collected by the compiler is being overwritten");
+ }
+ }
+ if (TraceDeoptimization) {
+ tty->print_cr("Saving speculation to speculation log");
+ }
+ SpeculationLog::set_lastFailed(speculation_log, speculation);
+ } else {
+ if (TraceDeoptimization) {
+ tty->print_cr("Speculation present but no speculation log");
+ }
+ }
+ thread->set_pending_failed_speculation(NULL);
+ } else {
+ if (TraceDeoptimization) {
+ tty->print_cr("No speculation");
+ }
+ }
+ } else {
+ assert(speculation == NULL, "There should not be a speculation for method compiled by non-JVMCI compilers");
+ }
+
+ if (trap_bci == SynchronizationEntryBCI) {
+ trap_bci = 0;
+ thread->set_pending_monitorenter(true);
+ }
+
+ if (reason == Deoptimization::Reason_transfer_to_interpreter) {
+ thread->set_pending_transfer_to_interpreter(true);
+ }
+#endif
+
Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci);
+ if (trap_scope->rethrow_exception()) {
+ if (PrintDeoptimizationDetails) {
+ tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_method->method_holder()->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
+ }
+ GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
+ guarantee(expressions != NULL, "must have exception to throw");
+ ScopeValue* topOfStack = expressions->top();
+ Handle topOfStackObj = StackValue::create_stack_value(&fr, ®_map, topOfStack)->get_obj();
+ THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
+ }
+
// Record this event in the histogram.
gather_statistics(reason, action, trap_bc);
@@ -1326,8 +1515,19 @@
// Need MDO to record RTM code generation state.
bool create_if_missing = ProfileTraps || UseCodeAging RTM_OPT_ONLY( || UseRTMLocking );
+ methodHandle profiled_method;
+#if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci()) {
+ profiled_method = nm->method();
+ } else {
+ profiled_method = trap_method;
+ }
+#else
+ profiled_method = trap_method;
+#endif
+
MethodData* trap_mdo =
- get_method_data(thread, trap_method, create_if_missing);
+ get_method_data(thread, profiled_method, create_if_missing);
// Log a message
Events::log_deopt_message(thread, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d",
@@ -1385,12 +1585,33 @@
if (TraceDeoptimization) { // make noise on the tty
tty->print("Uncommon trap occurred in");
nm->method()->print_short_name(tty);
- tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d",
+ tty->print(" compiler=%s compile_id=%d", nm->compiler() == NULL ? "" : nm->compiler()->name(), nm->compile_id());
+#if INCLUDE_JVMCI
+ oop installedCode = nm->jvmci_installed_code();
+ if (installedCode != NULL) {
+ oop installedCodeName = NULL;
+ if (installedCode->is_a(InstalledCode::klass())) {
+ installedCodeName = InstalledCode::name(installedCode);
+ }
+ if (installedCodeName != NULL) {
+ tty->print(" (JVMCI: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
+ } else {
+ tty->print(" (JVMCI: installed code has no name) ");
+ }
+ } else if (nm->is_compiled_by_jvmci()) {
+ tty->print(" (JVMCI: no installed code) ");
+ }
+#endif
+ tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d" JVMCI_ONLY(" debug_id=%d"),
fr.pc(),
os::current_thread_id(),
trap_reason_name(reason),
trap_action_name(action),
- unloaded_class_index);
+ unloaded_class_index
+#if INCLUDE_JVMCI
+ , debug_id
+#endif
+ );
if (class_name != NULL) {
tty->print(unresolved ? " unresolved class: " : " symbol: ");
class_name->print_symbol_on(tty);
@@ -1524,11 +1745,14 @@
bool inc_recompile_count = false;
ProfileData* pdata = NULL;
if (ProfileTraps && update_trap_state && trap_mdo != NULL) {
- assert(trap_mdo == get_method_data(thread, trap_method, false), "sanity");
+ assert(trap_mdo == get_method_data(thread, profiled_method, false), "sanity");
uint this_trap_count = 0;
bool maybe_prior_trap = false;
bool maybe_prior_recompile = false;
- pdata = query_update_method_data(trap_mdo, trap_bci, reason,
+ pdata = query_update_method_data(trap_mdo, trap_bci, reason, true,
+#if INCLUDE_JVMCI
+ nm->is_compiled_by_jvmci() && nm->is_osr_method(),
+#endif
nm->method(),
//outputs:
this_trap_count,
@@ -1660,26 +1884,42 @@
Deoptimization::query_update_method_data(MethodData* trap_mdo,
int trap_bci,
Deoptimization::DeoptReason reason,
+ bool update_total_trap_count,
+#if INCLUDE_JVMCI
+ bool is_osr,
+#endif
Method* compiled_method,
//outputs:
uint& ret_this_trap_count,
bool& ret_maybe_prior_trap,
bool& ret_maybe_prior_recompile) {
- uint prior_trap_count = trap_mdo->trap_count(reason);
- uint this_trap_count = trap_mdo->inc_trap_count(reason);
+ bool maybe_prior_trap = false;
+ bool maybe_prior_recompile = false;
+ uint this_trap_count = 0;
+ if (update_total_trap_count) {
+ uint idx = reason;
+#if INCLUDE_JVMCI
+ if (is_osr) {
+ idx += Reason_LIMIT;
+ }
+#endif
+ uint prior_trap_count = trap_mdo->trap_count(idx);
+ this_trap_count = trap_mdo->inc_trap_count(idx);
- // If the runtime cannot find a place to store trap history,
- // it is estimated based on the general condition of the method.
- // If the method has ever been recompiled, or has ever incurred
- // a trap with the present reason , then this BCI is assumed
- // (pessimistically) to be the culprit.
- bool maybe_prior_trap = (prior_trap_count != 0);
- bool maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
+ // If the runtime cannot find a place to store trap history,
+ // it is estimated based on the general condition of the method.
+ // If the method has ever been recompiled, or has ever incurred
+ // a trap with the present reason , then this BCI is assumed
+ // (pessimistically) to be the culprit.
+ maybe_prior_trap = (prior_trap_count != 0);
+ maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
+ }
ProfileData* pdata = NULL;
// For reasons which are recorded per bytecode, we check per-BCI data.
DeoptReason per_bc_reason = reason_recorded_per_bytecode_if_any(reason);
+ assert(per_bc_reason != Reason_none || update_total_trap_count, "must be");
if (per_bc_reason != Reason_none) {
// Find the profile data for this BCI. If there isn't one,
// try to allocate one from the MDO's set of spares.
@@ -1732,8 +1972,14 @@
bool ignore_maybe_prior_trap;
bool ignore_maybe_prior_recompile;
assert(!reason_is_speculate(reason), "reason speculate only used by compiler");
+ // JVMCI uses the total counts to determine if deoptimizations are happening too frequently -> do not adjust total counts
+ bool update_total_counts = JVMCI_ONLY(false) NOT_JVMCI(true);
query_update_method_data(trap_mdo, trap_bci,
(DeoptReason)reason,
+ update_total_counts,
+#if INCLUDE_JVMCI
+ false,
+#endif
NULL,
ignore_this_trap_count,
ignore_maybe_prior_trap,
@@ -1741,7 +1987,9 @@
}
Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, jint trap_request) {
-
+ if (TraceDeoptimization) {
+ tty->print("Uncommon trap ");
+ }
// Still in Java no safepoints
{
// This enters VM and may safepoint
@@ -1846,12 +2094,12 @@
// Note: Keep this in sync. with enum DeoptReason.
"none",
"null_check",
- "null_assert",
+ "null_assert" JVMCI_ONLY("_or_unreached0"),
"range_check",
"class_check",
"array_check",
- "intrinsic",
- "bimorphic",
+ "intrinsic" JVMCI_ONLY("_or_type_checked_inlining"),
+ "bimorphic" JVMCI_ONLY("_or_optimized_type_check"),
"unloaded",
"uninitialized",
"unreached",
@@ -1866,6 +2114,13 @@
"rtm_state_change",
"unstable_if",
"unstable_fused_if",
+#if INCLUDE_JVMCI
+ "aliasing",
+ "transfer_to_interpreter",
+ "not_compiled_exception_handler",
+ "unresolved",
+ "jsr_mismatch",
+#endif
"tenured"
};
const char* Deoptimization::_trap_action_name[] = {
@@ -1905,13 +2160,24 @@
jint unloaded_class_index = trap_request_index(trap_request);
const char* reason = trap_reason_name(trap_request_reason(trap_request));
const char* action = trap_action_name(trap_request_action(trap_request));
+#if INCLUDE_JVMCI
+ int debug_id = trap_request_debug_id(trap_request);
+#endif
size_t len;
if (unloaded_class_index < 0) {
- len = jio_snprintf(buf, buflen, "reason='%s' action='%s'",
- reason, action);
+ len = jio_snprintf(buf, buflen, "reason='%s' action='%s'" JVMCI_ONLY(" debug_id='%d'"),
+ reason, action
+#if INCLUDE_JVMCI
+ ,debug_id
+#endif
+ );
} else {
- len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'",
- reason, action, unloaded_class_index);
+ len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'" JVMCI_ONLY(" debug_id='%d'"),
+ reason, action, unloaded_class_index
+#if INCLUDE_JVMCI
+ ,debug_id
+#endif
+ );
}
if (len >= buflen)
buf[buflen-1] = '\0';
@@ -2008,7 +2274,7 @@
if (xtty != NULL) xtty->tail("statistics");
}
}
-#else // COMPILER2 || SHARK
+#else // COMPILER2 || SHARK || INCLUDE_JVMCI
// Stubs for C1 only system.
@@ -2044,4 +2310,4 @@
return buf;
}
-#endif // COMPILER2 || SHARK
+#endif // COMPILER2 || SHARK || INCLUDE_JVMCI
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -41,7 +41,13 @@
enum DeoptReason {
Reason_many = -1, // indicates presence of several reasons
Reason_none = 0, // indicates absence of a relevant deopt.
- // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits
+ // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits.
+ // This is more complicated for JVMCI as JVMCI may deoptimize to *some* bytecode before the
+ // bytecode that actually caused the deopt (with inlining, JVMCI may even deoptimize to a
+ // bytecode in another method):
+ // - bytecode y in method b() causes deopt
+ // - JVMCI deoptimizes to bytecode x in method a()
+ // -> the deopt reason will be recorded for method a() at bytecode x
Reason_null_check, // saw unexpected null or zero divisor (@bci)
Reason_null_assert, // saw unexpected non-null or non-zero (@bci)
Reason_range_check, // saw unexpected array index (@bci)
@@ -50,6 +56,13 @@
Reason_intrinsic, // saw unexpected operand to intrinsic (@bci)
Reason_bimorphic, // saw unexpected object class in bimorphic inlining (@bci)
+#if INCLUDE_JVMCI
+ Reason_unreached0 = Reason_null_assert,
+ Reason_type_checked_inlining = Reason_intrinsic,
+ Reason_optimized_type_check = Reason_bimorphic,
+#endif
+
+ // recorded per method
Reason_unloaded, // unloaded class or constant pool entry
Reason_uninitialized, // bad class state (uninitialized)
Reason_unreached, // code is not reached, compiler
@@ -64,11 +77,19 @@
Reason_rtm_state_change, // rtm state change detected
Reason_unstable_if, // a branch predicted always false was taken
Reason_unstable_fused_if, // fused two ifs that had each one untaken branch. One is now taken.
+#if INCLUDE_JVMCI
+ Reason_aliasing, // optimistic assumption about aliasing failed
+ Reason_transfer_to_interpreter, // explicit transferToInterpreter()
+ Reason_not_compiled_exception_handler,
+ Reason_unresolved,
+ Reason_jsr_mismatch,
+#endif
// Reason_tenured is counted separately, add normal counted Reasons above.
// Related to MethodData::_trap_hist_limit where Reason_tenured isn't included
Reason_tenured, // age of the code has reached the limit
Reason_LIMIT,
+
// Note: Keep this enum in sync. with _trap_reason_name.
Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc
// Note: Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of
@@ -91,8 +112,10 @@
enum {
_action_bits = 3,
_reason_bits = 5,
+ _debug_id_bits = 23,
_action_shift = 0,
_reason_shift = _action_shift+_action_bits,
+ _debug_id_shift = _reason_shift+_reason_bits,
BC_CASE_LIMIT = PRODUCT_ONLY(1) NOT_PRODUCT(4) // for _deoptimization_hist
};
@@ -109,10 +132,11 @@
// Deoptimizes a frame lazily. nmethod gets patched deopt happens on return to the frame
static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map);
+ static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map, DeoptReason reason);
private:
// Does the actual work for deoptimizing a single frame
- static void deoptimize_single_frame(JavaThread* thread, frame fr);
+ static void deoptimize_single_frame(JavaThread* thread, frame fr, DeoptReason reason);
// Helper function to revoke biases of all monitors in frame if UseBiasedLocking
// is enabled
@@ -121,16 +145,18 @@
// executing in a particular CodeBlob if UseBiasedLocking is enabled
static void revoke_biases_of_monitors(CodeBlob* cb);
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
+JVMCI_ONLY(public:)
+
// Support for restoring non-escaping objects
static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
- static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures);
+ static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal);
static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
public:
static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
@@ -140,6 +166,7 @@
// UnrollBlock is returned by fetch_unroll_info() to the deoptimization handler (blob).
// This is only a CheapObj to ease debugging after a deopt failure
class UnrollBlock : public CHeapObj<mtCompiler> {
+ friend class VMStructs;
private:
int _size_of_deoptimized_frame; // Size, in bytes, of current deoptimized frame
int _caller_adjustment; // Adjustment, in bytes, to caller's SP by initial interpreted frame
@@ -243,10 +270,11 @@
// Only called from VMDeoptimizeFrame
// @argument thread. Thread where stub_frame resides.
// @argument id. id of frame that should be deoptimized.
- static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id);
+ static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason);
- // If thread is not the current thread then execute
+ // if thread is not the current thread then execute
// VM_DeoptimizeFrame otherwise deoptimize directly.
+ static void deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason);
static void deoptimize_frame(JavaThread* thread, intptr_t* id);
// Statistics
@@ -276,6 +304,14 @@
// standard action for unloaded CP entry
return _unloaded_action;
}
+ static int trap_request_debug_id(int trap_request) {
+ if (trap_request < 0) {
+ return ((~(trap_request) >> _debug_id_shift) & right_n_bits(_debug_id_bits));
+ } else {
+ // standard action for unloaded CP entry
+ return 0;
+ }
+ }
static int trap_request_index(int trap_request) {
if (trap_request < 0)
return -1;
@@ -374,6 +410,10 @@
static ProfileData* query_update_method_data(MethodData* trap_mdo,
int trap_bci,
DeoptReason reason,
+ bool update_total_trap_count,
+#if INCLUDE_JVMCI
+ bool is_osr,
+#endif
Method* compiled_method,
//outputs:
uint& ret_this_trap_count,
--- a/hotspot/src/share/vm/runtime/frame.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/frame.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -661,9 +661,16 @@
Method* m = nm->method();
if (m != NULL) {
m->name_and_sig_as_C_string(buf, buflen);
- st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]",
+ st->print("J %d%s %s ",
nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
- ((nm->compiler() != NULL) ? nm->compiler()->name() : ""),
+ ((nm->compiler() != NULL) ? nm->compiler()->name() : ""));
+#if INCLUDE_JVMCI
+ char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
+ if (jvmciName != NULL) {
+ st->print(" (%s)", jvmciName);
+ }
+#endif
+ st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]",
buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin());
} else {
st->print("J " PTR_FORMAT, pc());
@@ -1122,7 +1129,9 @@
// make sure we have the right receiver type
}
}
- COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "must be empty before verify");)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ assert(DerivedPointerTable::is_empty(), "must be empty before verify");
+#endif
oops_do_internal(&VerifyOopClosure::verify_oop, NULL, NULL, (RegisterMap*)map, false);
}
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/globals.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -42,6 +42,9 @@
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci_globals.hpp"
+#endif
#ifdef COMPILER2
#include "opto/c2_globals.hpp"
#endif
@@ -441,6 +444,7 @@
};
Data data[] = {
+ { KIND_JVMCI, "JVMCI" },
{ KIND_C1, "C1" },
{ KIND_C2, "C2" },
{ KIND_ARCH, "ARCH" },
@@ -548,6 +552,14 @@
#define RUNTIME_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
#define RUNTIME_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_NOT_PRODUCT) },
+#define JVMCI_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_PRODUCT) },
+#define JVMCI_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) },
+#define JVMCI_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_DEVELOP) },
+#define JVMCI_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
+#define JVMCI_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_DIAGNOSTIC) },
+#define JVMCI_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_EXPERIMENTAL) },
+#define JVMCI_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_NOT_PRODUCT) },
+
#ifdef _LP64
#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_LP64_PRODUCT) },
#else
@@ -616,6 +628,17 @@
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
+ JVMCI_PD_DEVELOP_FLAG_STRUCT, \
+ JVMCI_PRODUCT_FLAG_STRUCT, \
+ JVMCI_PD_PRODUCT_FLAG_STRUCT, \
+ JVMCI_DIAGNOSTIC_FLAG_STRUCT, \
+ JVMCI_EXPERIMENTAL_FLAG_STRUCT, \
+ JVMCI_NOTPRODUCT_FLAG_STRUCT, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+#endif // INCLUDE_JVMCI
#ifdef COMPILER1
C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \
C1_PD_DEVELOP_FLAG_STRUCT, \
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -176,7 +176,7 @@
#endif
#endif
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
define_pd_global(bool, BackgroundCompilation, false);
define_pd_global(bool, UseTLAB, false);
define_pd_global(bool, CICompileOSR, false);
@@ -211,11 +211,11 @@
#define CI_COMPILER_COUNT 0
#else
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
#define CI_COMPILER_COUNT 2
#else
#define CI_COMPILER_COUNT 1
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
#endif // no compilers
@@ -254,6 +254,7 @@
KIND_SHARK = 1 << 15,
KIND_LP64_PRODUCT = 1 << 16,
KIND_COMMERCIAL = 1 << 17,
+ KIND_JVMCI = 1 << 18,
KIND_MASK = ~VALUE_ORIGIN_MASK
};
@@ -1098,9 +1099,15 @@
diagnostic(ccstr, PrintAssemblyOptions, NULL, \
"Print options string passed to disassembler.so") \
\
+ notproduct(bool, PrintNMethodStatistics, false, \
+ "Print a summary statistic for the generated nmethods") \
+ \
diagnostic(bool, PrintNMethods, false, \
"Print assembly code for nmethods when generated") \
\
+ diagnostic(intx, PrintNMethodsAtLevel, -1, \
+ "Only print code for nmethods at the given compilation level") \
+ \
diagnostic(bool, PrintNativeNMethods, false, \
"Print assembly code for native nmethods when generated") \
\
@@ -2825,7 +2832,7 @@
\
develop(bool, CompileTheWorld, false, \
"Compile all methods in all classes in bootstrap class path " \
- "(stress test)") \
+ "(stress test)") \
\
develop(bool, CompileTheWorldPreloadClasses, true, \
"Preload all classes used by a class before start loading") \
@@ -3063,6 +3070,9 @@
develop(bool, TraceDeoptimization, false, \
"Trace deoptimization") \
\
+ develop(bool, PrintDeoptimizationDetails, false, \
+ "Print more information about deoptimization") \
+ \
develop(bool, DebugDeoptimization, false, \
"Tracing various information while debugging deoptimization") \
\
@@ -3209,9 +3219,12 @@
"If non-zero, maximum number of words that malloc/realloc can " \
"allocate (for testing only)") \
\
- product(intx, TypeProfileWidth, 2, \
+ product(intx, TypeProfileWidth, 2, \
"Number of receiver types to record in call/cast profile") \
\
+ experimental(intx, MethodProfileWidth, 0, \
+ "Number of methods to record in call profile") \
+ \
develop(intx, BciProfileWidth, 2, \
"Number of return bci's to record in ret profile") \
\
@@ -3747,7 +3760,7 @@
\
product(intx, Tier3CompileThreshold, 2000, \
"Threshold at which tier 3 compilation is invoked (invocation " \
- "minimum must be satisfied") \
+ "minimum must be satisfied)") \
\
product(intx, Tier3BackEdgeThreshold, 60000, \
"Back edge threshold at which tier 3 OSR compilation is invoked") \
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -44,6 +44,14 @@
#define RUNTIME_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name),
#define RUNTIME_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+#define JVMCI_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+#define JVMCI_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name),
+#define JVMCI_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+#define JVMCI_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name),
+#define JVMCI_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+#define JVMCI_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+#define JVMCI_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
+
#ifdef _LP64
#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name),
#else
@@ -105,6 +113,17 @@
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER, \
+ JVMCI_PD_DEVELOP_FLAG_MEMBER, \
+ JVMCI_PRODUCT_FLAG_MEMBER, \
+ JVMCI_PD_PRODUCT_FLAG_MEMBER, \
+ JVMCI_DIAGNOSTIC_FLAG_MEMBER, \
+ JVMCI_EXPERIMENTAL_FLAG_MEMBER, \
+ JVMCI_NOTPRODUCT_FLAG_MEMBER, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+#endif // INCLUDE_JVMCI
#ifdef COMPILER1
C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, \
C1_PD_DEVELOP_FLAG_MEMBER, \
@@ -151,6 +170,14 @@
#define RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type),
#define RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
+
#define C1_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
#define C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type),
#define C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
@@ -212,6 +239,17 @@
IGNORE_RANGE,
IGNORE_CONSTRAINT)
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
+ JVMCI_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+ IGNORE_RANGE,
+ IGNORE_CONSTRAINT)
+#endif // INCLUDE_JVMCI
#ifdef COMPILER1
C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE,
C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
--- a/hotspot/src/share/vm/runtime/java.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/java.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -31,6 +31,10 @@
#include "compiler/compilerOracle.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "interpreter/bytecodeHistogram.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
#include "memory/oopFactory.hpp"
#include "memory/universe.hpp"
#include "oops/constantPool.hpp"
@@ -236,7 +240,6 @@
Runtime1::print_statistics();
Deoptimization::print_statistics();
SharedRuntime::print_statistics();
- nmethod::print_statistics();
}
#endif /* COMPILER1 */
@@ -246,7 +249,6 @@
Compile::print_statistics();
#ifndef COMPILER1
Deoptimization::print_statistics();
- nmethod::print_statistics();
SharedRuntime::print_statistics();
#endif //COMPILER1
os::print_statistics();
@@ -264,7 +266,21 @@
IndexSet::print_statistics();
}
#endif // ASSERT
-#endif // COMPILER2
+#else
+#ifdef INCLUDE_JVMCI
+#ifndef COMPILER1
+ if ((TraceDeoptimization || LogVMOutput || LogCompilation) && UseCompiler) {
+ FlagSetting fs(DisplayVMOutput, DisplayVMOutput && TraceDeoptimization);
+ Deoptimization::print_statistics();
+ SharedRuntime::print_statistics();
+ }
+#endif
+#endif
+#endif
+
+ if (PrintNMethodStatistics) {
+ nmethod::print_statistics();
+ }
if (CountCompiledCalls) {
print_method_invocation_histogram();
}
@@ -409,6 +425,10 @@
}
}
+#if INCLUDE_JVMCI
+ JVMCIRuntime::shutdown();
+#endif
+
// Hang forever on exit if we're reporting an error.
if (ShowMessageBoxOnError && is_error_reported()) {
os::infinite_sleep();
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -41,6 +41,10 @@
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
// -----------------------------------------------------
// Implementation of JavaCallWrapper
@@ -51,7 +55,7 @@
guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code");
assert(!thread->owns_locks(), "must release all locks when leaving VM");
- guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
+ guarantee(thread->can_call_java(), "cannot make java calls from the native compiler");
_result = result;
// Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub,
@@ -309,19 +313,27 @@
CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
- // Verify the arguments
+#if INCLUDE_JVMCI
+ // Gets the nmethod (if any) that should be called instead of normal target
+ nmethod* alternative_target = args->alternative_target();
+ if (alternative_target == NULL) {
+#endif
+// Verify the arguments
if (CheckJNICalls) {
args->verify(method, result->get_type(), thread);
}
else debug_only(args->verify(method, result->get_type(), thread));
+#if INCLUDE_JVMCI
+ }
+#else
// Ignore call if method is empty
if (method->is_empty_method()) {
assert(result->get_type() == T_VOID, "an empty method must return a void value");
return;
}
-
+#endif
#ifdef ASSERT
{ InstanceKlass* holder = method->method_holder();
@@ -333,7 +345,7 @@
#endif
- assert(!thread->is_Compiler_thread(), "cannot compile from the compiler");
+ assert(thread->can_call_java(), "cannot compile from the native compiler");
if (CompilationPolicy::must_be_compiled(method)) {
CompileBroker::compile_method(method, InvocationEntryBci,
CompilationPolicy::policy()->initial_compile_level(),
@@ -377,6 +389,17 @@
os::bang_stack_shadow_pages();
}
+#if INCLUDE_JVMCI
+ if (alternative_target != NULL) {
+ if (alternative_target->is_alive()) {
+ thread->set_jvmci_alternate_call_target(alternative_target->verified_entry_point());
+ entry_point = method->adapter()->get_i2c_entry();
+ } else {
+ THROW(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+ }
+ }
+#endif
+
// do call
{ JavaCallWrapper link(method, receiver, result, CHECK);
{ HandleMark hm(thread); // HandleMark used by HandleMarkCleaner
--- a/hotspot/src/share/vm/runtime/javaCalls.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -103,6 +103,7 @@
int _size;
int _max_size;
bool _start_at_zero; // Support late setting of receiver
+ JVMCI_ONLY(nmethod* _alternative_target;) // Nmethod that should be called instead of normal target
void initialize() {
// Starts at first element to support set_receiver.
@@ -112,6 +113,7 @@
_max_size = _default_size;
_size = 0;
_start_at_zero = false;
+ JVMCI_ONLY(_alternative_target = NULL;)
}
public:
@@ -133,11 +135,22 @@
_max_size = max_size;
_size = 0;
_start_at_zero = false;
+ JVMCI_ONLY(_alternative_target = NULL;)
} else {
initialize();
}
}
+#if INCLUDE_JVMCI
+ void set_alternative_target(nmethod* target) {
+ _alternative_target = target;
+ }
+
+ nmethod* alternative_target() {
+ return _alternative_target;
+ }
+#endif
+
inline void push_oop(Handle h) { _is_oop[_size] = true;
JNITypes::put_obj((oop)h.raw_value(), _value, _size); }
--- a/hotspot/src/share/vm/runtime/rframe.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/rframe.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -155,7 +155,7 @@
void RFrame::print(const char* kind) {
#ifndef PRODUCT
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
int cnt = top_method()->interpreter_invocation_count();
#else
int cnt = top_method()->invocation_count();
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
@@ -46,6 +47,7 @@
#include "runtime/arguments.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/biasedLocking.hpp"
+#include "runtime/compilationPolicy.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -93,12 +95,13 @@
_resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call");
_resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call");
-#ifdef COMPILER2
- // Vectors are generated only by C2.
- if (is_wide_vector(MaxVectorSize)) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ // Vectors are generated only by C2 and JVMCI.
+ bool support_wide = is_wide_vector(MaxVectorSize);
+ if (support_wide) {
_polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
}
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);
@@ -461,6 +464,12 @@
// Reset method handle flag.
thread->set_is_method_handle_return(false);
+#if INCLUDE_JVMCI
+ // JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear
+ // and other exception handler continuations do not read it
+ thread->set_exception_pc(NULL);
+#endif
+
// The fastest case first
CodeBlob* blob = CodeCache::find_blob(return_address);
nmethod* nm = (blob != NULL) ? blob->as_nmethod_or_null() : NULL;
@@ -526,8 +535,13 @@
assert(((nmethod*)cb)->is_at_poll_or_poll_return(pc),
"safepoint polling: type must be poll");
- assert(((NativeInstruction*)pc)->is_safepoint_poll(),
- "Only polling locations are used for safepoint");
+#ifdef ASSERT
+ if (!((NativeInstruction*)pc)->is_safepoint_poll()) {
+ tty->print_cr("bad pc: " PTR_FORMAT, p2i(pc));
+ Disassembler::decode(cb);
+ fatal("Only polling locations are used for safepoint");
+ }
+#endif
bool at_poll_return = ((nmethod*)cb)->is_at_poll_return(pc);
bool has_wide_vectors = ((nmethod*)cb)->has_wide_vectors();
@@ -617,6 +631,33 @@
assert(nm != NULL, "must exist");
ResourceMark rm;
+#if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci()) {
+ // lookup exception handler for this pc
+ int catch_pco = ret_pc - nm->code_begin();
+ ExceptionHandlerTable table(nm);
+ HandlerTableEntry *t = table.entry_for(catch_pco, -1, 0);
+ if (t != NULL) {
+ return nm->code_begin() + t->pco();
+ } else {
+ // there is no exception handler for this pc => deoptimize
+ nm->make_not_entrant();
+
+ // Use Deoptimization::deoptimize for all of its side-effects:
+ // revoking biases of monitors, gathering traps statistics, logging...
+ // it also patches the return pc but we do not care about that
+ // since we return a continuation to the deopt_blob below.
+ JavaThread* thread = JavaThread::current();
+ RegisterMap reg_map(thread, UseBiasedLocking);
+ frame runtime_frame = thread->last_frame();
+ frame caller_frame = runtime_frame.sender(®_map);
+ Deoptimization::deoptimize(thread, caller_frame, ®_map, Deoptimization::Reason_not_compiled_exception_handler);
+
+ return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+ }
+ }
+#endif // INCLUDE_JVMCI
+
ScopeDesc* sd = nm->scope_desc_at(ret_pc);
// determine handler bci, if any
EXCEPTION_MARK;
@@ -737,6 +778,15 @@
throw_and_post_jvmti_exception(thread, exception);
JRT_END
+#if INCLUDE_JVMCI
+address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) {
+ assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
+ thread->set_jvmci_implicit_exception_pc(pc);
+ thread->set_pending_deoptimization(Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret));
+ return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
+}
+#endif // INCLUDE_JVMCI
+
address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
address pc,
SharedRuntime::ImplicitExceptionKind exception_kind)
@@ -806,8 +856,8 @@
if (!cb->is_nmethod()) {
bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob();
if (!is_in_blob) {
- cb->print();
- fatal(err_msg("exception happened outside interpreter, nmethods and vtable stubs at pc " INTPTR_FORMAT, pc));
+ // Allow normal crash reporting to handle this
+ return NULL;
}
Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc);
// There is no handler here, so we will simply unwind.
@@ -834,7 +884,19 @@
#ifndef PRODUCT
_implicit_null_throws++;
#endif
+#if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci() && nm->pc_desc_at(pc) != NULL) {
+ // If there's no PcDesc then we'll die way down inside of
+ // deopt instead of just getting normal error reporting,
+ // so only go there if it will succeed.
+ return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check);
+ } else {
+#endif // INCLUDE_JVMCI
+ assert (nm->is_nmethod(), "Expect nmethod");
target_pc = nm->continuation_for_implicit_exception(pc);
+#if INCLUDE_JVMCI
+ }
+#endif // INCLUDE_JVMCI
// If there's an unexpected fault, target_pc might be NULL,
// in which case we want to fall through into the normal
// error handling code.
@@ -846,11 +908,19 @@
case IMPLICIT_DIVIDE_BY_ZERO: {
nmethod* nm = CodeCache::find_nmethod(pc);
- guarantee(nm != NULL, "must have containing nmethod for implicit division-by-zero exceptions");
+ guarantee(nm != NULL, "must have containing compiled method for implicit division-by-zero exceptions");
#ifndef PRODUCT
_implicit_div0_throws++;
#endif
+#if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci() && nm->pc_desc_at(pc) != NULL) {
+ return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check);
+ } else {
+#endif // INCLUDE_JVMCI
target_pc = nm->continuation_for_implicit_exception(pc);
+#if INCLUDE_JVMCI
+ }
+#endif // INCLUDE_JVMCI
// If there's an unexpected fault, target_pc might be NULL,
// in which case we want to fall through into the normal
// error handling code.
@@ -862,11 +932,17 @@
assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind");
- // for AbortVMOnException flag
- NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException"));
if (exception_kind == IMPLICIT_NULL) {
+#ifndef PRODUCT
+ // for AbortVMOnException flag
+ Exceptions::debug_check_abort("java.lang.NullPointerException");
+#endif //PRODUCT
Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
} else {
+#ifndef PRODUCT
+ // for AbortVMOnException flag
+ Exceptions::debug_check_abort("java.lang.ArithmeticException");
+#endif //PRODUCT
Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
}
return target_pc;
@@ -916,6 +992,16 @@
JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
assert(obj->is_oop(), "must be a valid oop");
+#if INCLUDE_JVMCI
+ // This removes the requirement for JVMCI compilers to emit code
+ // performing a dynamic check that obj has a finalizer before
+ // calling this routine. There should be no performance impact
+ // for C1 since it emits a dynamic check. C2 and the interpreter
+ // uses other runtime routines for registering finalizers.
+ if (!obj->klass()->has_finalizer()) {
+ return;
+ }
+#endif // INCLUDE_JVMCI
assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
JRT_END
@@ -1157,6 +1243,7 @@
methodHandle callee_method = call_info.selected_method();
assert((!is_virtual && invoke_code == Bytecodes::_invokestatic ) ||
+ (!is_virtual && invoke_code == Bytecodes::_invokespecial) ||
(!is_virtual && invoke_code == Bytecodes::_invokehandle ) ||
(!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
@@ -1367,9 +1454,6 @@
JRT_END
-
-
-
methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, TRAPS) {
ResourceMark rm(thread);
CallInfo call_info;
@@ -1493,6 +1577,8 @@
} else {
// Either clean or megamorphic
}
+ } else {
+ fatal("Unimplemented");
}
} // Release CompiledIC_lock
@@ -1520,6 +1606,10 @@
address pc = caller.pc();
+ // Check for static or virtual call
+ bool is_static_call = false;
+ nmethod* caller_nm = CodeCache::find_nmethod(pc);
+
// Default call_addr is the location of the "basic" call.
// Determine the address of the call we a reresolving. With
// Inline Caches we will always find a recognizable call.
@@ -1549,10 +1639,6 @@
call_addr = ncall->instruction_address();
}
}
-
- // Check for static or virtual call
- bool is_static_call = false;
- nmethod* caller_nm = CodeCache::find_nmethod(pc);
// Make sure nmethod doesn't get deoptimized and removed until
// this is done with it.
// CLEANUP - with lazy deopt shouldn't need this lock
@@ -2567,8 +2653,7 @@
// Perform the work while holding the lock, but perform any printing outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
// See if somebody beat us to it
- nm = method->code();
- if (nm != NULL) {
+ if (method->code() != NULL) {
return;
}
@@ -2810,7 +2895,7 @@
FREE_C_HEAP_ARRAY(intptr_t, buf);
JRT_END
-bool AdapterHandlerLibrary::contains(CodeBlob* b) {
+bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
@@ -2819,7 +2904,7 @@
return false;
}
-void AdapterHandlerLibrary::print_handler_on(outputStream* st, CodeBlob* b) {
+void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -199,6 +199,9 @@
static address continuation_for_implicit_exception(JavaThread* thread,
address faulting_pc,
ImplicitExceptionKind exception_kind);
+#if INCLUDE_JVMCI
+ static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason);
+#endif
// Shared stub locations
static address get_poll_stub(address pc);
@@ -417,6 +420,12 @@
const VMRegPair *regs,
AdapterFingerPrint* fingerprint);
+ static void gen_i2c_adapter(MacroAssembler *_masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs);
+
// OSR support
// OSR_migration_begin will extract the jvm state from an interpreter
@@ -475,6 +484,7 @@
// A compiled caller has just called the interpreter, but compiled code
// exists. Patch the caller so he no longer calls into the interpreter.
static void fixup_callers_callsite(Method* moop, address ret_pc);
+ static bool should_fixup_call_destination(address destination, address entry_point, address caller_pc, Method* moop, CodeBlob* cb);
// Slow-path Locking and Unlocking
static void complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* thread);
@@ -673,9 +683,9 @@
static void create_native_wrapper(methodHandle method);
static AdapterHandlerEntry* get_adapter(methodHandle method);
- static void print_handler(CodeBlob* b) { print_handler_on(tty, b); }
- static void print_handler_on(outputStream* st, CodeBlob* b);
- static bool contains(CodeBlob* b);
+ static void print_handler(const CodeBlob* b) { print_handler_on(tty, b); }
+ static void print_handler_on(outputStream* st, const CodeBlob* b);
+ static bool contains(const CodeBlob* b);
#ifndef PRODUCT
static void print_statistics();
#endif // PRODUCT
--- a/hotspot/src/share/vm/runtime/sweeper.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sweeper.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -27,7 +27,9 @@
class WhiteBox;
+#include "code/codeCache.hpp"
#include "utilities/ticks.hpp"
+
// An NmethodSweeper is an incremental cleaner for:
// - cleanup inline caches
// - reclamation of nmethods
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -99,6 +99,10 @@
#include "gc/g1/concurrentMarkThread.inline.hpp"
#include "gc/parallel/pcTasks.hpp"
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
@@ -1386,6 +1390,33 @@
// ======= JavaThread ========
+#if INCLUDE_JVMCI
+
+jlong* JavaThread::_jvmci_old_thread_counters;
+
+bool jvmci_counters_include(JavaThread* thread) {
+ oop threadObj = thread->threadObj();
+ return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
+}
+
+void JavaThread::collect_counters(typeArrayOop array) {
+ if (JVMCICounterSize > 0) {
+ MutexLocker tl(Threads_lock);
+ for (int i = 0; i < array->length(); i++) {
+ array->long_at_put(i, _jvmci_old_thread_counters[i]);
+ }
+ for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
+ if (jvmci_counters_include(tp)) {
+ for (int i = 0; i < array->length(); i++) {
+ array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]);
+ }
+ }
+ }
+ }
+}
+
+#endif // INCLUDE_JVMCI
+
// A JavaThread is a normal Java thread
void JavaThread::initialize() {
@@ -1418,6 +1449,20 @@
_in_deopt_handler = 0;
_doing_unsafe_access = false;
_stack_guard_state = stack_guard_unused;
+#if INCLUDE_JVMCI
+ _pending_monitorenter = false;
+ _pending_deoptimization = -1;
+ _pending_failed_speculation = NULL;
+ _pending_transfer_to_interpreter = false;
+ _jvmci._alternate_call_target = NULL;
+ assert(_jvmci._implicit_exception_pc == NULL, "must be");
+ if (JVMCICounterSize > 0) {
+ _jvmci_counters = NEW_C_HEAP_ARRAY(jlong, JVMCICounterSize, mtInternal);
+ memset(_jvmci_counters, 0, sizeof(jlong) * JVMCICounterSize);
+ } else {
+ _jvmci_counters = NULL;
+ }
+#endif // INCLUDE_JVMCI
(void)const_cast<oop&>(_exception_oop = oop(NULL));
_exception_pc = 0;
_exception_handler_pc = 0;
@@ -1592,6 +1637,17 @@
ThreadSafepointState::destroy(this);
if (_thread_profiler != NULL) delete _thread_profiler;
if (_thread_stat != NULL) delete _thread_stat;
+
+#if INCLUDE_JVMCI
+ if (JVMCICounterSize > 0) {
+ if (jvmci_counters_include(this)) {
+ for (int i = 0; i < JVMCICounterSize; i++) {
+ _jvmci_old_thread_counters[i] += _jvmci_counters[i];
+ }
+ }
+ FREE_C_HEAP_ARRAY(jlong, _jvmci_counters);
+ }
+#endif // INCLUDE_JVMCI
}
@@ -2135,7 +2191,7 @@
// Do not throw asynchronous exceptions against the compiler thread
// (the compiler thread should not be a Java thread -- fix in 1.4.2)
- if (is_Compiler_thread()) return;
+ if (!can_call_java()) return;
{
// Actually throw the Throwable against the target Thread - however
@@ -2614,12 +2670,6 @@
StackFrameStream fst(this, UseBiasedLocking);
for (; !fst.is_done(); fst.next()) {
if (fst.current()->should_be_deoptimized()) {
- if (LogCompilation && xtty != NULL) {
- nmethod* nm = fst.current()->cb()->as_nmethod_or_null();
- xtty->elem("deoptimized thread='" UINTX_FORMAT "' compile_id='%d'",
- this->name(), nm != NULL ? nm->compile_id() : -1);
- }
-
Deoptimization::deoptimize(this, *fst.current(), fst.register_map());
}
}
@@ -2658,6 +2708,8 @@
// Traverse the GCHandles
Thread::oops_do(f, cld_f, cf);
+ JVMCI_ONLY(f->do_oop((oop*)&_pending_failed_speculation);)
+
assert((!has_last_Java_frame() && java_call_counter() == 0) ||
(has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
@@ -3175,6 +3227,10 @@
#endif
}
+bool CompilerThread::can_call_java() const {
+ return _compiler != NULL && _compiler->is_jvmci();
+}
+
// Create sweeper thread
CodeCacheSweeperThread::CodeCacheSweeperThread()
: JavaThread(&sweeper_thread_entry) {
@@ -3380,6 +3436,15 @@
// Initialize global data structures and create system classes in heap
vm_init_globals();
+#if INCLUDE_JVMCI
+ if (JVMCICounterSize > 0) {
+ JavaThread::_jvmci_old_thread_counters = NEW_C_HEAP_ARRAY(jlong, JVMCICounterSize, mtInternal);
+ memset(JavaThread::_jvmci_old_thread_counters, 0, sizeof(jlong) * JVMCICounterSize);
+ } else {
+ JavaThread::_jvmci_old_thread_counters = NULL;
+ }
+#endif // INCLUDE_JVMCI
+
// Attach the main thread to this os thread
JavaThread* main_thread = new JavaThread();
main_thread->set_thread_state(_thread_in_vm);
@@ -3506,7 +3571,7 @@
// Note that we do not use CHECK_0 here since we are inside an EXCEPTION_MARK and
// set_init_completed has just been called, causing exceptions not to be shortcut
// anymore. We call vm_exit_during_initialization directly instead.
- SystemDictionary::compute_java_system_loader(CHECK_JNI_ERR);
+ SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
#if INCLUDE_ALL_GCS
// Support for ConcurrentMarkSweep. This should be cleaned up
@@ -3554,8 +3619,17 @@
Chunk::start_chunk_pool_cleaner_task();
}
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ const char* jvmciCompiler = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.compiler");
+ if (jvmciCompiler != NULL) {
+ JVMCIRuntime::save_compiler(jvmciCompiler);
+ }
+ }
+#endif // INCLUDE_JVMCI
+
// initialize compiler(s)
-#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK)
+#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
CompileBroker::compilation_init();
#endif
@@ -3963,6 +4037,12 @@
delete thread;
+#if INCLUDE_JVMCI
+ if (JVMCICounterSize > 0) {
+ FREE_C_HEAP_ARRAY(jlong, JavaThread::_jvmci_old_thread_counters);
+ }
+#endif
+
// exit_globals() will delete tty
exit_globals();
@@ -4179,7 +4259,7 @@
{
MutexLockerEx ml(doLock ? Threads_lock : NULL);
ALL_JAVA_THREADS(p) {
- if (p->is_Compiler_thread()) continue;
+ if (!p->can_call_java()) continue;
address pending = (address)p->current_pending_monitor();
if (pending == monitor) { // found a match
@@ -4236,7 +4316,7 @@
void Threads::print_on(outputStream* st, bool print_stacks,
bool internal_format, bool print_concurrent_locks) {
char buf[32];
- st->print_cr("%s", os::local_time_string(buf, sizeof(buf)));
+ st->print_raw_cr(os::local_time_string(buf, sizeof(buf)));
st->print_cr("Full thread dump %s (%s %s):",
Abstract_VM_Version::vm_name(),
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -329,6 +329,9 @@
virtual bool is_Named_thread() const { return false; }
virtual bool is_Worker_thread() const { return false; }
+ // Can this thread make Java upcalls
+ virtual bool can_call_java() const { return false; }
+
// Casts
virtual WorkerThread* as_Worker_thread() const { return NULL; }
@@ -900,6 +903,43 @@
private:
+#if INCLUDE_JVMCI
+ // The _pending_* fields below are used to communicate extra information
+ // from an uncommon trap in JVMCI compiled code to the uncommon trap handler.
+
+ // Communicates the DeoptReason and DeoptAction of the uncommon trap
+ int _pending_deoptimization;
+
+ // Specifies whether the uncommon trap is to bci 0 of a synchronized method
+ // before the monitor has been acquired.
+ bool _pending_monitorenter;
+
+ // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter
+ bool _pending_transfer_to_interpreter;
+
+ // An object that JVMCI compiled code can use to further describe and
+ // uniquely identify the speculative optimization guarded by the uncommon trap
+ oop _pending_failed_speculation;
+
+ // These fields are mutually exclusive in terms of live ranges.
+ union {
+ // Communicates the pc at which the most recent implicit exception occurred
+ // from the signal handler to a deoptimization stub.
+ address _implicit_exception_pc;
+
+ // Communicates an alternative call target to an i2c stub from a JavaCall .
+ address _alternate_call_target;
+ } _jvmci;
+
+ // Support for high precision, thread sensitive counters in JVMCI compiled code.
+ jlong* _jvmci_counters;
+
+ public:
+ static jlong* _jvmci_old_thread_counters;
+ static void collect_counters(typeArrayOop array);
+ private:
+#endif // INCLUDE_JVMCI
+
StackGuardState _stack_guard_state;
// Precompute the limit of the stack as used in stack overflow checks.
@@ -914,6 +954,7 @@
volatile address _exception_handler_pc; // PC for handler of exception
volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site.
+ private:
// support for JNI critical regions
jint _jni_active_critical; // count of entries into JNI critical region
@@ -1001,6 +1042,7 @@
// Testers
virtual bool is_Java_thread() const { return true; }
+ virtual bool can_call_java() const { return true; }
// Thread chain operations
JavaThread* next() const { return _next; }
@@ -1259,6 +1301,18 @@
MemRegion deferred_card_mark() const { return _deferred_card_mark; }
void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; }
+#if INCLUDE_JVMCI
+ int pending_deoptimization() const { return _pending_deoptimization; }
+ oop pending_failed_speculation() const { return _pending_failed_speculation; }
+ bool has_pending_monitorenter() const { return _pending_monitorenter; }
+ void set_pending_monitorenter(bool b) { _pending_monitorenter = b; }
+ void set_pending_deoptimization(int reason) { _pending_deoptimization = reason; }
+ void set_pending_failed_speculation(oop failed_speculation) { _pending_failed_speculation = failed_speculation; }
+ void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; }
+ void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == NULL, "must be"); _jvmci._alternate_call_target = a; }
+ void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == NULL, "must be"); _jvmci._implicit_exception_pc = a; }
+#endif // INCLUDE_JVMCI
+
// Exception handling for compiled methods
oop exception_oop() const { return _exception_oop; }
address exception_pc() const { return _exception_pc; }
@@ -1359,6 +1413,14 @@
static ByteSize thread_state_offset() { return byte_offset_of(JavaThread, _thread_state); }
static ByteSize saved_exception_pc_offset() { return byte_offset_of(JavaThread, _saved_exception_pc); }
static ByteSize osthread_offset() { return byte_offset_of(JavaThread, _osthread); }
+#if INCLUDE_JVMCI
+ static ByteSize pending_deoptimization_offset() { return byte_offset_of(JavaThread, _pending_deoptimization); }
+ static ByteSize pending_monitorenter_offset() { return byte_offset_of(JavaThread, _pending_monitorenter); }
+ static ByteSize pending_failed_speculation_offset() { return byte_offset_of(JavaThread, _pending_failed_speculation); }
+ static ByteSize jvmci_alternate_call_target_offset() { return byte_offset_of(JavaThread, _jvmci._alternate_call_target); }
+ static ByteSize jvmci_implicit_exception_pc_offset() { return byte_offset_of(JavaThread, _jvmci._implicit_exception_pc); }
+ static ByteSize jvmci_counters_offset() { return byte_offset_of(JavaThread, _jvmci_counters); }
+#endif // INCLUDE_JVMCI
static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop); }
static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc); }
static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); }
@@ -1828,8 +1890,11 @@
CompilerThread(CompileQueue* queue, CompilerCounters* counters);
bool is_Compiler_thread() const { return true; }
- // Hide this compiler thread from external view.
- bool is_hidden_from_external_view() const { return true; }
+
+ virtual bool can_call_java() const;
+
+ // Hide native compiler threads from external view.
+ bool is_hidden_from_external_view() const { return !can_call_java(); }
void set_compiler(AbstractCompiler* c) { _compiler = c; }
AbstractCompiler* compiler() const { return _compiler; }
--- a/hotspot/src/share/vm/runtime/timer.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/timer.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -36,6 +36,22 @@
return counter_to_seconds(counter) * 1000.0;
}
+elapsedTimer::elapsedTimer(jlong time, jlong timeUnitsPerSecond) {
+ _active = false;
+ jlong osTimeUnitsPerSecond = os::elapsed_frequency();
+ assert(osTimeUnitsPerSecond % 1000 == 0, "must be");
+ assert(timeUnitsPerSecond % 1000 == 0, "must be");
+ while (osTimeUnitsPerSecond < timeUnitsPerSecond) {
+ timeUnitsPerSecond /= 1000;
+ time *= 1000;
+ }
+ while (osTimeUnitsPerSecond > timeUnitsPerSecond) {
+ timeUnitsPerSecond *= 1000;
+ time /= 1000;
+ }
+ _counter = time;
+}
+
void elapsedTimer::add(elapsedTimer t) {
_counter += t._counter;
}
--- a/hotspot/src/share/vm/runtime/timer.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/timer.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -37,6 +37,7 @@
bool _active;
public:
elapsedTimer() { _active = false; reset(); }
+ elapsedTimer(jlong time, jlong timeUnitsPerSecond);
void add(elapsedTimer t);
void start();
void stop();
--- a/hotspot/src/share/vm/runtime/vframe.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -400,7 +400,7 @@
InterpreterOopMap oop_mask;
// oopmap for current bci
- if (TraceDeoptimization && Verbose) {
+ if ((TraceDeoptimization && Verbose) JVMCI_ONLY( || PrintDeoptimizationDetails)) {
methodHandle m_h(Thread::current(), method());
OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
} else {
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -294,7 +294,7 @@
_frame.patch_pc(thread, pc);
- assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
+ assert (!method()->is_synchronized() || locks > 0 || _removed_monitors || raw_bci() == SynchronizationEntryBCI, "synchronized methods must have monitors");
BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
for (int index = 0; index < locks; index++) {
@@ -317,6 +317,10 @@
}
}
+ if (PrintDeoptimizationDetails) {
+ tty->print_cr("Expressions size: %d", expressions()->size());
+ }
+
// Unpack expression stack
// If this is an intermediate frame (i.e. not top frame) then this
// only unpacks the part of the expression stack not used by callee
@@ -329,9 +333,26 @@
switch(value->type()) {
case T_INT:
*addr = value->get_int();
+#ifndef PRODUCT
+ if (PrintDeoptimizationDetails) {
+ tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr));
+ }
+#endif
break;
case T_OBJECT:
*addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+ if (PrintDeoptimizationDetails) {
+ tty->print("Reconstructed expression %d (OBJECT): ", i);
+ oop o = (oop)(address)(*addr);
+ if (o == NULL) {
+ tty->print_cr("NULL");
+ } else {
+ ResourceMark rm;
+ tty->print_raw_cr(o->klass()->name()->as_C_string());
+ }
+ }
+#endif
break;
case T_CONFLICT:
// A dead stack slot. Initialize to null in case it is an oop.
@@ -350,9 +371,26 @@
switch(value->type()) {
case T_INT:
*addr = value->get_int();
+#ifndef PRODUCT
+ if (PrintDeoptimizationDetails) {
+ tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr));
+ }
+#endif
break;
case T_OBJECT:
*addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+ if (PrintDeoptimizationDetails) {
+ tty->print("Reconstructed local %d (OBJECT): ", i);
+ oop o = (oop)(address)(*addr);
+ if (o == NULL) {
+ tty->print_cr("NULL");
+ } else {
+ ResourceMark rm;
+ tty->print_raw_cr(o->klass()->name()->as_C_string());
+ }
+ }
+#endif
break;
case T_CONFLICT:
// A dead location. If it is an oop then we need a NULL to prevent GC from following it
@@ -394,7 +432,7 @@
}
#ifndef PRODUCT
- if (TraceDeoptimization && Verbose) {
+ if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
tty->print_cr("[%d Interpreted Frame]", ++unpack_counter);
iframe()->print_on(tty);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -107,6 +107,22 @@
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp"
+#ifdef TARGET_OS_FAMILY_linux
+# include "vmStructs_linux.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_solaris
+# include "vmStructs_solaris.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_windows
+# include "vmStructs_windows.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_aix
+# include "vmStructs_aix.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "vmStructs_bsd.hpp"
+#endif
+
#ifdef TARGET_ARCH_x86
# include "vmStructs_x86.hpp"
#endif
@@ -125,6 +141,7 @@
#ifdef TARGET_ARCH_aarch64
# include "vmStructs_aarch64.hpp"
#endif
+
#ifdef TARGET_OS_ARCH_linux_x86
# include "vmStructs_linux_x86.hpp"
#endif
@@ -161,6 +178,7 @@
#ifdef TARGET_OS_ARCH_bsd_zero
# include "vmStructs_bsd_zero.hpp"
#endif
+
#if INCLUDE_ALL_GCS
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.hpp"
@@ -178,6 +196,10 @@
#include "gc/parallel/vmStructs_parallelgc.hpp"
#endif // INCLUDE_ALL_GCS
+#if INCLUDE_JVMCI
+# include "jvmci/vmStructs_jvmci.hpp"
+#endif
+
#if INCLUDE_TRACE
#include "runtime/vmStructs_trace.hpp"
#endif
@@ -311,6 +333,7 @@
nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
nonstatic_field(InstanceKlass, _nonstatic_oop_map_size, int) \
nonstatic_field(InstanceKlass, _is_marked_dependent, bool) \
+ nonstatic_field(InstanceKlass, _misc_flags, u2) \
nonstatic_field(InstanceKlass, _minor_version, u2) \
nonstatic_field(InstanceKlass, _major_version, u2) \
nonstatic_field(InstanceKlass, _init_state, u1) \
@@ -384,6 +407,7 @@
nonstatic_field(Method, _vtable_index, int) \
nonstatic_field(Method, _method_size, u2) \
nonstatic_field(Method, _intrinsic_id, u2) \
+ nonstatic_field(Method, _flags, u1) \
nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \
volatile_nonstatic_field(Method, _code, nmethod*) \
nonstatic_field(Method, _i2i_entry, address) \
@@ -408,6 +432,7 @@
nonstatic_field(Symbol, _identity_hash, short) \
nonstatic_field(Symbol, _length, unsigned short) \
unchecked_nonstatic_field(Symbol, _body, sizeof(jbyte)) /* NOTE: no type */ \
+ nonstatic_field(Symbol, _body[0], jbyte) \
nonstatic_field(TypeArrayKlass, _max_length, int) \
\
/***********************/ \
@@ -470,6 +495,8 @@
static_field(Universe, _bootstrapping, bool) \
static_field(Universe, _fully_initialized, bool) \
static_field(Universe, _verify_count, int) \
+ static_field(Universe, _verify_oop_mask, uintptr_t) \
+ static_field(Universe, _verify_oop_bits, uintptr_t) \
static_field(Universe, _non_oop_bits, intptr_t) \
static_field(Universe, _narrow_oop._base, address) \
static_field(Universe, _narrow_oop._shift, int) \
@@ -489,6 +516,10 @@
\
unchecked_nonstatic_field(ageTable, sizes, sizeof(ageTable::sizes)) \
\
+ nonstatic_field(BarrierSet, _fake_rtti, BarrierSet::FakeRtti) \
+ \
+ nonstatic_field(BarrierSet::FakeRtti, _concrete_tag, BarrierSet::Name) \
+ \
nonstatic_field(BlockOffsetTable, _bottom, HeapWord*) \
nonstatic_field(BlockOffsetTable, _end, HeapWord*) \
\
@@ -578,6 +609,7 @@
nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \
+ nonstatic_field(ThreadLocalAllocBuffer, _pf_top, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _desired_size, size_t) \
nonstatic_field(ThreadLocalAllocBuffer, _refill_waste_limit, size_t) \
static_field(ThreadLocalAllocBuffer, _target_refills, unsigned) \
@@ -787,6 +819,8 @@
/********************************/ \
\
static_field(CodeCache, _heaps, GrowableArray<CodeHeap*>*) \
+ static_field(CodeCache, _low_bound, address) \
+ static_field(CodeCache, _high_bound, address) \
static_field(CodeCache, _scavenge_root_nmethods, nmethod*) \
\
/*******************************/ \
@@ -838,12 +872,42 @@
static_field(StubRoutines, _squareToLen, address) \
static_field(StubRoutines, _mulAdd, address) \
static_field(StubRoutines, _dexp, address) \
+ static_field(StubRoutines, _jbyte_arraycopy, address) \
+ static_field(StubRoutines, _jshort_arraycopy, address) \
+ static_field(StubRoutines, _jint_arraycopy, address) \
+ static_field(StubRoutines, _jlong_arraycopy, address) \
+ static_field(StubRoutines, _oop_arraycopy, address) \
+ static_field(StubRoutines, _oop_arraycopy_uninit, address) \
+ static_field(StubRoutines, _jbyte_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _jshort_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _jint_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _jlong_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _oop_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _oop_disjoint_arraycopy_uninit, address) \
+ static_field(StubRoutines, _arrayof_jbyte_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jshort_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jlong_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_oop_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_oop_arraycopy_uninit, address) \
+ static_field(StubRoutines, _arrayof_jbyte_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jshort_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jint_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_jlong_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_oop_disjoint_arraycopy, address) \
+ static_field(StubRoutines, _arrayof_oop_disjoint_arraycopy_uninit, address) \
+ static_field(StubRoutines, _checkcast_arraycopy, address) \
+ static_field(StubRoutines, _checkcast_arraycopy_uninit, address) \
+ static_field(StubRoutines, _unsafe_arraycopy, address) \
+ static_field(StubRoutines, _generic_arraycopy, address) \
\
/*****************/ \
/* SharedRuntime */ \
/*****************/ \
\
+ static_field(SharedRuntime, _wrong_method_blob, RuntimeStub*) \
static_field(SharedRuntime, _ic_miss_blob, RuntimeStub*) \
+ static_field(SharedRuntime, _deopt_blob, DeoptimizationBlob*) \
\
/***************************************/ \
/* PcDesc and other compiled code info */ \
@@ -858,16 +922,18 @@
/* CodeBlobs (NOTE: incomplete, but only a little) */ \
/***************************************************/ \
\
- nonstatic_field(CodeBlob, _name, const char*) \
- nonstatic_field(CodeBlob, _size, int) \
- nonstatic_field(CodeBlob, _header_size, int) \
- nonstatic_field(CodeBlob, _relocation_size, int) \
- nonstatic_field(CodeBlob, _content_offset, int) \
- nonstatic_field(CodeBlob, _code_offset, int) \
- nonstatic_field(CodeBlob, _frame_complete_offset, int) \
- nonstatic_field(CodeBlob, _data_offset, int) \
- nonstatic_field(CodeBlob, _frame_size, int) \
- nonstatic_field(CodeBlob, _oop_maps, ImmutableOopMapSet*) \
+ nonstatic_field(CodeBlob, _name, const char*) \
+ nonstatic_field(CodeBlob, _size, int) \
+ nonstatic_field(CodeBlob, _header_size, int) \
+ nonstatic_field(CodeBlob, _relocation_size, int) \
+ nonstatic_field(CodeBlob, _content_offset, int) \
+ nonstatic_field(CodeBlob, _code_offset, int) \
+ nonstatic_field(CodeBlob, _frame_complete_offset, int) \
+ nonstatic_field(CodeBlob, _data_offset, int) \
+ nonstatic_field(CodeBlob, _frame_size, int) \
+ nonstatic_field(CodeBlob, _oop_maps, ImmutableOopMapSet*) \
+ \
+ nonstatic_field(DeoptimizationBlob, _unpack_offset, int) \
\
nonstatic_field(RuntimeStub, _caller_must_gc_arguments, bool) \
\
@@ -907,6 +973,17 @@
\
unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \
\
+ nonstatic_field(Deoptimization::UnrollBlock, _size_of_deoptimized_frame, int) \
+ nonstatic_field(Deoptimization::UnrollBlock, _caller_adjustment, int) \
+ nonstatic_field(Deoptimization::UnrollBlock, _number_of_frames, int) \
+ nonstatic_field(Deoptimization::UnrollBlock, _total_frame_sizes, int) \
+ nonstatic_field(Deoptimization::UnrollBlock, _frame_sizes, intptr_t*) \
+ nonstatic_field(Deoptimization::UnrollBlock, _frame_pcs, address*) \
+ nonstatic_field(Deoptimization::UnrollBlock, _register_block, intptr_t*) \
+ nonstatic_field(Deoptimization::UnrollBlock, _return_type, BasicType) \
+ nonstatic_field(Deoptimization::UnrollBlock, _initial_info, intptr_t) \
+ nonstatic_field(Deoptimization::UnrollBlock, _caller_actual_parameters, int) \
+ \
/********************************/ \
/* JavaCalls (NOTE: incomplete) */ \
/********************************/ \
@@ -1296,6 +1373,7 @@
nonstatic_field(CompileTask, _osr_bci, int) \
nonstatic_field(CompileTask, _comp_level, int) \
nonstatic_field(CompileTask, _compile_id, uint) \
+ nonstatic_field(CompileTask, _num_inlined_bytecodes, int) \
nonstatic_field(CompileTask, _next, CompileTask*) \
nonstatic_field(CompileTask, _prev, CompileTask*) \
\
@@ -1475,6 +1553,8 @@
declare_type(MethodCounters, MetaspaceObj) \
declare_type(ConstMethod, MetaspaceObj) \
\
+ declare_toplevel_type(narrowKlass) \
+ \
declare_toplevel_type(vtableEntry) \
\
declare_toplevel_type(Symbol) \
@@ -1574,6 +1654,8 @@
declare_toplevel_type(TenuredGeneration*) \
declare_toplevel_type(ThreadLocalAllocBuffer*) \
\
+ declare_toplevel_type(BarrierSet::FakeRtti) \
+ \
/************************/ \
/* PerfMemory - jvmstat */ \
/************************/ \
@@ -1696,6 +1778,7 @@
declare_toplevel_type(Dependencies) \
declare_toplevel_type(CompileTask) \
declare_toplevel_type(Deoptimization) \
+ declare_toplevel_type(Deoptimization::UnrollBlock) \
\
/************************/ \
/* OopMap and OopMapSet */ \
@@ -2277,6 +2360,8 @@
\
declare_constant(CardTableRS::youngergen_card) \
\
+ declare_constant(G1SATBCardTableModRefBS::g1_young_gen) \
+ \
declare_constant(CollectedHeap::GenCollectedHeap) \
declare_constant(CollectedHeap::ParallelScavengeHeap) \
declare_constant(CollectedHeap::G1CollectedHeap) \
@@ -2335,6 +2420,36 @@
declare_constant(JVM_ACC_PROMOTED_FLAGS) \
declare_constant(JVM_ACC_FIELD_ACCESS_WATCHED) \
declare_constant(JVM_ACC_FIELD_MODIFICATION_WATCHED) \
+ declare_constant(JVM_ACC_FIELD_INTERNAL) \
+ declare_constant(JVM_ACC_FIELD_STABLE) \
+ declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) \
+ \
+ declare_constant(JVM_CONSTANT_Utf8) \
+ declare_constant(JVM_CONSTANT_Unicode) \
+ declare_constant(JVM_CONSTANT_Integer) \
+ declare_constant(JVM_CONSTANT_Float) \
+ declare_constant(JVM_CONSTANT_Long) \
+ declare_constant(JVM_CONSTANT_Double) \
+ declare_constant(JVM_CONSTANT_Class) \
+ declare_constant(JVM_CONSTANT_String) \
+ declare_constant(JVM_CONSTANT_Fieldref) \
+ declare_constant(JVM_CONSTANT_Methodref) \
+ declare_constant(JVM_CONSTANT_InterfaceMethodref) \
+ declare_constant(JVM_CONSTANT_NameAndType) \
+ declare_constant(JVM_CONSTANT_MethodHandle) \
+ declare_constant(JVM_CONSTANT_MethodType) \
+ declare_constant(JVM_CONSTANT_InvokeDynamic) \
+ declare_constant(JVM_CONSTANT_ExternalMax) \
+ \
+ declare_constant(JVM_CONSTANT_Invalid) \
+ declare_constant(JVM_CONSTANT_InternalMin) \
+ declare_constant(JVM_CONSTANT_UnresolvedClass) \
+ declare_constant(JVM_CONSTANT_ClassIndex) \
+ declare_constant(JVM_CONSTANT_StringIndex) \
+ declare_constant(JVM_CONSTANT_UnresolvedClassInError) \
+ declare_constant(JVM_CONSTANT_MethodHandleInError) \
+ declare_constant(JVM_CONSTANT_MethodTypeInError) \
+ declare_constant(JVM_CONSTANT_InternalMax) \
\
/*****************************/ \
/* Thread::SuspendFlags enum */ \
@@ -2365,6 +2480,7 @@
/******************************/ \
\
declare_constant(Klass::_primary_super_limit) \
+ declare_constant(Klass::_lh_neutral_value) \
declare_constant(Klass::_lh_instance_slow_path_bit) \
declare_constant(Klass::_lh_log2_element_size_shift) \
declare_constant(Klass::_lh_log2_element_size_mask) \
@@ -2386,6 +2502,10 @@
declare_constant(Method::_dont_inline) \
declare_constant(Method::_hidden) \
\
+ declare_constant(Method::nonvirtual_vtable_index) \
+ \
+ declare_constant(Method::extra_stack_entries_for_jsr292) \
+ \
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_checked_exceptions) \
declare_constant(ConstMethod::_has_localvariable_table) \
@@ -2402,6 +2522,20 @@
/**************/ \
\
declare_constant(DataLayout::cell_size) \
+ declare_constant(DataLayout::no_tag) \
+ declare_constant(DataLayout::bit_data_tag) \
+ declare_constant(DataLayout::counter_data_tag) \
+ declare_constant(DataLayout::jump_data_tag) \
+ declare_constant(DataLayout::receiver_type_data_tag) \
+ declare_constant(DataLayout::virtual_call_data_tag) \
+ declare_constant(DataLayout::ret_data_tag) \
+ declare_constant(DataLayout::branch_data_tag) \
+ declare_constant(DataLayout::multi_branch_data_tag) \
+ declare_constant(DataLayout::arg_info_data_tag) \
+ declare_constant(DataLayout::call_type_data_tag) \
+ declare_constant(DataLayout::virtual_call_type_data_tag) \
+ declare_constant(DataLayout::parameters_type_data_tag) \
+ declare_constant(DataLayout::speculative_trap_data_tag) \
\
/*************************************/ \
/* InstanceKlass enum */ \
@@ -2455,13 +2589,14 @@
\
declare_constant(Symbol::max_symbol_length) \
\
- /*************************************************/ \
- /* ConstantPool* layout enum for InvokeDynamic */ \
- /*************************************************/ \
+ /***********************************************/ \
+ /* ConstantPool* layout enum for InvokeDynamic */ \
+ /***********************************************/ \
\
- declare_constant(ConstantPool::_indy_bsm_offset) \
- declare_constant(ConstantPool::_indy_argc_offset) \
- declare_constant(ConstantPool::_indy_argv_offset) \
+ declare_constant(ConstantPool::_indy_bsm_offset) \
+ declare_constant(ConstantPool::_indy_argc_offset) \
+ declare_constant(ConstantPool::_indy_argv_offset) \
+ declare_constant(ConstantPool::CPCACHE_INDEX_TAG) \
\
/********************************/ \
/* ConstantPoolCacheEntry enums */ \
@@ -2556,6 +2691,18 @@
\
declare_constant(DEFAULT_CACHE_LINE_SIZE) \
\
+ declare_constant(Deoptimization::Unpack_deopt) \
+ declare_constant(Deoptimization::Unpack_exception) \
+ declare_constant(Deoptimization::Unpack_uncommon_trap) \
+ declare_constant(Deoptimization::Unpack_reexecute) \
+ \
+ declare_constant(Deoptimization::_action_bits) \
+ declare_constant(Deoptimization::_reason_bits) \
+ declare_constant(Deoptimization::_debug_id_bits) \
+ declare_constant(Deoptimization::_action_shift) \
+ declare_constant(Deoptimization::_reason_shift) \
+ declare_constant(Deoptimization::_debug_id_shift) \
+ \
/*********************/ \
/* Matcher (C2 only) */ \
/*********************/ \
@@ -2568,6 +2715,18 @@
\
declare_constant(InvocationEntryBci) \
\
+ /*************/ \
+ /* CompLevel */ \
+ /*************/ \
+ \
+ declare_constant(CompLevel_any) \
+ declare_constant(CompLevel_all) \
+ declare_constant(CompLevel_none) \
+ declare_constant(CompLevel_simple) \
+ declare_constant(CompLevel_limited_profile) \
+ declare_constant(CompLevel_full_profile) \
+ declare_constant(CompLevel_full_optimization) \
+ \
/***************/ \
/* OopMapValue */ \
/***************/ \
@@ -2698,8 +2857,38 @@
/* Constants in markOop used by CMS. */ \
declare_constant(markOopDesc::cms_shift) \
declare_constant(markOopDesc::cms_mask) \
- declare_constant(markOopDesc::size_shift)
+ declare_constant(markOopDesc::size_shift) \
+ \
+ /* InvocationCounter constants */ \
+ declare_constant(InvocationCounter::count_increment) \
+ declare_constant(InvocationCounter::count_shift)
+
+
+//--------------------------------------------------------------------------------
+// VM_ADDRESSES
+//
+#define VM_ADDRESSES(declare_address, declare_preprocessor_address, declare_function) \
+ \
+ declare_function(SharedRuntime::register_finalizer) \
+ declare_function(SharedRuntime::exception_handler_for_return_address) \
+ declare_function(SharedRuntime::OSR_migration_end) \
+ declare_function(SharedRuntime::dsin) \
+ declare_function(SharedRuntime::dcos) \
+ declare_function(SharedRuntime::dtan) \
+ declare_function(SharedRuntime::dexp) \
+ declare_function(SharedRuntime::dlog) \
+ declare_function(SharedRuntime::dlog10) \
+ declare_function(SharedRuntime::dpow) \
+ \
+ declare_function(os::dll_load) \
+ declare_function(os::dll_lookup) \
+ declare_function(os::javaTimeMillis) \
+ declare_function(os::javaTimeNanos) \
+ \
+ declare_function(Deoptimization::fetch_unroll_info) \
+ COMPILER2_PRESENT(declare_function(Deoptimization::uncommon_trap)) \
+ declare_function(Deoptimization::unpack_frames)
//--------------------------------------------------------------------------------
// Macros operating on the above lists
@@ -2932,6 +3121,23 @@
# define GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value)
#endif /* COMPILER1 */
+//--------------------------------------------------------------------------------
+// VMAddressEntry macros
+//
+
+#define GENERATE_VM_ADDRESS_ENTRY(name) \
+ { QUOTE(name), (void*) (name) },
+
+#define GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY(name, value) \
+ { name, (void*) (value) },
+
+#define GENERATE_VM_FUNCTION_ENTRY(name) \
+ { QUOTE(name), CAST_FROM_FN_PTR(void*, &(name)) },
+
+// This macro generates the sentinel value indicating the end of the list
+#define GENERATE_VM_ADDRESS_LAST_ENTRY() \
+ { NULL, NULL }
+
//
// Instantiation of VMStructEntries, VMTypeEntries and VMIntConstantEntries
//
@@ -2950,6 +3156,11 @@
GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
+#if INCLUDE_JVMCI
+ VM_STRUCTS_JVMCI(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_STATIC_VM_STRUCT_ENTRY)
+#endif
+
#if INCLUDE_ALL_GCS
VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
GENERATE_STATIC_VM_STRUCT_ENTRY)
@@ -2970,6 +3181,15 @@
VM_STRUCTS_EXT(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
GENERATE_STATIC_VM_STRUCT_ENTRY)
+ VM_STRUCTS_OS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_STATIC_VM_STRUCT_ENTRY,
+ GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
+ GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
+
VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
GENERATE_STATIC_VM_STRUCT_ENTRY,
GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY,
@@ -3002,6 +3222,11 @@
GENERATE_C2_VM_TYPE_ENTRY,
GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
+#if INCLUDE_JVMCI
+ VM_TYPES_JVMCI(GENERATE_VM_TYPE_ENTRY,
+ GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
+#endif
+
#if INCLUDE_ALL_GCS
VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY,
GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
@@ -3023,6 +3248,15 @@
VM_TYPES_EXT(GENERATE_VM_TYPE_ENTRY,
GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
+ VM_TYPES_OS(GENERATE_VM_TYPE_ENTRY,
+ GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
+ GENERATE_OOP_VM_TYPE_ENTRY,
+ GENERATE_INTEGER_VM_TYPE_ENTRY,
+ GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY,
+ GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY,
+ GENERATE_C2_VM_TYPE_ENTRY,
+ GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
+
VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY,
GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
GENERATE_OOP_VM_TYPE_ENTRY,
@@ -3052,6 +3286,12 @@
GENERATE_C2_VM_INT_CONSTANT_ENTRY,
GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+#if INCLUDE_JVMCI
+ VM_INT_CONSTANTS_JVMCI(GENERATE_VM_INT_CONSTANT_ENTRY,
+ GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+
+#endif
+
#if INCLUDE_ALL_GCS
VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)
@@ -3062,6 +3302,12 @@
VM_INT_CONSTANTS_TRACE(GENERATE_VM_INT_CONSTANT_ENTRY)
#endif
+ VM_INT_CONSTANTS_OS(GENERATE_VM_INT_CONSTANT_ENTRY,
+ GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
+ GENERATE_C1_VM_INT_CONSTANT_ENTRY,
+ GENERATE_C2_VM_INT_CONSTANT_ENTRY,
+ GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+
VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY,
GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
GENERATE_C1_VM_INT_CONSTANT_ENTRY,
@@ -3085,6 +3331,12 @@
GENERATE_C2_VM_LONG_CONSTANT_ENTRY,
GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY)
+ VM_LONG_CONSTANTS_OS(GENERATE_VM_LONG_CONSTANT_ENTRY,
+ GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY,
+ GENERATE_C1_VM_LONG_CONSTANT_ENTRY,
+ GENERATE_C2_VM_LONG_CONSTANT_ENTRY,
+ GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY)
+
VM_LONG_CONSTANTS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY,
GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY,
GENERATE_C1_VM_LONG_CONSTANT_ENTRY,
@@ -3100,6 +3352,25 @@
GENERATE_VM_LONG_CONSTANT_LAST_ENTRY()
};
+VMAddressEntry VMStructs::localHotSpotVMAddresses[] = {
+
+ VM_ADDRESSES(GENERATE_VM_ADDRESS_ENTRY,
+ GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
+ GENERATE_VM_FUNCTION_ENTRY)
+
+ VM_ADDRESSES_OS(GENERATE_VM_ADDRESS_ENTRY,
+ GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
+ GENERATE_VM_FUNCTION_ENTRY)
+
+#if INCLUDE_JVMCI
+ VM_ADDRESSES_JVMCI(GENERATE_VM_ADDRESS_ENTRY,
+ GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
+ GENERATE_VM_FUNCTION_ENTRY)
+#endif
+
+ GENERATE_VM_ADDRESS_LAST_ENTRY()
+};
+
// This is used both to check the types of referenced fields and, in
// debug builds, to ensure that all of the field types are present.
void
@@ -3308,6 +3579,11 @@
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryNameOffset, VMLongConstantEntry, name);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryValueOffset, VMLongConstantEntry, value);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMLongConstantEntryArrayStride, gHotSpotVMLongConstants);
+
+JNIEXPORT VMAddressEntry* gHotSpotVMAddresses = VMStructs::localHotSpotVMAddresses;
+ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryNameOffset, VMAddressEntry, name);
+ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryValueOffset, VMAddressEntry, value);
+ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMAddressEntryArrayStride, gHotSpotVMAddresses);
}
#ifdef ASSERT
@@ -3415,6 +3691,11 @@
&long_last_entry,
sizeof(VMLongConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMLongConstants");
+ static VMAddressEntry address_last_entry = GENERATE_VM_ADDRESS_LAST_ENTRY();
+ assert(memcmp(&localHotSpotVMAddresses[sizeof(localHotSpotVMAddresses) / sizeof(VMAddressEntry) - 1],
+ &address_last_entry,
+ sizeof(VMAddressEntry)) == 0, "Incorrect last entry in localHotSpotVMAddresses");
+
// Check for duplicate entries in type array
for (int i = 0; localHotSpotVMTypes[i].typeName != NULL; i++) {
--- a/hotspot/src/share/vm/runtime/vmStructs.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -95,6 +95,11 @@
uint64_t value; // Value of constant
} VMLongConstantEntry;
+typedef struct {
+ const char* name; // Name of address (example: "SharedRuntime::register_finalizer")
+ void* value; // Value of address
+} VMAddressEntry;
+
// This class is a friend of most classes, to be able to access
// private fields
class VMStructs {
@@ -117,6 +122,11 @@
// the fact that it has a NULL typeName
static VMLongConstantEntry localHotSpotVMLongConstants[];
+ /**
+ * Table of addresses.
+ */
+ static VMAddressEntry localHotSpotVMAddresses[];
+
// This is used to run any checking code necessary for validation of
// the data structure (debug build only)
static void init();
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -117,14 +117,16 @@
NMethodSweeper::mark_active_nmethods();
}
-VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id) {
+VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason) {
_thread = thread;
_id = id;
+ _reason = reason;
}
void VM_DeoptimizeFrame::doit() {
- Deoptimization::deoptimize_frame_internal(_thread, _id);
+ assert(_reason > Deoptimization::Reason_none && _reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
+ Deoptimization::deoptimize_frame_internal(_thread, _id, (Deoptimization::DeoptReason)_reason);
}
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -272,7 +272,8 @@
private:
JavaThread* _thread;
intptr_t* _id;
- VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
+ int _reason;
+ VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
public:
VMOp_Type type() const { return VMOp_DeoptimizeFrame; }
--- a/hotspot/src/share/vm/shark/sharkCacheDecache.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/shark/sharkCacheDecache.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -150,8 +150,10 @@
void SharkDecacher::end_frame() {
// Record the scope
+ methodHandle null_mh;
debug_info()->describe_scope(
pc_offset(),
+ null_mh,
target(),
bci(),
true,
--- a/hotspot/src/share/vm/utilities/exceptions.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -85,7 +85,7 @@
#endif // ASSERT
if (thread->is_VM_thread()
- || thread->is_Compiler_thread()
+ || !thread->can_call_java()
|| DumpSharedSpaces ) {
// We do not care what kind of exception we get for the vm-thread or a thread which
// is compiling. We just install a dummy exception object
@@ -112,7 +112,7 @@
}
if (thread->is_VM_thread()
- || thread->is_Compiler_thread()
+ || !thread->can_call_java()
|| DumpSharedSpaces ) {
// We do not care what kind of exception we get for the vm-thread or a thread which
// is compiling. We just install a dummy exception object
--- a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -50,6 +50,7 @@
// with.
template<typename T, typename TagType>
class FakeRttiSupport VALUE_OBJ_CLASS_SPEC {
+ friend class VMStructs;
public:
// Construct with the indicated concrete tag, and include the
// concrete tag in the associated tag set.
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -903,20 +903,20 @@
CompLevel_simple = 1, // C1
CompLevel_limited_profile = 2, // C1, invocation & backedge counters
CompLevel_full_profile = 3, // C1, invocation & backedge counters + mdo
- CompLevel_full_optimization = 4, // C2 or Shark
+ CompLevel_full_optimization = 4, // C2, Shark or JVMCI
-#if defined(COMPILER2) || defined(SHARK)
- CompLevel_highest_tier = CompLevel_full_optimization, // pure C2 and tiered
+#if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
+ CompLevel_highest_tier = CompLevel_full_optimization, // pure C2 and tiered or JVMCI and tiered
#elif defined(COMPILER1)
- CompLevel_highest_tier = CompLevel_simple, // pure C1
+ CompLevel_highest_tier = CompLevel_simple, // pure C1 or JVMCI
#else
CompLevel_highest_tier = CompLevel_none,
#endif
#if defined(TIERED)
CompLevel_initial_compile = CompLevel_full_profile // tiered
-#elif defined(COMPILER1)
- CompLevel_initial_compile = CompLevel_simple // pure C1
+#elif defined(COMPILER1) || INCLUDE_JVMCI
+ CompLevel_initial_compile = CompLevel_simple // pure C1 or JVMCI
#elif defined(COMPILER2) || defined(SHARK)
CompLevel_initial_compile = CompLevel_full_optimization // pure C2
#else
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -374,6 +374,40 @@
void sort(int f(E*,E*), int stride) {
qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
}
+
+ // Binary search and insertion utility. Search array for element
+ // matching key according to the static compare function. Insert
+ // that element is not already in the list. Assumes the list is
+ // already sorted according to compare function.
+ template <int compare(const E&, const E&)> E insert_sorted(E& key) {
+ bool found;
+ int location = find_sorted<E, compare>(key, found);
+ if (!found) {
+ insert_before(location, key);
+ }
+ return at(location);
+ }
+
+ template <typename K, int compare(const K&, const E&)> int find_sorted(const K& key, bool& found) {
+ found = false;
+ int min = 0;
+ int max = length() - 1;
+
+ while (max >= min) {
+ int mid = (max + min) / 2;
+ E value = at(mid);
+ int diff = compare(key, value);
+ if (diff > 0) {
+ min = mid + 1;
+ } else if (diff < 0) {
+ max = mid - 1;
+ } else {
+ found = true;
+ return mid;
+ }
+ }
+ return min;
+ }
};
// Global GrowableArray methods (one instance in the library per each 'E' type).
--- a/hotspot/src/share/vm/utilities/macros.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/macros.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -173,6 +173,20 @@
#define INCLUDE_TRACE 1
#endif // INCLUDE_TRACE
+#ifndef INCLUDE_JVMCI
+#define INCLUDE_JVMCI 1
+#endif
+
+#if INCLUDE_JVMCI
+#define JVMCI_ONLY(code) code
+#define NOT_JVMCI(code)
+#define NOT_JVMCI_RETURN /* next token must be ; */
+#else
+#define JVMCI_ONLY(code)
+#define NOT_JVMCI(code) code
+#define NOT_JVMCI_RETURN {}
+#endif // INCLUDE_JVMCI
+
// COMPILER1 variant
#ifdef COMPILER1
#ifdef COMPILER2
@@ -195,7 +209,7 @@
#ifdef TIERED
#define TIERED_ONLY(code) code
#define NOT_TIERED(code)
-#else
+#else // TIERED
#define TIERED_ONLY(code)
#define NOT_TIERED(code) code
#endif // TIERED
--- a/hotspot/src/share/vm/utilities/top.hpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/top.hpp Thu Oct 08 12:49:30 2015 -1000
@@ -42,6 +42,9 @@
#ifdef COMPILER2
#include "opto/c2_globals.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci_globals.hpp"
+#endif
// THIS FILE IS INTESIONALLY LEFT EMPTY
// IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Thu Oct 08 12:49:30 2015 -1000
@@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "prims/whitebox.hpp"
#include "runtime/arguments.hpp"
@@ -511,11 +512,15 @@
JDK_Version::runtime_version() : "";
st->print_cr("# JRE version: %s (%s) (build %s)", runtime_name, buf, runtime_version);
// This is the long version with some default settings added
- st->print_cr("# Java VM: %s (%s, %s%s%s, %s, %s)",
+ st->print_cr("# Java VM: %s (%s, %s%s%s%s%s, %s, %s)",
Abstract_VM_Version::vm_name(),
Abstract_VM_Version::vm_release(),
Abstract_VM_Version::vm_info_string(),
TieredCompilation ? ", tiered" : "",
+#if INCLUDE_JVMCI
+ EnableJVMCI ? ", jvmci" : "",
+ UseJVMCICompiler ? ", jvmci compiler" : "",
+#endif
UseCompressedOops ? ", compressed oops" : "",
gc_mode(),
Abstract_VM_Version::vm_platform_string()
@@ -704,6 +709,31 @@
st->cr();
}
+ STEP(265, "(printing code blob if possible)")
+
+ if (_verbose && _context) {
+ CodeBlob* cb = CodeCache::find_blob(_pc);
+ if (cb != NULL) {
+ if (Interpreter::contains(_pc)) {
+ // The interpreter CodeBlob is very large so try to print the codelet instead.
+ InterpreterCodelet* codelet = Interpreter::codelet_containing(_pc);
+ if (codelet != NULL) {
+ codelet->print_on(st);
+ Disassembler::decode(codelet->code_begin(), codelet->code_end(), st);
+ }
+ } else {
+ StubCodeDesc* desc = StubCodeDesc::desc_for(_pc);
+ if (desc != NULL) {
+ desc->print_on(st);
+ Disassembler::decode(desc->begin(), desc->end(), st);
+ } else {
+ Disassembler::decode(cb, st);
+ st->cr();
+ }
+ }
+ }
+ }
+
STEP(270, "(printing VM operation)" )
if (_verbose && _thread && _thread->is_VM_thread()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true
+ * -XX:+EnableJVMCI
+ * compiler.jvmci.JVM_GetJVMCIRuntimeTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=false
+ * -XX:-EnableJVMCI
+ * compiler.jvmci.JVM_GetJVMCIRuntimeTest
+
+ */
+
+package compiler.jvmci;
+
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.test.lib.Asserts;
+
+import java.lang.reflect.Method;
+
+public class JVM_GetJVMCIRuntimeTest {
+ private static final boolean IS_POSITIVE = Boolean.getBoolean(
+ "compiler.jvmci.JVM_GetJVMCIRuntimeTest.positive");
+
+ private final Method initializeRuntime;
+
+ public static void main(String[] args) {
+ new JVM_GetJVMCIRuntimeTest().runTest();
+ }
+
+ private void runTest() {
+ Object result;
+ try {
+ result = invoke();
+ } catch (InternalError e) {
+ if (IS_POSITIVE) {
+ throw new AssertionError("unexpected exception", e);
+ }
+ return;
+ }
+ if (!IS_POSITIVE) {
+ throw new AssertionError("didn't get expected exception");
+ }
+ Asserts.assertNotNull(result,
+ "initializeRuntime returned null");
+ Asserts.assertEQ(result, invoke(),
+ "initializeRuntime returns different results");
+
+ }
+ private Object invoke() {
+ Object result;
+ try {
+ result = initializeRuntime.invoke(JVMCI.class);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("can't invoke initializeRuntime", e);
+ }
+ return result;
+ }
+
+ private JVM_GetJVMCIRuntimeTest() {
+ Method method;
+ try {
+ method = JVMCI.class.getDeclaredMethod("initializeRuntime");
+ method.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ throw new Error("can't find JVMCI::initializeRuntime", e);
+ }
+ initializeRuntime = method;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.SecurityRestrictionsTest
+ * NO_SEC_MAN
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.SecurityRestrictionsTest
+ * NO_PERM
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.SecurityRestrictionsTest
+ * ALL_PERM
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.SecurityRestrictionsTest
+ * NO_JVMCI_ACCESS_PERM
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * compiler.jvmci.SecurityRestrictionsTest
+ * NO_JVMCI
+ */
+
+package compiler.jvmci;
+
+import jdk.vm.ci.hotspot.CompilerToVM;
+import jdk.test.lib.Utils;
+import java.lang.InternalError;
+import java.security.AccessControlException;
+import java.security.Permission;
+
+public class SecurityRestrictionsTest {
+
+ public static void main(String[] args) {
+ try {
+ // to init Utils before call SecurityManager
+ Class.forName(Utils.class.getName(), true,
+ Utils.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new Error("[TEST BUG]: jdk.test.lib.Utils not found", e);
+ }
+ try {
+ TestCase mode = TestCase.valueOf(args[0]);
+ mode.run();
+ } catch (IllegalArgumentException e) {
+ throw new Error("[TEST BUG]: Unknown mode " + args[0], e);
+ }
+ }
+
+ private enum TestCase {
+ NO_SEC_MAN,
+ NO_JVMCI {
+ @Override
+ public Class<? extends Throwable> getExpectedException() {
+ return InternalError.class;
+ }
+ },
+ ALL_PERM {
+ @Override
+ public SecurityManager getSecurityManager() {
+ return new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ }
+ };
+ }
+ },
+ NO_PERM {
+ @Override
+ public SecurityManager getSecurityManager() {
+ return new SecurityManager();
+ }
+
+ @Override
+ public Class<? extends Throwable> getExpectedException() {
+ return AccessControlException.class;
+ }
+ },
+ NO_JVMCI_ACCESS_PERM {
+ @Override
+ public SecurityManager getSecurityManager() {
+ return new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ if (isJvmciPermission(perm)) {
+ super.checkPermission(perm);
+ }
+ }
+
+ @Override
+ public void checkPropertyAccess(String key) {
+ if (key.startsWith(JVMCI_PROP_START)) {
+ super.checkPropertyAccess(key);
+ }
+ }
+ };
+ }
+
+ private boolean isJvmciPermission(Permission perm) {
+ String name = perm.getName();
+ return perm instanceof RuntimePermission
+ && (JVMCI_SERVICES.equals(name)
+ || name.startsWith(JVMCI_RT_PERM_START));
+ }
+
+ @Override
+ public Class<? extends Throwable> getExpectedException() {
+ return AccessControlException.class;
+ }
+ };
+
+ public void run() {
+ System.setSecurityManager(getSecurityManager());
+ Utils.runAndCheckException(
+ // to run CompilerToVM::<cinit> inside runAndCheckException
+ () -> new CompilerToVM(),
+ getExpectedException());
+ }
+
+ public SecurityManager getSecurityManager() {
+ return null;
+ }
+
+ public Class<? extends Throwable> getExpectedException() {
+ return null;
+ }
+
+ private static final String JVMCI_RT_PERM_START
+ = "accessClassInPackage.jdk.vm.ci";
+ private static final String JVMCI_SERVICES = "jvmciServices";
+ private static final String JVMCI_PROP_START = "jvmci.";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+
+public class CTVMUtilities {
+ /*
+ * A method to return HotSpotResolvedJavaMethod object using class object
+ * and method as input
+ */
+ public static HotSpotResolvedJavaMethodImpl getResolvedMethod(Class<?> cls,
+ Executable method) {
+ if (!(method instanceof Method || method instanceof Constructor)) {
+ throw new Error("wrong executable type " + method.getClass());
+ }
+ Field slotField;
+ int slot;
+ try {
+ slotField = method.getClass().getDeclaredField("slot");
+ boolean old = slotField.isAccessible();
+ slotField.setAccessible(true);
+ slot = slotField.getInt(method);
+ slotField.setAccessible(old);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TEST BUG: Can't get slot field", e);
+ }
+ return CompilerToVMHelper.getResolvedJavaMethodAtSlot(cls, slot);
+ }
+
+ public static HotSpotResolvedJavaMethodImpl getResolvedMethod(
+ Executable method) {
+ return getResolvedMethod(method.getDeclaringClass(), method);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.SpeculationLog;
+
+/*
+ * A simple "proxy" class to get test access to CompilerToVM package-private methods
+ */
+public class CompilerToVMHelper {
+ public static final CompilerToVM CTVM = new CompilerToVM();
+
+ public static byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getBytecode(method);
+ }
+
+ public static int getExceptionTableLength(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getExceptionTableLength(method);
+ }
+
+ public static long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getExceptionTableStart(method);
+ }
+
+ public static boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.canInlineMethod(method);
+ }
+
+ public static boolean shouldInlineMethod(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.shouldInlineMethod(method);
+ }
+
+ public static HotSpotResolvedJavaMethodImpl findUniqueConcreteMethod(
+ HotSpotResolvedObjectTypeImpl actualHolderType,
+ HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.findUniqueConcreteMethod(actualHolderType, method);
+ }
+
+ public static HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type) {
+ return CTVM.getImplementor(type);
+ }
+
+ public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.methodIsIgnoredBySecurityStackWalk(method);
+ }
+
+ public static HotSpotResolvedObjectTypeImpl lookupType(String name,
+ Class<?> accessingClass, boolean resolve) {
+ return CTVM.lookupType(name, accessingClass, resolve);
+ }
+
+ public static Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.resolveConstantInPool(constantPool, cpi);
+ }
+
+ public static Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.resolvePossiblyCachedConstantInPool(constantPool, cpi);
+ }
+
+ public static int lookupNameAndTypeRefIndexInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupNameAndTypeRefIndexInPool(constantPool, cpi);
+ }
+
+ public static String lookupNameInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupNameInPool(constantPool, cpi);
+ }
+
+ public static String lookupSignatureInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupSignatureInPool(constantPool, cpi);
+ }
+
+ public static int lookupKlassRefIndexInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupKlassRefIndexInPool(constantPool, cpi);
+ }
+
+ public static Object lookupKlassInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupKlassInPool(constantPool, cpi);
+ }
+
+ public static HotSpotResolvedJavaMethodImpl lookupMethodInPool(
+ HotSpotConstantPool constantPool, int cpi, byte opcode) {
+ return CTVM.lookupMethodInPool(constantPool, cpi, opcode);
+ }
+
+ public static void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi) {
+ CTVM.resolveInvokeDynamicInPool(constantPool, cpi);
+ }
+
+ public static void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi) {
+ CTVM.resolveInvokeHandleInPool(constantPool, cpi);
+ }
+
+ public static HotSpotResolvedObjectTypeImpl resolveTypeInPool(
+ HotSpotConstantPool constantPool, int cpi) throws LinkageError {
+ return CTVM.resolveTypeInPool(constantPool, cpi);
+ }
+
+ public static HotSpotResolvedObjectTypeImpl resolveFieldInPool(
+ HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info) {
+ return CTVM.resolveFieldInPool(constantPool, cpi, opcode, info);
+ }
+
+ public static int constantPoolRemapInstructionOperandFromCache(
+ HotSpotConstantPool constantPool, int cpci) {
+ return CTVM.constantPoolRemapInstructionOperandFromCache(constantPool, cpci);
+ }
+
+ public static Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi) {
+ return CTVM.lookupAppendixInPool(constantPool, cpi);
+ }
+
+ public static int installCode(TargetDescription target,
+ HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) {
+ return CTVM.installCode(target, compiledCode, code, speculationLog);
+ }
+
+ public static int getMetadata(TargetDescription target,
+ HotSpotCompiledCode compiledCode, HotSpotMetaData metaData) {
+ return CTVM.getMetadata(target, compiledCode, metaData);
+ }
+
+ public static void notifyCompilationStatistics(int id,
+ HotSpotResolvedJavaMethodImpl method, boolean osr,
+ int processedBytecodes, long time, long timeUnitsPerSecond,
+ InstalledCode installedCode) {
+ CTVM.notifyCompilationStatistics(id, method, osr, processedBytecodes,
+ time, timeUnitsPerSecond, installedCode);
+ }
+
+ public static void resetCompilationStatistics() {
+ CTVM.resetCompilationStatistics();
+ }
+
+ public static long initializeConfiguration() {
+ return CTVM.initializeConfiguration();
+ }
+
+ public static HotSpotResolvedJavaMethodImpl resolveMethod(
+ HotSpotResolvedObjectTypeImpl exactReceiver,
+ HotSpotResolvedJavaMethodImpl method,
+ HotSpotResolvedObjectTypeImpl caller) {
+ return CTVM.resolveMethod(exactReceiver, method, caller);
+ }
+
+ public static HotSpotResolvedJavaMethodImpl getClassInitializer(
+ HotSpotResolvedObjectTypeImpl type) {
+ return CTVM.getClassInitializer(type);
+ }
+
+ public static boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type) {
+ return CTVM.hasFinalizableSubclass(type);
+ }
+
+ public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(Class<?> holder,
+ int slot) {
+ return CTVM.getResolvedJavaMethodAtSlot(holder, slot);
+ }
+
+ public static long getMaxCallTargetOffset(long address) {
+ return CTVM.getMaxCallTargetOffset(address);
+ }
+
+ public static String disassembleCodeBlob(long codeBlob) {
+ return CTVM.disassembleCodeBlob(codeBlob);
+ }
+
+ public static StackTraceElement getStackTraceElement(
+ HotSpotResolvedJavaMethodImpl method, int bci) {
+ return CTVM.getStackTraceElement(method, bci);
+ }
+
+ public static Object executeInstalledCode(Object[] args,
+ InstalledCode installedCode) throws InvalidInstalledCodeException {
+ return CTVM.executeInstalledCode(args, installedCode);
+ }
+
+ public static long[] getLineNumberTable(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getLineNumberTable(method);
+ }
+
+ public static int getLocalVariableTableLength(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getLocalVariableTableLength(method);
+ }
+
+ public static long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getLocalVariableTableStart(method);
+ }
+
+ public static Object readUncompressedOop(long address) {
+ return CTVM.readUncompressedOop(address);
+ }
+
+ public static void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method) {
+ CTVM.doNotInlineOrCompile(method);
+ }
+
+ public static void reprofile(HotSpotResolvedJavaMethodImpl method) {
+ CTVM.reprofile(method);
+ }
+
+ public static void invalidateInstalledCode(InstalledCode installedCode) {
+ CTVM.invalidateInstalledCode(installedCode);
+ }
+
+ public static long[] collectCounters() {
+ return CTVM.collectCounters();
+ }
+
+ public static boolean isMature(long metaspaceMethodData) {
+ return CTVM.isMature(metaspaceMethodData);
+ }
+
+ public static int allocateCompileId(HotSpotResolvedJavaMethodImpl method,
+ int entryBCI) {
+ return CTVM.allocateCompileId(method, entryBCI);
+ }
+
+ public static boolean hasCompiledCodeForOSR(
+ HotSpotResolvedJavaMethodImpl method, int entryBCI, int level) {
+ return CTVM.hasCompiledCodeForOSR(method, entryBCI, level);
+ }
+
+ public static String getSymbol(long metaspaceSymbol) {
+ return CTVM.getSymbol(metaspaceSymbol);
+ }
+
+ public static HotSpotStackFrameReference getNextStackFrame(
+ HotSpotStackFrameReference frame,
+ HotSpotResolvedJavaMethodImpl[] methods, int initialSkip) {
+ return CTVM.getNextStackFrame(frame, methods, initialSkip);
+ }
+
+ public static void materializeVirtualObjects(
+ HotSpotStackFrameReference stackFrame, boolean invalidate) {
+ CTVM.materializeVirtualObjects(stackFrame, invalidate);
+ }
+
+ public static int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type,
+ HotSpotResolvedJavaMethodImpl method) {
+ return CTVM.getVtableIndexForInterfaceMethod(type, method);
+ }
+
+ public static boolean shouldDebugNonSafepoints() {
+ return CTVM.shouldDebugNonSafepoints();
+ }
+
+ public static void writeDebugOutput(byte[] bytes, int offset, int length) {
+ CTVM.writeDebugOutput(bytes, offset, length);
+ }
+
+ public static void flushDebugOutput() {
+ CTVM.flushDebugOutput();
+ }
+
+ public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base,
+ long displacement) {
+ return CTVM.getResolvedJavaMethod(base, displacement);
+ }
+
+ public static HotSpotConstantPool getConstantPool(Object base, long displacement) {
+ return CTVM.getConstantPool(base, displacement);
+ }
+
+ public static HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base,
+ long displacement, boolean compressed) {
+ return CTVM.getResolvedJavaType(base, displacement, compressed);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+import jdk.vm.ci.compiler.Compiler;
+import jdk.vm.ci.compiler.CompilerFactory;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.runtime.JVMCIRuntime;
+
+/*
+ * A stub classes to be able to use jvmci
+ */
+public class JVMCIHelpers {
+
+ public static class EmptyVMEventListener implements HotSpotVMEventListener {
+ // just empty, using default interface methods
+ }
+
+ public static class EmptyHotspotCompiler implements Compiler {
+
+ @Override
+ public void compileMethod(ResolvedJavaMethod method, int entryBCI,
+ long jvmciEnv, int id) {
+ // do nothing
+ }
+ }
+
+ public static class EmptyCompilerFactory implements CompilerFactory {
+
+ @Override
+ public String getCompilerName() {
+ return "EmptyCompiler";
+ }
+
+ @Override
+ public Architecture initializeArchitecture(Architecture arch) {
+ return arch;
+ }
+
+ @Override
+ public Compiler createCompiler(JVMCIRuntime runtime) {
+ return new EmptyHotspotCompiler();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.Compiler Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.CompilerFactory Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.hotspot.HotSpotVMEventListener Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyVMEventListener
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/AbstractClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public abstract class AbstractClass {
+ public static final long initTime = System.currentTimeMillis();
+ public abstract void abstractMethod();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/AbstractClassExtender.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class AbstractClassExtender extends AbstractClass {
+ @Override
+ public void abstractMethod() {
+ // empty
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/AnotherSingleImplementer.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class AnotherSingleImplementer implements AnotherSingleImplementerInterface {
+
+ @Override
+ public void interfaceMethod() {
+ // empty
+ }
+
+ public void nonInterfaceMethod() {
+ // empty
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ super.finalize();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/AnotherSingleImplementerInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface AnotherSingleImplementerInterface {
+ public static final long initTime = System.currentTimeMillis();
+
+ default void defaultMethod() {
+ // empty
+ }
+
+ void interfaceMethod();
+
+ void finalize() throws Throwable;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/DoNotExtendClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class DoNotExtendClass {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/DoNotImplementInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface DoNotImplementInterface {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultiSubclassedClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class MultiSubclassedClass {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultiSubclassedClassSubclass1.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class MultiSubclassedClassSubclass1 extends MultiSubclassedClass {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultiSubclassedClassSubclass2.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class MultiSubclassedClassSubclass2 extends MultiSubclassedClass {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public abstract class MultipleAbstractImplementer
+ implements MultipleImplementersInterface {
+
+ public abstract void abstractMethod();
+
+ @Override
+ public void finalize() throws Throwable {
+ super.finalize();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer1.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class MultipleImplementer1 implements MultipleImplementersInterface {
+
+ @Override
+ public void defaultMethod() {
+ // empty
+ }
+
+ @Override
+ public void testMethod() {
+ // empty
+ }
+ @Override
+ public void finalize() throws Throwable {
+ super.finalize();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class MultipleImplementer2 implements MultipleImplementersInterface {
+
+ private static int intStaticField = INT_CONSTANT;
+ static long longStaticField = LONG_CONSTANT;
+ static float floatStaticField = FLOAT_CONSTANT;
+ static double doubleStaticField = DOUBLE_CONSTANT;
+ public static String stringStaticField = STRING_CONSTANT;
+ protected static Object objectStaticField = OBJECT_CONSTANT;
+
+ public int intField = INT_CONSTANT;
+ private long longField = LONG_CONSTANT;
+ protected float floatField = FLOAT_CONSTANT;
+ double doubleField = DOUBLE_CONSTANT;
+ String stringField = STRING_CONSTANT;
+ Object objectField = OBJECT_CONSTANT;
+
+ public MultipleImplementer2() {
+ intField = Integer.MAX_VALUE;
+ longField = Long.MAX_VALUE;
+ floatField = Float.MAX_VALUE;
+ doubleField = Double.MAX_VALUE;
+ stringField = "Message";
+ objectField = new Object();
+ }
+
+ @Override
+ public void testMethod() {
+ // empty
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ super.finalize();
+ }
+
+ public void interfaceMethodReferral2(MultipleImplementersInterface obj) {
+ obj.interfaceMethodReferral(obj);
+ }
+
+ public void lambdaUsingMethod2() {
+ Thread t = new Thread(this::testMethod);
+ t.start();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface MultipleImplementersInterface {
+
+ int INT_CONSTANT = Integer.MAX_VALUE;
+ long LONG_CONSTANT = Long.MAX_VALUE;
+ float FLOAT_CONSTANT = Float.MAX_VALUE;
+ double DOUBLE_CONSTANT = Double.MAX_VALUE;
+ String STRING_CONSTANT = "Hello";
+ Object OBJECT_CONSTANT = new Object();
+
+ default void defaultMethod() {
+ // empty
+ }
+
+ void testMethod();
+
+ default void finalize() throws Throwable {
+ // empty
+ }
+
+ default void interfaceMethodReferral(MultipleImplementersInterface obj) {
+ obj.defaultMethod();
+ }
+
+ default void lambdaUsingMethod() {
+ Thread t = new Thread(this::defaultMethod);
+ t.start();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterfaceExtender.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface MultipleImplementersInterfaceExtender
+ extends MultipleImplementersInterface {
+ // provide default implementation for parent interface
+ @Override
+ default void testMethod() {
+ // empty
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/PackagePrivateClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+class PackagePrivateClass {
+ // empty
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/SimpleClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+// just a most common simple class with method "testMethod" to use anywhere
+public class SimpleClass {
+
+ public void testMethod() {
+ // empty
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/SingleImplementer.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class SingleImplementer implements SingleImplementerInterface {
+ public static final long initTime = System.currentTimeMillis();
+
+ @Override
+ public void interfaceMethod() {
+ // empty
+ }
+
+ public void nonInterfaceMethod() {
+ // empty
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ super.finalize();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/SingleImplementerInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface SingleImplementerInterface {
+ public static final long initTime = System.currentTimeMillis();
+
+ default void defaultMethod() {
+ // empty
+ }
+
+ void interfaceMethod();
+
+ void finalize() throws Throwable;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/SingleSubclass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class SingleSubclass extends SingleSubclassedClass {
+ public void usualMethod() {
+ // empty
+ }
+
+ @Override
+ public void overridenMethod() {
+ // empty
+ }
+
+ private void privateMethod() {
+ // empty
+ }
+
+ public static void staticMethod() {
+ // empty
+ }
+
+ protected void protectedMethod() {
+ // empty
+ }
+
+ void defaultAccessMethod() {
+ // empty
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/SingleSubclassedClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public class SingleSubclassedClass {
+ public void inheritedMethod() {
+ // empty
+ }
+
+ public void overridenMethod() {
+ //empty
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/testcases/TestCase.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.common.testcases;
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * A test case for tests in compiler.jvmci.compilerToVM package.
+ */
+public class TestCase {
+ private static final Class<?>[] CLASSES = {
+ AbstractClass.class,
+ AbstractClassExtender.class,
+ AnotherSingleImplementer.class,
+ AnotherSingleImplementerInterface.class,
+ DoNotExtendClass.class,
+ DoNotImplementInterface.class,
+ MultipleAbstractImplementer.class,
+ MultipleImplementer1.class,
+ MultipleImplementer2.class,
+ MultipleImplementersInterface.class,
+ MultipleImplementersInterfaceExtender.class,
+ MultiSubclassedClass.class,
+ MultiSubclassedClassSubclass1.class,
+ MultiSubclassedClassSubclass2.class,
+ PackagePrivateClass.class,
+ SimpleClass.class,
+ SingleImplementer.class,
+ SingleImplementerInterface.class,
+ SingleSubclass.class,
+ SingleSubclassedClass.class
+ };
+
+ public static Collection<Class<?>> getAllClasses() {
+ return Arrays.asList(CLASSES);
+ }
+
+ public static Collection<Executable> getAllExecutables() {
+ Set<Executable> result = new HashSet<>();
+ for (Class<?> aClass : CLASSES) {
+ result.addAll(Arrays.asList(aClass.getMethods()));
+ result.addAll(Arrays.asList(aClass.getConstructors()));
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:-BackgroundCompilation
+ * compiler.jvmci.compilerToVM.AllocateCompileIdTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.HashSet;
+
+import compiler.jvmci.common.testcases.TestCase;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Pair;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
+
+public class AllocateCompileIdTest {
+
+ private final HashSet<Integer> ids = new HashSet<>();
+
+ public static void main(String[] args) {
+ AllocateCompileIdTest test = new AllocateCompileIdTest();
+ createTestCasesCorrectBci().forEach(test::runSanityCorrectTest);
+ createTestCasesIncorrectBci().forEach(test::runSanityIncorrectTest);
+ }
+
+
+ private static List<CompileCodeTestCase> createTestCasesCorrectBci() {
+ List<CompileCodeTestCase> result = new ArrayList<>();
+ try {
+ Class<?> aClass = DummyClass.class;
+ Method method = aClass.getMethod("withLoop");
+ result.add(new CompileCodeTestCase(method, 17));
+ result.add(new CompileCodeTestCase(method, -1));
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG : " + e, e);
+ }
+ return result;
+ }
+
+
+ private static List<Pair<CompileCodeTestCase, Class<? extends Throwable>>>
+ createTestCasesIncorrectBci() {
+ List<Pair<CompileCodeTestCase, Class<? extends Throwable>>> result
+ = new ArrayList<>();
+
+ try {
+ Class<?> aClass = DummyClass.class;
+ Method method = aClass.getMethod("dummyInstanceFunction");
+ // greater than bytecode.length
+ int[] bcis = new int[] {30, 50, 200};
+ for (int bci : bcis) {
+ result.add(new Pair<>(new CompileCodeTestCase(method, bci),
+ IllegalArgumentException.class));
+ }
+ bcis = new int[] {-4, -50, -200};
+ for (int bci : bcis) {
+ result.add(new Pair<>(new CompileCodeTestCase(method, bci),
+ IllegalArgumentException.class));
+ }
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG : " + e.getMessage(), e);
+ }
+ return result;
+ }
+
+ private void runSanityCorrectTest(CompileCodeTestCase testCase) {
+ System.out.println(testCase);
+ Executable aMethod = testCase.executable;
+ int bci = testCase.bci;
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ int wbCompileID = getWBCompileID(testCase);
+ int id = CompilerToVMHelper.allocateCompileId(method, bci);
+ Asserts.assertNE(id, 0, testCase + " : zero compile id");
+
+ if (wbCompileID > 0) {
+ Asserts.assertGT(id, wbCompileID, testCase
+ + " : allocated 'compile id' not greater than existed");
+ if (!ids.add(wbCompileID)) {
+ throw new AssertionError(String.format(
+ "%s : vm compilation allocated existed id -- %d",
+ testCase, id));
+ }
+ }
+ if (!ids.add(id)) {
+ throw new AssertionError(String.format(
+ "%s : allocateCompileId returned existed id %d",
+ testCase, id));
+ }
+ }
+
+ private void runSanityIncorrectTest(
+ Pair<CompileCodeTestCase, Class<? extends Throwable>> testCase) {
+ System.out.println(testCase);
+ Class<? extends Throwable> exception = testCase.second;
+ Executable aMethod = testCase.first.executable;
+ int bci = testCase.first.bci;
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ Utils.runAndCheckException(
+ () -> CompilerToVMHelper.allocateCompileId(method, bci),
+ exception);
+ }
+
+ private int getWBCompileID(CompileCodeTestCase testCase) {
+ NMethod nm = testCase.deoptimizeAndCompile();
+ if (nm == null) {
+ throw new Error("[TEST BUG] cannot compile method " + testCase);
+ }
+ return nm.compile_id;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.CanInlineMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+public class CanInlineMethodTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Executable> testCases = createTestCases();
+ testCases.forEach(CanInlineMethodTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ boolean canInline = CompilerToVMHelper.canInlineMethod(method);
+ boolean expectedCanInline = !WB.testSetDontInlineMethod(aMethod,
+ true);
+ Asserts.assertEQ(canInline, expectedCanInline, "Unexpected initial " +
+ "value of property 'can inline'");
+
+ canInline = CompilerToVMHelper.canInlineMethod(method);
+ Asserts.assertFalse(canInline, aMethod + "Unexpected value of " +
+ "property 'can inline' after setting 'do not inline' to true");
+ WB.testSetDontInlineMethod(aMethod, false);
+ canInline = CompilerToVMHelper.canInlineMethod(method);
+ Asserts.assertTrue(canInline, "Unexpected value of " +
+ "property 'can inline' after setting 'do not inline' to false");
+ }
+
+ private static List<Executable> createTestCases() {
+ List<Executable> testCases = new ArrayList<>();
+
+ Class<?> aClass = DummyClass.class;
+ testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
+ testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
+ return testCases;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib/
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.CollectCountersTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI -Xbootclasspath/a:.
+ * -XX:JVMCICounterSize=0
+ * -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=0
+ * compiler.jvmci.compilerToVM.CollectCountersTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI -Xbootclasspath/a:.
+ * -XX:JVMCICounterSize=11
+ * -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=11
+ * compiler.jvmci.compilerToVM.CollectCountersTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class CollectCountersTest {
+ private static final int EXPECTED = Integer.getInteger(
+ "compiler.jvmci.compilerToVM.CollectCountersTest.expected");
+ public static void main(String args[]) {
+ new CollectCountersTest().runTest();
+ }
+
+ private void runTest() {
+ long[] counters = CompilerToVMHelper.collectCounters();
+ Asserts.assertNotNull(counters, "Expected not-null counters array");
+ int ctvmData = counters.length;
+ Asserts.assertEQ(EXPECTED, ctvmData, "Unexpected counters amount");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.testlibrary.CompilerUtils;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A test case for tests which require compiled code.
+ */
+public final class CompileCodeTestCase {
+ public static final Map<Class<?>, Object> RECEIVERS;
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final int COMP_LEVEL;
+ static {
+ int[] levels = CompilerUtils.getAvailableCompilationLevels();
+ if (levels.length == 0) {
+ throw new Error("TESTBUG: no compilers available");
+ }
+ COMP_LEVEL = levels[levels.length - 1];
+ }
+ private static final Class<?>[] CLASSES = {
+ Interface.class,
+ Dummy.class,
+ DummyEx.class};
+
+ public final Executable executable;
+ public final int bci;
+ private final boolean isOsr;
+
+ public CompileCodeTestCase(Executable executable, int bci) {
+ this.executable = executable;
+ this.bci = bci;
+ isOsr = bci >= 0;
+ }
+
+ public NMethod compile() {
+ return compile(COMP_LEVEL);
+ }
+
+ public NMethod compile(int level) {
+ boolean enqueued = WB.enqueueMethodForCompilation(executable,
+ level, bci);
+ if (!enqueued) {
+ throw new Error(String.format(
+ "%s can't be enqueued for %scompilation on level %d",
+ executable, bci >= 0 ? "osr-" : "", level));
+ }
+ Utils.waitForCondition(() -> WB.isMethodCompiled(executable, isOsr));
+ return NMethod.get(executable, isOsr);
+ }
+
+ public static List<CompileCodeTestCase> generate(int bci) {
+ ArrayList<CompileCodeTestCase> result = new ArrayList<>();
+ for (Class<?> aClass : CLASSES) {
+ for (Executable m : aClass.getDeclaredConstructors()) {
+ result.add(new CompileCodeTestCase(m, bci));
+ }
+ Arrays.stream(aClass.getDeclaredMethods())
+ .filter(m -> !Modifier.isAbstract(m.getModifiers()))
+ .filter(m -> !Modifier.isNative(m.getModifiers()))
+ .map(m -> new CompileCodeTestCase(m, bci))
+ .forEach(result::add);
+ }
+ return result;
+ }
+
+ public NMethod toNMethod() {
+ return NMethod.get(executable, isOsr);
+ }
+
+ @Override
+ public String toString() {
+ return "CompileCodeTestCase{" +
+ "executable=" + executable +
+ ", bci=" + bci +
+ '}';
+ }
+
+ public void deoptimize() {
+ WB.deoptimizeMethod(executable, isOsr);
+ }
+
+ public NMethod deoptimizeAndCompile() {
+ deoptimize();
+ return compile();
+ }
+
+ // classes which are used as "input" data in test cases
+ private static interface Interface {
+ Interface interfaceMethod();
+ default Long defaultOverriddenMethod(Interface[] array) {
+ return array == null ? 0L : array.length;
+ }
+ default int defaultMethod(Object o) {
+ return o != null ? o.hashCode() : 0;
+ }
+ }
+
+ private static abstract class Dummy implements Interface {
+ protected Dummy() {
+ }
+
+ private static void staticMethod() {
+ }
+
+ Dummy instanceMethod(int i) {
+ return null;
+ }
+
+ abstract Object abstractMethod(double d);
+
+ @Override
+ public Long defaultOverriddenMethod(Interface[] array) {
+ return 0L;
+ }
+ }
+
+ public static class DummyEx extends Dummy {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ public DummyEx() {
+ }
+
+ protected Dummy instanceMethod(int i) {
+ if (i == 0) {
+ return this;
+ }
+ return null;
+ }
+
+ @Override
+ Object abstractMethod(double d) {
+ return this;
+ }
+
+ @Override
+ public Interface interfaceMethod() {
+ return null;
+ }
+ }
+
+ static {
+ Map<Class<?>, Object> map = new HashMap<>();;
+ map.put(CompileCodeTestCase.DummyEx.class,
+ new CompileCodeTestCase.DummyEx());
+ map.put(CompileCodeTestCase.Dummy.class,
+ new CompileCodeTestCase.Dummy() {
+ @Override
+ public CompileCodeTestCase.Interface interfaceMethod() {
+ throw new AbstractMethodError();
+ }
+
+ @Override
+ Object abstractMethod(double d) {
+ throw new AbstractMethodError();
+ }
+ });
+ map.put(CompileCodeTestCase.Interface.class,
+ new CompileCodeTestCase.Interface() {
+ @Override
+ public CompileCodeTestCase.Interface interfaceMethod() {
+ throw new AbstractMethodError();
+ }
+ });
+ RECEIVERS = Collections.unmodifiableMap(map);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.internal.misc.SharedSecrets;
+import sun.reflect.ConstantPool;
+
+/**
+ * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests
+ */
+public class ConstantPoolTestCase {
+
+ private final Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests;
+
+ public static interface Validator {
+ void validate(HotSpotConstantPool constantPoolCTVM, ConstantPool constantPoolSS,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int index);
+ }
+
+ public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests) {
+ this.typeTests = new HashMap<>();
+ this.typeTests.putAll(typeTests);
+ }
+
+ private void messageOnFail(Throwable t,
+ ConstantPoolTestsHelper.ConstantTypes cpType,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
+ ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess().
+ getConstantPool(dummyClass.klass);
+ String msg = String.format("Test for %s constant pool entry of"
+ + " type %s",
+ dummyClass.klass, cpType.name());
+ switch (cpType) {
+ case CONSTANT_CLASS:
+ case CONSTANT_STRING:
+ case CONSTANT_METHODTYPE:
+ String utf8 = constantPoolSS
+ .getUTF8At((int) dummyClass.cp.get(index).value);
+ msg = String.format("%s (%s) failed with %s", msg, utf8, t);
+ break;
+ case CONSTANT_INTEGER:
+ int intValue = constantPoolSS.getIntAt(index);
+ msg = String.format("%s (%d) failed with %s", msg, intValue, t);
+ break;
+ case CONSTANT_LONG:
+ long longValue = constantPoolSS.getLongAt(index);
+ msg = String.format("%s (%d) failed with %s", msg, longValue, t);
+ break;
+ case CONSTANT_FLOAT:
+ float floatValue = constantPoolSS.getFloatAt(index);
+ msg = String.format("%s (%E) failed with %s", msg, floatValue, t);
+ break;
+ case CONSTANT_DOUBLE:
+ double doubleValue = constantPoolSS.getDoubleAt(index);
+ msg = String.format("%s (%E) failed with %s", msg, doubleValue, t);
+ break;
+ case CONSTANT_UTF8:
+ String utf8Value = constantPoolSS.getUTF8At(index);
+ msg = String.format("%s (%s) failed with %s", msg, utf8Value, t);
+ break;
+ case CONSTANT_INVOKEDYNAMIC:
+ index = ((int[]) dummyClass.cp.get(index).value)[1];
+ case CONSTANT_NAMEANDTYPE:
+ String name = constantPoolSS
+ .getUTF8At(((int[]) dummyClass.cp.get(index).value)[0]);
+ String type = constantPoolSS
+ .getUTF8At(((int[]) dummyClass.cp.get(index).value)[1]);
+ msg = String.format("%s (%s:%s) failed with %s",
+ msg, name, type, t);
+ break;
+ case CONSTANT_METHODHANDLE:
+ index = ((int[]) dummyClass.cp.get(index).value)[1];
+ case CONSTANT_METHODREF:
+ case CONSTANT_INTERFACEMETHODREF:
+ case CONSTANT_FIELDREF:
+ int classIndex = ((int[]) dummyClass.cp.get(index).value)[0];
+ int nameAndTypeIndex = ((int[]) dummyClass.cp.get(index).value)[1];
+ String cName = constantPoolSS
+ .getUTF8At((int) dummyClass.cp.get(classIndex).value);
+ String mName = constantPoolSS
+ .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[0]);
+ String mType = constantPoolSS
+ .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[1]);
+ msg = String.format("%s (%s.%s:%s) failed with %s ",
+ msg, cName, mName, mType, t);
+ break;
+ default:
+ msg = String.format("Test bug: unknown constant type %s ", cpType);
+ }
+ throw new Error(msg + t.getMessage(), t);
+ }
+
+ public void test() {
+ for (ConstantPoolTestsHelper.DummyClasses dummyClass
+ : ConstantPoolTestsHelper.DummyClasses.values()) {
+ System.out.printf("%nTesting dummy %s%n", dummyClass.klass);
+ HotSpotResolvedObjectTypeImpl holder = HotSpotResolvedObjectTypeImpl
+ .fromObjectClass(dummyClass.klass);
+ HotSpotConstantPool constantPoolCTVM = holder.getConstantPool();
+ ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess().
+ getConstantPool(dummyClass.klass);
+ for (Integer i : dummyClass.cp.keySet()) {
+ ConstantPoolTestsHelper.ConstantTypes cpType
+ = dummyClass.cp.get(i).type;
+ if (!typeTests.keySet().contains(cpType)) {
+ continue;
+ }
+ try {
+ typeTests.get(cpType).validate(constantPoolCTVM,
+ constantPoolSS, dummyClass, i);
+ } catch (Throwable t) {
+ messageOnFail(t, cpType, dummyClass, i);
+ }
+ }
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.MultipleImplementer2;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class contains hard-coded constant pool tables for dummy classes used for
+ * jdk.vm.ci.hotspot.CompilerToVM constant pool methods
+ */
+public class ConstantPoolTestsHelper {
+
+ public enum ConstantTypes {
+ CONSTANT_CLASS,
+ CONSTANT_FIELDREF,
+ CONSTANT_METHODREF,
+ CONSTANT_INTERFACEMETHODREF,
+ CONSTANT_STRING,
+ CONSTANT_INTEGER,
+ CONSTANT_FLOAT,
+ CONSTANT_LONG,
+ CONSTANT_DOUBLE,
+ CONSTANT_NAMEANDTYPE,
+ CONSTANT_UTF8,
+ CONSTANT_METHODHANDLE,
+ CONSTANT_METHODTYPE,
+ CONSTANT_INVOKEDYNAMIC;
+ }
+
+ public enum DummyClasses {
+ DUMMY_CLASS(MultipleImplementer2.class, CP_MAP_FOR_CLASS),
+ DUMMY_INTERFACE(MultipleImplementersInterface.class, CP_MAP_FOR_INTERFACE);
+
+ public final Class<?> klass;
+ public final Map<Integer, ConstantPoolEntry> cp;
+
+ DummyClasses(Class<?> klass, Map<Integer, ConstantPoolEntry> cp) {
+ this.klass = klass;
+ this.cp = cp;
+ }
+ }
+
+ public static class ConstantPoolEntry {
+
+ public final ConstantTypes type;
+ public final Object value;
+
+ public ConstantPoolEntry(ConstantTypes type, Object value) {
+ this.type = type;
+ this.value = value;
+ }
+ }
+
+ private static final Map<Integer, ConstantPoolEntry> CP_MAP_FOR_CLASS
+ = new HashMap<>();
+ static {
+ CP_MAP_FOR_CLASS.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 68}));
+ CP_MAP_FOR_CLASS.put(2, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 69));
+ CP_MAP_FOR_CLASS.put(3, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647));
+ CP_MAP_FOR_CLASS.put(4, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 70}));
+ CP_MAP_FOR_CLASS.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807L));
+ CP_MAP_FOR_CLASS.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38F));
+ CP_MAP_FOR_CLASS.put(10, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308D));
+ CP_MAP_FOR_CLASS.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 74));
+ CP_MAP_FOR_CLASS.put(22, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 83));
+ CP_MAP_FOR_CLASS.put(23, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 84}));
+ CP_MAP_FOR_CLASS.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{2, 85}));
+ CP_MAP_FOR_CLASS.put(26, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 91}));
+ CP_MAP_FOR_CLASS.put(29, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 94}));
+ CP_MAP_FOR_CLASS.put(35, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 100));
+ CP_MAP_FOR_CLASS.put(68, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{54, 55}));
+ CP_MAP_FOR_CLASS.put(70, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{48, 37}));
+ CP_MAP_FOR_CLASS.put(84, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{59, 55}));
+ CP_MAP_FOR_CLASS.put(85, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{103, 63}));
+ CP_MAP_FOR_CLASS.put(91, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{106, 107}));
+ CP_MAP_FOR_CLASS.put(94, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{36, 37}));
+ CP_MAP_FOR_CLASS.put(104, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{110, 111}));
+ CP_MAP_FOR_CLASS.put(105, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{35, 112}));
+ CP_MAP_FOR_CLASS.put(110, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 113));
+ CP_MAP_FOR_CLASS.put(111, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{114, 118}));
+ CP_MAP_FOR_CLASS.put(112, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{58, 55}));
+ }
+
+ private static final Map<Integer, ConstantPoolEntry> CP_MAP_FOR_INTERFACE
+ = new HashMap<>();
+ static {
+ CP_MAP_FOR_INTERFACE.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 48));
+ CP_MAP_FOR_INTERFACE.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{13, 52}));
+ CP_MAP_FOR_INTERFACE.put(6, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 53));
+ CP_MAP_FOR_INTERFACE.put(7, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 58}));
+ CP_MAP_FOR_INTERFACE.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 59}));
+ CP_MAP_FOR_INTERFACE.put(9, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 60}));
+ CP_MAP_FOR_INTERFACE.put(12, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{13, 63}));
+ CP_MAP_FOR_INTERFACE.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 64));
+ CP_MAP_FOR_INTERFACE.put(17, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647));
+ CP_MAP_FOR_INTERFACE.put(20, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807l));
+ CP_MAP_FOR_INTERFACE.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38f));
+ CP_MAP_FOR_INTERFACE.put(27, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308d));
+ CP_MAP_FOR_INTERFACE.put(31, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 65));
+ CP_MAP_FOR_INTERFACE.put(52, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{34, 35}));
+ CP_MAP_FOR_INTERFACE.put(55, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{6, 67}));
+ CP_MAP_FOR_INTERFACE.put(56, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODTYPE, 35));
+ CP_MAP_FOR_INTERFACE.put(57, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{9, 5}));
+ CP_MAP_FOR_INTERFACE.put(58, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{68, 69}));
+ CP_MAP_FOR_INTERFACE.put(59, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{70, 71}));
+ CP_MAP_FOR_INTERFACE.put(60, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{72, 35}));
+ CP_MAP_FOR_INTERFACE.put(63, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{32, 33}));
+ CP_MAP_FOR_INTERFACE.put(67, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{73, 74}));
+ CP_MAP_FOR_INTERFACE.put(73, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 75));
+ CP_MAP_FOR_INTERFACE.put(74, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{76, 80}));
+ CP_MAP_FOR_INTERFACE.put(77, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 82));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run driver compiler.jvmci.compilerToVM.DebugOutputTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.ProcessTools;
+import java.util.Arrays;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Utils;
+
+public class DebugOutputTest {
+ public static void main(String[] args) {
+ new DebugOutputTest().test();
+ }
+
+ private void test() {
+ for (TestCaseData testCase : TestCaseData.values()) {
+ System.out.println(testCase);
+ OutputAnalyzer oa;
+ try {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ /* use test options = */ true,
+ "-XX:+UnlockExperimentalVMOptions",
+ "-XX:+EnableJVMCI",
+ "-Xbootclasspath/a:.",
+ DebugOutputTest.Worker.class.getName(),
+ testCase.name());
+ oa = ProcessTools.executeProcess(pb);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("Problems running child process", e);
+ }
+ if (testCase.expectedException != null) {
+ oa.shouldHaveExitValue(1);
+ oa.shouldContain(testCase.expectedException.getName());
+ } else {
+ oa.shouldHaveExitValue(0);
+ oa.shouldContain(new String(testCase.getExpected()));
+ }
+ }
+ }
+
+ /**
+ * A list of test cases that are executed in forked VM
+ */
+ private enum TestCaseData {
+ PART_ARRAY(100, 50),
+ FULL_ARRAY(0, 255),
+ EMPTY(0, 0),
+ NEGATIVE_LENGTH(0, Integer.MIN_VALUE,
+ ArrayIndexOutOfBoundsException.class),
+ NEGATIVE_OFFSET(-1, 255,
+ ArrayIndexOutOfBoundsException.class),
+ LEFT_BOUND(Integer.MIN_VALUE, 100,
+ ArrayIndexOutOfBoundsException.class),
+ RIGHT_BOUND(Integer.MAX_VALUE, 100,
+ ArrayIndexOutOfBoundsException.class),
+ BIG_LENGTH(0, Integer.MAX_VALUE,
+ ArrayIndexOutOfBoundsException.class),
+ NULL_POINTER(0, 0,
+ NullPointerException.class),
+ ;
+
+ private static final int SIZE = 255;
+ private static final byte[] DATA = generate();
+ public final int offset;
+ public final int length;
+ public final Class<? extends Throwable> expectedException;
+
+ private TestCaseData(int offset, int length,
+ Class<? extends Throwable> expectedException) {
+ this.offset = offset;
+ this.length = length;
+ this.expectedException = expectedException;
+ }
+
+ private TestCaseData(int offset, int length) {
+ this(offset, length, null);
+ }
+
+ private static byte[] generate() {
+ byte[] byteArray = new byte[SIZE];
+ for (int i = 0; i < SIZE; i++) {
+ byteArray[i] = (byte) (i + 1);
+ }
+ return byteArray;
+ }
+
+ public byte[] getExpected() {
+ if (expectedException != null) {
+ return new byte[0];
+ }
+ return Arrays.copyOfRange(TestCaseData.DATA, offset,
+ offset + length);
+ }
+
+ @Override
+ public String toString() {
+ return "CASE: " + this.name();
+ }
+
+ public byte[] getData() {
+ if (equals(NULL_POINTER)) {
+ return null;
+ } else {
+ return DATA;
+ }
+ }
+ }
+
+ public static class Worker {
+ public static void main(String[] args) {
+ for (String arg : args) {
+ TestCaseData tcase = TestCaseData.valueOf(arg);
+ CompilerToVMHelper.writeDebugOutput(tcase.getData(),
+ tcase.offset, tcase.length);
+ CompilerToVMHelper.flushDebugOutput();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.DisassembleCodeBlobTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.DisassembleCodeBlobTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import sun.hotspot.code.NMethod;
+
+import java.util.List;
+
+public class DisassembleCodeBlobTest {
+
+ public static void main(String[] args) {
+ DisassembleCodeBlobTest test
+ = new DisassembleCodeBlobTest();
+ List<CompileCodeTestCase> testCases
+ = CompileCodeTestCase.generate(/* bci = */ -1);
+ testCases.addAll(CompileCodeTestCase.generate(/* bci = */ 0));
+ testCases.forEach(test::check);
+ test.checkNull();
+ }
+
+ private void checkNull() {
+ String str = CompilerToVMHelper.disassembleCodeBlob(0L);
+ Asserts.assertNull(str, "not null string returned for null pointer");
+ }
+
+ private void check(CompileCodeTestCase testCase) {
+ System.out.println(testCase);
+ // to have a clean state
+ NMethod nMethod = testCase.deoptimizeAndCompile();
+ if (nMethod == null) {
+ throw new Error(testCase + " : method is not compiled");
+ }
+ String str = CompilerToVMHelper.disassembleCodeBlob(nMethod.address);
+ if (str != null) {
+ Asserts.assertGT(str.length(), 0,
+ testCase + " : returned string has to be non-zero length");
+ }
+ String str2 = CompilerToVMHelper.disassembleCodeBlob(nMethod.address);
+ Asserts.assertEQ(str, str2,
+ testCase + " : 2nd invocation returned different value");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.DoNotInlineOrCompileTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+public class DoNotInlineOrCompileTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Executable> testCases = createTestCases();
+ testCases.forEach(DoNotInlineOrCompileTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ boolean canInline = CompilerToVMHelper.canInlineMethod(method);
+ Asserts.assertTrue(canInline, "Unexpected initial " +
+ "value of property 'can inline'");
+ CompilerToVMHelper.doNotInlineOrCompile(method);
+ canInline = CompilerToVMHelper.canInlineMethod(method);
+ Asserts.assertFalse(canInline, aMethod
+ + " : can be inlined even after doNotInlineOrCompile'");
+ }
+
+ private static List<Executable> createTestCases() {
+ List<Executable> testCases = new ArrayList<>();
+
+ Class<?> aClass = DummyClass.class;
+ testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
+ testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
+ return testCases;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DummyAbstractClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.compilerToVM;
+
+abstract class DummyAbstractClass implements DummyInterface {
+ public abstract int dummyAbstractFunction();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DummyClass.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+import java.util.Random;
+
+class DummyClass extends DummyAbstractClass {
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ int p1 = 5;
+ int p2 = 6;
+
+ public int dummyInstanceFunction() {
+ String str1 = "123123123";
+ double x = 3.14;
+ int y = Integer.parseInt(str1);
+
+ return y / (int) x;
+ }
+
+ public int dummyEmptyInstanceFunction() {
+ return 42;
+ }
+
+ public static int dummyEmptyStaticFunction() {
+ return -42;
+ }
+
+ @Override
+ public int dummyAbstractFunction() {
+ int z = p1 * p2;
+ return (int) (Math.cos(p2 - p1 + z) * 100);
+ }
+
+ @Override
+ public void dummyFunction() {
+ dummyEmptyInstanceFunction();
+ }
+
+ public void withLoop() {
+ long tier4 = (Long) WB.getVMFlag("Tier4BackEdgeThreshold");
+ for (long i = 0; i < tier4; ++i) {
+ randomProfile();
+ }
+ }
+
+ private double randomProfile() {
+ String str1 = "123123123";
+ double x = 3.14;
+ int y = Integer.parseInt(str1);
+
+ Random rnd = Utils.getRandomInstance();
+ if (rnd.nextDouble() > 0.2) {
+ return y / (int) x;
+ } else {
+ return x / y;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DummyInterface.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+package compiler.jvmci.compilerToVM;
+
+interface DummyInterface {
+ void dummyFunction();
+
+ default int dummyDefaultFunction(int x, int y) {
+ int z = x * y;
+ return (int) (Math.cos(x - y + z) * 100);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,175 @@
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Pair;
+import sun.hotspot.code.NMethod;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/*
+ * @test
+ * @bug 8136421
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
+ */
+
+public class ExecuteInstalledCodeTest {
+
+
+ public static void main(String[] args) {
+ ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest();
+ List<CompileCodeTestCase> testCases = new ArrayList<>();
+ testCases.addAll(CompileCodeTestCase.generate(/* bci = */ -1));
+ testCases .stream()
+ // ignore <init> of abstract class -- 8138793
+ .filter(e -> !(e.executable instanceof Constructor
+ && Modifier.isAbstract(
+ e.executable.getDeclaringClass()
+ .getModifiers())))
+ .forEach(test::checkSanity);
+ }
+
+ private void checkSanity(CompileCodeTestCase testCase) {
+ System.out.println(testCase);
+ // to have a clean state
+ testCase.deoptimize();
+ Pair<Object, ? extends Throwable> reflectionResult;
+ Object[] args = getArguments(testCase.executable);
+ reflectionResult = invoke(testCase, args);
+ NMethod nMethod = testCase.compile();
+ if (nMethod == null) {
+ throw new Error(testCase + " : nmethod is null");
+ }
+ InstalledCode installedCode = new InstalledCode(
+ testCase.executable.getName());
+ installedCode.setAddress(nMethod.address);
+ Object result = null;
+ Throwable expectedException = reflectionResult.second;
+ boolean gotException = true;
+ try {
+ args = addReceiver(testCase, args);
+ result = CompilerToVMHelper.executeInstalledCode(
+ args, installedCode);
+ if (testCase.executable instanceof Constructor) {
+ // <init> doesn't have return value, it changes receiver
+ result = args[0];
+ }
+ gotException = false;
+ } catch (InvalidInstalledCodeException e) {
+ throw new AssertionError(
+ testCase + " : unexpected InvalidInstalledCodeException", e);
+ } catch (Throwable t) {
+ if (expectedException == null) {
+ throw new AssertionError(testCase
+ + " : got unexpected execption : " + t.getMessage(), t);
+ }
+
+ if (expectedException.getClass() != t.getClass()) {
+ System.err.println("exception from CompilerToVM:");
+ t.printStackTrace();
+ System.err.println("exception from reflection:");
+ expectedException.printStackTrace();
+ throw new AssertionError(String.format(
+ "%s : got unexpected different exceptions : %s != %s",
+ testCase, expectedException.getClass(), t.getClass()));
+ }
+ }
+
+ Asserts.assertEQ(reflectionResult.first, result, testCase
+ + " : different return value");
+ if (!gotException) {
+ Asserts.assertNull(expectedException, testCase
+ + " : expected exception hasn't been thrown");
+ }
+ }
+
+ private Object[] addReceiver(CompileCodeTestCase testCase, Object[] args) {
+ if (!Modifier.isStatic(testCase.executable.getModifiers())) {
+ // add instance as 0th arg
+ Object[] newArgs = new Object[args.length + 1];
+ newArgs[0] = getReciever(testCase);
+ System.arraycopy(args, 0, newArgs, 1, args.length);
+ args = newArgs;
+ }
+ return args;
+ }
+
+ private Object getReciever(CompileCodeTestCase testCase) {
+ return CompileCodeTestCase.RECEIVERS.get(
+ testCase.executable.getDeclaringClass());
+ }
+
+ public Pair<Object, ? extends Throwable> invoke(
+ CompileCodeTestCase testCase, Object[] args) {
+ Executable executable = testCase.executable;
+ boolean old = executable.isAccessible();
+ executable.setAccessible(true);
+ try {
+ try {
+ if (executable instanceof Method) {
+ Method m = (Method) executable;
+ return new Pair<>(m.invoke(getReciever(testCase), args), null);
+ }
+
+ if (executable instanceof Constructor) {
+ Constructor c = (Constructor) executable;
+ return new Pair<>(c.newInstance(args), null);
+ }
+ } catch (InvocationTargetException e) {
+ return new Pair<>(null, e.getCause());
+ } catch (Throwable e) {
+ return new Pair<>(null, e);
+ }
+ } finally {
+ executable.setAccessible(old);
+ }
+ throw new Error(executable + " has unsupported type "
+ + executable.getClass());
+ }
+
+ private Object[] getArguments(Executable method) {
+ Class<?>[] params = method.getParameterTypes();
+ Object[] result = new Object[params.length];
+ int i = 0;
+ for (Class<?> aClass : params) {
+ result[i++] = getArgument(aClass);
+ }
+ return result;
+ }
+ private static Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>();
+ static {
+ DEFAULT_VALUES.put(boolean.class, false);
+ DEFAULT_VALUES.put(byte.class, (byte) 0);
+ DEFAULT_VALUES.put(short.class, (short) 0);
+ DEFAULT_VALUES.put(char.class, '\0');
+ DEFAULT_VALUES.put(int.class, 0);
+ DEFAULT_VALUES.put(long.class, 0L);
+ DEFAULT_VALUES.put(float.class, 0.0f);
+ DEFAULT_VALUES.put(double.class, 0.0d);
+ }
+ private Object getArgument(Class<?> aClass) {
+ if (aClass.isPrimitive()) {
+ return DEFAULT_VALUES.get(aClass);
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class FindUniqueConcreteMethodTest {
+ public static void main(String args[]) {
+ FindUniqueConcreteMethodTest test = new FindUniqueConcreteMethodTest();
+ try {
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find method", e);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ // a public method
+ result.add(new TestCase(true, SingleSubclass.class,
+ SingleSubclass.class, "usualMethod"));
+ // overriden method
+ result.add(new TestCase(true, SingleSubclass.class,
+ SingleSubclass.class, "overridenMethod"));
+ // private method
+ result.add(new TestCase(true, SingleSubclass.class,
+ SingleSubclass.class, "privateMethod"));
+ // protected method
+ result.add(new TestCase(true, SingleSubclass.class,
+ SingleSubclass.class, "protectedMethod"));
+ // default(package-private) method
+ result.add(new TestCase(true, SingleSubclass.class,
+ SingleSubclass.class, "defaultAccessMethod"));
+ // default interface method redefined in implementer
+ result.add(new TestCase(true, MultipleImplementer1.class,
+ MultipleImplementer1.class, "defaultMethod"));
+ // interface method
+ result.add(new TestCase(true, MultipleImplementer1.class,
+ MultipleImplementer1.class, "testMethod"));
+ // default interface method not redefined in implementer
+ result.add(new TestCase(true, SingleImplementer.class,
+ SingleImplementerInterface.class, "defaultMethod"));
+ // static method
+ result.add(new TestCase(false, SingleSubclass.class,
+ SingleSubclass.class, "staticMethod"));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) throws NoSuchMethodException {
+ System.out.println(tcase);
+ Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
+ HotSpotResolvedJavaMethodImpl testMethod = CTVMUtilities
+ .getResolvedMethod(tcase.reciever, method);
+ HotSpotResolvedObjectTypeImpl resolvedType = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.reciever), getClass(),
+ /* resolve = */ true);
+ HotSpotResolvedJavaMethodImpl concreteMethod = CompilerToVMHelper
+ .findUniqueConcreteMethod(resolvedType, testMethod);
+ Asserts.assertEQ(concreteMethod, tcase.isPositive ? testMethod : null,
+ "Unexpected concrete method for " + tcase.methodName);
+ }
+
+ private static class TestCase {
+ public final Class<?> reciever;
+ public final Class<?> holder;
+ public final String methodName;
+ public final boolean isPositive;
+
+ public TestCase(boolean isPositive, Class<?> clazz, Class<?> holder,
+ String methodName) {
+ this.reciever = clazz;
+ this.methodName = methodName;
+ this.isPositive = isPositive;
+ this.holder = holder;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CASE: reciever=%s, holder=%s, method=%s,"
+ + " isPositive=%s", reciever.getName(),
+ holder.getName(), methodName, isPositive);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.GetBytecodeTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.TestCase;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Modifier;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.test.lib.Asserts;
+
+public class GetBytecodeTest {
+
+ public static void main(String[] args) {
+ TestCase.getAllExecutables()
+ .forEach(GetBytecodeTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ byte[] bytecode = CompilerToVMHelper.getBytecode(method);
+
+ int mods = aMethod.getModifiers();
+ boolean shouldHasZeroLength = Modifier.isAbstract(mods)
+ || Modifier.isNative(mods);
+ boolean correctLength = (bytecode.length == 0 && shouldHasZeroLength)
+ || (bytecode.length > 0 && !shouldHasZeroLength);
+
+ Asserts.assertTrue(correctLength, "Bytecode of '" + aMethod + "' has "
+ + bytecode.length + " length");
+
+ if (!shouldHasZeroLength) {
+ Asserts.assertTrue(containsReturn(bytecode), "Bytecode of '"
+ + aMethod + "' doesn't have any return statement");
+ }
+ }
+
+ private static boolean containsReturn(byte[] bytecode) {
+ for (byte b : bytecode) {
+ // cast unsigned byte to int
+ int value = (int) b & 0x000000FF;
+ switch (value) {
+ case Opcodes.RET:
+ case Opcodes.ARETURN:
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.RETURN:
+ return true;
+ }
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetClassInitializerTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetClassInitializerTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.AbstractClassExtender;
+import compiler.jvmci.common.testcases.DoNotExtendClass;
+import compiler.jvmci.common.testcases.MultipleImplementersInterfaceExtender;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class GetClassInitializerTest {
+
+ public static void main(String args[]) {
+ GetClassInitializerTest test = new GetClassInitializerTest();
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ // a simple class with initializer
+ result.add(new TestCase(SingleImplementer.class, true));
+ // an interface with initializer
+ result.add(new TestCase(SingleImplementerInterface.class, true));
+ // an abstract class with initializer
+ result.add(new TestCase(AbstractClass.class, true));
+ // a class without initializer, extending class with initializer
+ result.add(new TestCase(AbstractClassExtender.class, false));
+ // an interface without initializer
+ result.add(new TestCase(MultipleImplementersInterfaceExtender.class, false));
+ // a class without initializer
+ result.add(new TestCase(DoNotExtendClass.class, false));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) {
+ System.out.println(tcase);
+ String className = tcase.holder.getName();
+ HotSpotResolvedObjectTypeImpl resolvedClazz = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.holder),
+ getClass(), /* resolve = */ true);
+ HotSpotResolvedJavaMethodImpl initializer = CompilerToVMHelper
+ .getClassInitializer(resolvedClazz);
+ if (tcase.isPositive) {
+ Asserts.assertNotNull(initializer, "Couldn't get initializer for "
+ + className);
+ Asserts.assertEQ(initializer.getName(), "<clinit>",
+ "Unexpected initializer name for " + className);
+ } else {
+ Asserts.assertNull(initializer, "Unexpected: found initializer for "
+ + className);
+ }
+ }
+
+ private static class TestCase {
+ public final Class<?> holder;
+ public final boolean isPositive;
+
+ public TestCase(Class<?> clazz, boolean isPositive) {
+ this.holder = clazz;
+ this.isPositive = isPositive;
+ }
+
+ @Override
+ public String toString() {
+ return "CASE: clazz=" + holder.getName()
+ + ", isPositive=" + isPositive;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.GetConstantPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetConstantPoolTest
+ */
+package compiler.jvmci.compilerToVM;
+
+import java.lang.reflect.Field;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+
+/**
+ * Tests for jdk.vm.ci.hotspot.CompilerToVM::getConstantPool method
+ */
+public class GetConstantPoolTest {
+ private static enum TestCase {
+ NULL_BASE {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ return CompilerToVMHelper.getConstantPool(null,
+ getPtrToCpAddress());
+ }
+ },
+ JAVA_METHOD_BASE {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ HotSpotResolvedJavaMethodImpl methodInstance
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
+ TEST_CLASS, 0);
+ Field field;
+ try {
+ field = HotSpotResolvedJavaMethodImpl
+ .class.getDeclaredField("metaspaceMethod");
+ field.setAccessible(true);
+ field.set(methodInstance, getPtrToCpAddress());
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+
+ return CompilerToVMHelper.getConstantPool(methodInstance, 0L);
+ }
+ },
+ CONSTANT_POOL_BASE {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ HotSpotConstantPool cpInst;
+ try {
+ cpInst = CompilerToVMHelper.getConstantPool(null,
+ getPtrToCpAddress());
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, getPtrToCpAddress());
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getConstantPool(cpInst, 0L);
+ }
+ },
+ CONSTANT_POOL_BASE_IN_TWO {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ long ptr = getPtrToCpAddress();
+ HotSpotConstantPool cpInst;
+ try {
+ cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, ptr / 2L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getConstantPool(cpInst,
+ ptr - ptr / 2L);
+ }
+ },
+ CONSTANT_POOL_BASE_ZERO {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ long ptr = getPtrToCpAddress();
+ HotSpotConstantPool cpInst;
+ try {
+ cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, 0L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getConstantPool(cpInst, ptr);
+ }
+ },
+ OBJECT_TYPE_BASE {
+ @Override
+ HotSpotConstantPool getConstantPool() {
+ HotSpotResolvedObjectTypeImpl type
+ = HotSpotResolvedObjectTypeImpl.fromObjectClass(
+ OBJECT_TYPE_BASE.getClass());
+ long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE);
+ return CompilerToVMHelper.getConstantPool(type,
+ getPtrToCpAddress() - ptrToClass);
+ }
+ },
+ ;
+ abstract HotSpotConstantPool getConstantPool();
+ }
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+ private static final Class TEST_CLASS = GetConstantPoolTest.class;
+ private static final long CP_ADDRESS
+ = WB.getConstantPool(GetConstantPoolTest.class);
+
+ public void test(TestCase testCase) {
+ System.out.println(testCase.name());
+ HotSpotConstantPool cp = testCase.getConstantPool();
+ String cpStringRep = cp.toString();
+ if (!cpStringRep.contains(HotSpotConstantPool.class.getSimpleName())
+ || !cpStringRep.contains(TEST_CLASS.getName())) {
+ String msg = String.format("%s : "
+ + " Constant pool is not valid."
+ + " String representation should contain \"%s\" and \"%s\"",
+ testCase.name(),
+ HotSpotConstantPool.class.getSimpleName(),
+ TEST_CLASS.getName());
+ throw new AssertionError(msg);
+ }
+ }
+
+ public static void main(String[] args) {
+ GetConstantPoolTest test = new GetConstantPoolTest();
+ for (TestCase testCase : TestCase.values()) {
+ test.test(testCase);
+ }
+ testObjectBase();
+ testMetaspaceWrapperBase();
+ }
+
+ private static void testObjectBase() {
+ try {
+ HotSpotConstantPool cp
+ = CompilerToVMHelper.getConstantPool(new Object(), 0L);
+ throw new AssertionError("Test OBJECT_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+ private static void testMetaspaceWrapperBase() {
+ try {
+ HotSpotConstantPool cp = CompilerToVMHelper.getConstantPool(
+ new MetaspaceWrapperObject() {
+ @Override
+ public long getMetaspacePointer() {
+ return getPtrToCpAddress();
+ }
+ }, 0L);
+ throw new AssertionError("Test METASPACE_WRAPPER_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ private static long getPtrToCpAddress() {
+ Field field;
+ try {
+ field = TEST_CLASS.getDeclaredField("CP_ADDRESS");
+ } catch (NoSuchFieldException nsfe) {
+ throw new Error("TESTBUG : cannot find field \"CP_ADDRESS\" : "
+ + nsfe.getMessage(), nsfe);
+ }
+ Object base = UNSAFE.staticFieldBase(field);
+ return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.GetExceptionTableTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.io.IOException;
+import java.lang.reflect.Executable;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class GetExceptionTableTest {
+
+ public static final int TRY_CATCH_COUNT = 3;
+ public static final int TRY_CATCH_FINALLY_COUNT = 8;
+ public static final int TRY_WITH_RESOURCES_COUNT = 6;
+ public static final int EMPTY_COUNT = 0;
+
+ public static void main(String[] args) {
+ Map<Executable, Integer> testCases = createTestCases();
+ testCases.forEach(GetExceptionTableTest::runSanityTest);
+ }
+
+ private static Map<Executable, Integer> createTestCases() {
+ HashMap<Executable, Integer> methods = new HashMap<>();
+ try {
+ Class<?> aClass = GetExceptionTableTest.DummyClass.class;
+ methods.put(aClass.getMethod("tryCatchDummy"), TRY_CATCH_COUNT);
+ methods.put(aClass.getMethod("tryCatchFinallyDummy"),
+ TRY_CATCH_FINALLY_COUNT);
+ methods.put(aClass.getMethod("tryWithResourcesDummy"),
+ TRY_WITH_RESOURCES_COUNT);
+ methods.put(aClass.getMethod("emptyFunction"), EMPTY_COUNT);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG", e);
+ }
+ return methods;
+ }
+
+ private static void runSanityTest(Executable aMethod,
+ Integer expectedTableLength) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ int tableLength = CompilerToVMHelper.getExceptionTableLength(method);
+ Asserts.assertEQ(tableLength, expectedTableLength, aMethod
+ + " incorrect exception table length.");
+
+ long tableStart = CompilerToVMHelper.getExceptionTableStart(method);
+ if (tableLength > 0) {
+ Asserts.assertNE(tableStart, 0L, aMethod + " exception table starts "
+ + "at 0.");
+ }
+ }
+
+ private static class DummyClass {
+ public static void emptyFunction() {}
+ public static void tryCatchDummy() throws Throwable {
+ try {
+ throw new Exception("Dummy exception");
+ } catch (ArithmeticException ex) {
+ throw new IOException(ex.getMessage());
+ } catch (IOException ex) {
+ throw new Exception(ex);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ public int tryCatchFinallyDummy() {
+ // 4 times catch/finally = 8 catch-blocks and finally-blocks
+ try {
+ throw new Exception("Dummy exception");
+ } catch (IndexOutOfBoundsException ex) {
+ return 1;
+ } catch (ArithmeticException ex) {
+ return 2;
+ } catch (IOException ex) {
+ return 3;
+ } catch (Exception ex) {
+ return 4;
+ } finally {
+ return 0;
+ }
+ }
+
+ public static int tryWithResourcesDummy() throws Throwable {
+ try (Socket socket = new Socket()) {
+ throw new Exception("Dummy exception");
+ } catch (ArithmeticException ex) {
+ return 1;
+ } catch (IOException ex) {
+ return 2;
+ } catch (Exception ex) {
+ return 3;
+ }
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib/
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetImplementorTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetImplementorTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.AbstractClassExtender;
+import compiler.jvmci.common.testcases.DoNotImplementInterface;
+import compiler.jvmci.common.testcases.DoNotExtendClass;
+import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.MultipleImplementer2;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import compiler.jvmci.common.testcases.SingleSubclassedClass;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class GetImplementorTest {
+ public static void main(String args[]) {
+ GetImplementorTest test = new GetImplementorTest();
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ Stream.of(
+ SingleSubclass.class,
+ AbstractClassExtender.class,
+ MultipleImplementer2.class,
+ MultipleImplementer1.class,
+ MultipleImplementersInterface.class,
+ DoNotImplementInterface.class,
+ DoNotExtendClass.class,
+ AbstractClass.class,
+ SingleSubclassedClass.class)
+ .forEach(Utils::ensureClassIsLoaded);
+ // an interface with single class implementing it
+ result.add(new TestCase(SingleImplementerInterface.class,
+ SingleImplementer.class));
+ /* an interface with multiple implementers. According to getImplementor
+ javadoc, an itself should be returned in case of more than one
+ implementor
+ */
+ result.add(new TestCase(MultipleImplementersInterface.class,
+ MultipleImplementersInterface.class));
+ // an interface with no implementors
+ result.add(new TestCase(DoNotImplementInterface.class, null));
+ // an abstract class with extender class
+ result.add(new TestCase(AbstractClass.class, null));
+ // a simple class, which is not extended
+ result.add(new TestCase(DoNotExtendClass.class, null));
+ // a usual class, which is extended
+ result.add(new TestCase(SingleSubclassedClass.class, null));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) {
+ System.out.println(tcase);
+ HotSpotResolvedObjectTypeImpl resolvedIface = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.anInterface),
+ getClass(), /* resolve = */ true);
+ HotSpotResolvedObjectTypeImpl resolvedImplementer = CompilerToVMHelper
+ .getImplementor(resolvedIface);
+ HotSpotResolvedObjectTypeImpl resolvedExpected = null;
+ if (tcase.expectedImplementer != null) {
+ resolvedExpected = CompilerToVMHelper.lookupType(Utils
+ .toJVMTypeSignature(tcase.expectedImplementer),
+ getClass(), /* resolve = */ true);
+ }
+ Asserts.assertEQ(resolvedImplementer, resolvedExpected,
+ "Unexpected implementer for " + tcase.anInterface.getName());
+ }
+
+ private static class TestCase {
+ public final Class<?> anInterface;
+ public final Class<?> expectedImplementer;
+
+ public TestCase(Class<?> iface, Class<?> expectedImplementer) {
+ this.anInterface = iface;
+ this.expectedImplementer = expectedImplementer;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CASE: interface=%s, expected=%s",
+ anInterface.getName(),
+ expectedImplementer == null
+ ? null
+ : expectedImplementer.getName());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.GetLineNumberTableTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.TestCase;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class GetLineNumberTableTest {
+ public static void main(String[] args) {
+ TestCase.getAllExecutables()
+ .forEach(GetLineNumberTableTest::runSanityTest);
+ }
+
+ public static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ long[] lineNumbers = CompilerToVMHelper.getLineNumberTable(method);
+ long[] expectedLineNumbers = getExpectedLineNumbers(aMethod);
+
+ Asserts.assertTrue(Arrays.equals(lineNumbers, expectedLineNumbers),
+ String.format("%s : unequal table values : %n%s%n%s%n",
+ aMethod,
+ Arrays.toString(lineNumbers),
+ Arrays.toString(expectedLineNumbers)));
+ }
+
+ public static long[] getExpectedLineNumbers(Executable aMethod) {
+ try {
+ ClassReader cr = new ClassReader(aMethod.getDeclaringClass()
+ .getName());
+ ClassNode cn = new ClassNode();
+ cr.accept(cn, ClassReader.EXPAND_FRAMES);
+
+ Map<Label, Integer> lineNumbers = new HashMap<>();
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ ClassVisitor cv = new ClassVisitorForLabels(cw, lineNumbers,
+ aMethod);
+ cr.accept(cv, ClassReader.EXPAND_FRAMES);
+
+ long[] result = null;
+ if (!lineNumbers.isEmpty()) {
+ Map<Integer, Integer> labels = new TreeMap<>();
+ lineNumbers.forEach((k, v) -> labels.put(k.getOffset(), v));
+
+ result = new long[2 * labels.size()];
+ int i = 0;
+ for (Integer key : labels.keySet()) {
+ result[i++] = key.longValue();
+ result[i++] = labels.get(key).longValue();
+ }
+ }
+ // compilerToVM::getLineNumberTable returns null in case empty table
+ return result;
+ } catch (IOException e) {
+ throw new Error("TEST BUG " + e, e);
+ }
+ }
+
+ private static class ClassVisitorForLabels extends ClassVisitor {
+ private final Map<Label, Integer> lineNumbers;
+ private final String targetName;
+ private final String targetDesc;
+
+ public ClassVisitorForLabels(ClassWriter cw, Map<Label, Integer> lines,
+ Executable target) {
+ super(Opcodes.ASM5, cw);
+ this.lineNumbers = lines;
+
+ StringBuilder builder = new StringBuilder("(");
+ for (Parameter parameter : target.getParameters()) {
+ builder.append(Utils.toJVMTypeSignature(parameter.getType()));
+ }
+ builder.append(")");
+ if (target instanceof Constructor) {
+ targetName = "<init>";
+ builder.append("V");
+ } else {
+ targetName = target.getName();
+ builder.append(Utils.toJVMTypeSignature(
+ ((Method) target).getReturnType()));
+ }
+ targetDesc = builder.toString();
+ }
+
+ @Override
+ public final MethodVisitor visitMethod(int access, String name,
+ String desc, String signature,
+ String[] exceptions) {
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
+ exceptions);
+ if (targetDesc.equals(desc) && targetName.equals(name)) {
+ return new MethodVisitor(Opcodes.ASM5, mv) {
+ @Override
+ public void visitLineNumber(int i, Label label) {
+ super.visitLineNumber(i, label);
+ lineNumbers.put(label, i);
+ }
+ };
+ }
+ return mv;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @clean compiler.jvmci.compilerToVM.*
+ * @compile -g DummyInterface.java
+ * @compile -g DummyAbstractClass.java
+ * @compile -g DummyClass.java
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.GetLocalVariableTableTest
+ * @clean compiler.jvmci.compilerToVM.*
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+import java.lang.reflect.Executable;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetLocalVariableTableTest {
+
+ public static final int MAIN_LOCALS_COUNT = 0;
+ public static final int INSTANCE_LOCALS_COUNT = 4;
+ public static final int EMPTY_INSTANCE_COUNT = 1;
+ public static final int EMPTY_STATIC_COUNT = 0;
+ public static final int ABSTRACT_INHERIT_LOCALS_COUNT = 2;
+ public static final int DEFAULTFUNC_LOCALS_COUNT = 4;
+
+ public static void main(String[] args) {
+ Map<Executable, Integer> testCases = createTestCases();
+ testCases.forEach(GetLocalVariableTableTest::runSanityTest);
+ }
+
+ private static Map<Executable, Integer> createTestCases() {
+ HashMap<Executable, Integer> methods = new HashMap<>();
+ try {
+ Class<?> aClass;
+
+ aClass = GetLocalVariableTableTest.class;
+ methods.put(aClass.getDeclaredMethod("main", String[].class),
+ MAIN_LOCALS_COUNT);
+
+ aClass = DummyClass.class;
+ methods.put(aClass.getMethod("dummyInstanceFunction"),
+ INSTANCE_LOCALS_COUNT);
+ methods.put(aClass.getMethod("dummyEmptyInstanceFunction"),
+ EMPTY_INSTANCE_COUNT);
+ methods.put(aClass.getMethod("dummyEmptyStaticFunction"),
+ EMPTY_STATIC_COUNT);
+ methods.put(aClass.getMethod("dummyFunction"),
+ EMPTY_INSTANCE_COUNT);
+ methods.put(aClass.getMethod("dummyAbstractFunction"),
+ ABSTRACT_INHERIT_LOCALS_COUNT);
+
+ aClass = DummyInterface.class;
+ methods.put(aClass.getMethod("dummyFunction"), EMPTY_STATIC_COUNT);
+ methods.put(aClass.getMethod("dummyDefaultFunction", int.class,
+ int.class), DEFAULTFUNC_LOCALS_COUNT);
+
+ aClass = DummyAbstractClass.class;
+ methods.put(aClass.getMethod("dummyAbstractFunction"), 0);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG", e);
+ }
+ return methods;
+ }
+
+ private static void runSanityTest(Executable aMethod,
+ Integer expectedTableLength) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+
+ int tblLength = CompilerToVMHelper.getLocalVariableTableLength(method);
+ Asserts.assertEQ(tblLength, expectedTableLength, aMethod + " : incorrect "
+ + "local variable table length.");
+
+ long tblStart = CompilerToVMHelper.getLocalVariableTableStart(method);
+ if (tblLength > 0) {
+ Asserts.assertNE(tblStart, 0L, aMethod + " : local variable table starts"
+ + " at 0 with length " + tblLength);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib/
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class GetMaxCallTargetOffsetTest {
+ public static void main(String args[]) {
+ new GetMaxCallTargetOffsetTest().runTest();
+ }
+
+ private void runTest() {
+ long offset1 = CompilerToVMHelper.getMaxCallTargetOffset(0L);
+ Asserts.assertNE(offset1, 0L,
+ "Unexpected maxCallTargetOffset for 0L");
+ long offset2 = CompilerToVMHelper.getMaxCallTargetOffset(100L);
+ Asserts.assertNE(offset2, 0L,
+ "Unexpected maxCallTargetOffset for 100L");
+ long offset3 = CompilerToVMHelper.getMaxCallTargetOffset(1000000L);
+ Asserts.assertNE(offset3, 0L,
+ "Unexpected maxCallTargetOffset for 1000000L");
+ // there can be 2 same offsets, but not 3
+ Asserts.assertFalse(offset1 == offset2 && offset2 == offset3,
+ "All 3 offsets are unexpectedly equal: " + offset1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetNextStackFrameTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Method;
+import jdk.vm.ci.hotspot.CompilerToVM;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotStackFrameReference;
+import jdk.test.lib.Asserts;
+
+public class GetNextStackFrameTest {
+ private static final int RECURSION_AMOUNT = 3;
+ private static final HotSpotResolvedJavaMethodImpl REC_FRAME_METHOD;
+ private static final HotSpotResolvedJavaMethodImpl FRAME1_METHOD;
+ private static final HotSpotResolvedJavaMethodImpl FRAME2_METHOD;
+ private static final HotSpotResolvedJavaMethodImpl FRAME3_METHOD;
+ private static final HotSpotResolvedJavaMethodImpl FRAME4_METHOD;
+ private static final HotSpotResolvedJavaMethodImpl RUN_METHOD;
+
+ static {
+ Method method;
+ try {
+ Class<?> aClass = GetNextStackFrameTest.class;
+ method = aClass.getDeclaredMethod("recursiveFrame", int.class);
+ REC_FRAME_METHOD = CTVMUtilities.getResolvedMethod(method);
+ method = aClass.getDeclaredMethod("frame1");
+ FRAME1_METHOD = CTVMUtilities.getResolvedMethod(method);
+ method = aClass.getDeclaredMethod("frame2");
+ FRAME2_METHOD = CTVMUtilities.getResolvedMethod(method);
+ method = aClass.getDeclaredMethod("frame3");
+ FRAME3_METHOD = CTVMUtilities.getResolvedMethod(method);
+ method = aClass.getDeclaredMethod("frame4");
+ FRAME4_METHOD = CTVMUtilities.getResolvedMethod(method);
+ method = Thread.class.getDeclaredMethod("run");
+ RUN_METHOD = CTVMUtilities.getResolvedMethod(Thread.class, method);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find a test method", e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new GetNextStackFrameTest().test();
+ }
+
+ private void test() {
+ // Create new thread to get new clean stack
+ Thread thread = new Thread(() -> recursiveFrame(RECURSION_AMOUNT));
+ thread.start();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new Error("Interrupted while waiting to join", e);
+ }
+ }
+
+ // Helper methods for a longer stack
+ private void recursiveFrame(int recursionAmount) {
+ if (--recursionAmount != 0) {
+ recursiveFrame(recursionAmount);
+ } else {
+ frame1();
+ }
+ }
+
+ private void frame1() {
+ frame2();
+ }
+
+ private void frame2() {
+ frame3();
+ }
+
+ private void frame3() {
+ frame4();
+ }
+
+ private void frame4() {
+ check();
+ }
+
+ private void check() {
+ findFirst();
+ walkThrough();
+ skipAll();
+ findNextSkipped();
+ findYourself();
+ }
+
+ /**
+ * Finds the first topmost frame from the list of methods to search
+ */
+ private void findFirst() {
+ checkNextFrameFor(null /* topmost frame */,
+ new HotSpotResolvedJavaMethodImpl[]
+ {FRAME2_METHOD, FRAME3_METHOD, FRAME4_METHOD},
+ FRAME4_METHOD, 0);
+ }
+
+ /**
+ * Walks through whole stack and checks that every frame could be found
+ * while going down the stack till the end
+ */
+ private void walkThrough() {
+ // Check that we would get a frame 4 starting from the topmost frame
+ HotSpotStackFrameReference nextStackFrame = checkNextFrameFor(
+ null /* topmost frame */,
+ new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD},
+ FRAME4_METHOD, 0);
+ // Check that we would get a frame 3 starting from frame 4 when we try
+ // to search one of the next two frames
+ nextStackFrame = checkNextFrameFor(nextStackFrame,
+ new HotSpotResolvedJavaMethodImpl[] {FRAME3_METHOD,
+ FRAME2_METHOD},
+ FRAME3_METHOD, 0);
+ // Check that we would get a frame 1
+ nextStackFrame = checkNextFrameFor(nextStackFrame,
+ new HotSpotResolvedJavaMethodImpl[] {FRAME1_METHOD},
+ FRAME1_METHOD, 0);
+ // Check that we would skip (RECURSION_AMOUNT - 1) methods and find a
+ // recursionFrame starting from frame 1
+ nextStackFrame = checkNextFrameFor(nextStackFrame,
+ new HotSpotResolvedJavaMethodImpl[] {REC_FRAME_METHOD},
+ REC_FRAME_METHOD, RECURSION_AMOUNT - 1);
+ // Check that we would get a Thread::run method frame;
+ nextStackFrame = checkNextFrameFor(nextStackFrame,
+ new HotSpotResolvedJavaMethodImpl[] {RUN_METHOD},
+ RUN_METHOD, 0);
+ // Check that there are no more frames after thread's run method
+ nextStackFrame = CompilerToVMHelper.getNextStackFrame(nextStackFrame,
+ null /* any */, 0);
+ Asserts.assertNull(nextStackFrame,
+ "Found stack frame after Thread::run");
+ }
+
+ /**
+ * Skips all frames to get null at the end of the stack
+ */
+ private void skipAll() {
+ // Skip all frames (stack size) + 2 (getNextStackFrame() itself
+ // and from CompilerToVMHelper)
+ int initialSkip = Thread.currentThread().getStackTrace().length + 2;
+ HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper
+ .getNextStackFrame(null /* topmost frame */, null /* any */,
+ initialSkip);
+ Asserts.assertNull(nextStackFrame, "Unexpected frame");
+ }
+
+ /**
+ * Search for any frame skipping one frame
+ */
+ private void findNextSkipped() {
+ // Get frame 4
+ HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper
+ .getNextStackFrame(null /* topmost frame */,
+ new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD}, 0);
+ // Get frame 2 by skipping one method starting from frame 4
+ checkNextFrameFor(nextStackFrame, null /* any */,
+ FRAME2_METHOD , 1 /* skip one */);
+ }
+
+ /**
+ * Finds test method in the stack
+ */
+ private void findYourself() {
+ Method method;
+ try {
+ method = CompilerToVM.class.getDeclaredMethod("getNextStackFrame",
+ HotSpotStackFrameReference.class,
+ HotSpotResolvedJavaMethodImpl[].class, int.class);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find getNextStackFrame method");
+ }
+ HotSpotResolvedJavaMethodImpl self
+ = CTVMUtilities.getResolvedMethod(CompilerToVM.class, method);
+ checkNextFrameFor(null /* topmost frame */, null /* any */, self, 0);
+ }
+
+ /**
+ * Searches next frame and checks that it equals to expected
+ *
+ * @param currentFrame start frame to search from
+ * @param searchMethods a list of methods to search
+ * @param expected expected frame
+ * @param skip amount of frames to be skipped
+ * @return frame reference
+ */
+ private HotSpotStackFrameReference checkNextFrameFor(
+ HotSpotStackFrameReference currentFrame,
+ HotSpotResolvedJavaMethodImpl[] searchMethods,
+ HotSpotResolvedJavaMethodImpl expected,
+ int skip) {
+ HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper
+ .getNextStackFrame(currentFrame, searchMethods, skip);
+ Asserts.assertNotNull(nextStackFrame);
+ Asserts.assertTrue(nextStackFrame.isMethod(expected),
+ "Unexpected next frame: " + nextStackFrame
+ + " from current frame: " + currentFrame);
+ return nextStackFrame;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.GetResolvedJavaMethodAtSlotTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetResolvedJavaMethodAtSlotTest {
+
+ private static class A {
+ {
+ System.out.println("Dummy");
+ }
+ public void f1() {}
+ public int f2() { return 0; }
+ public String f3() { return ""; }
+ }
+
+
+ private static class S {
+ static {
+ System.out.println("Dummy static");
+ }
+ public S() {}
+ public void f1() {}
+ public int f2() { return 0; }
+ public String f3() { return ""; }
+ }
+
+ private class B extends A {
+ public void f4() {}
+ }
+
+ private interface I {
+ void f1();
+ int f2();
+ String f3();
+ }
+
+ public static void main(String[] args) {
+ Map<Class<?>, Integer> testCases = getTestCases();
+ testCases.forEach(GetResolvedJavaMethodAtSlotTest::test);
+ }
+
+ private static Map<Class<?>, Integer> getTestCases() {
+ Map<Class<?>, Integer> testCases = new HashMap<>();
+ testCases.put(A.class, 5); // ctor, init, f1, f2, f3
+ testCases.put(S.class, 5); // ctor, cinit, f1, f2, f3
+ testCases.put(I.class, 3); // f1, f2, f3
+ testCases.put(B.class, 2); // ctor, f4
+ return testCases;
+ }
+
+ private static void test(Class<?> aClass, int methodNumber) {
+ testSlotBigger(aClass);
+ testCorrectMethods(aClass, methodNumber);
+ }
+
+ private static void testSlotBigger(Class<?> holder) {
+ HotSpotResolvedJavaMethodImpl method
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(holder, 50);
+ Asserts.assertNull(method, "Got method for non existing slot 50 in "
+ + holder);
+ }
+
+ private static void testCorrectMethods(Class<?> holder, int methodsNumber) {
+ for (int i = 0; i < methodsNumber; i++) {
+ HotSpotResolvedJavaMethodImpl method = CompilerToVMHelper
+ .getResolvedJavaMethodAtSlot(holder, i);
+ Asserts.assertNotNull(method, "Did not got method for slot " + i
+ + " in class " + holder.getCanonicalName());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
+ * @run main ClassFileInstaller
+ * sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+
+public class GetResolvedJavaMethodTest {
+ private static enum TestCase {
+ NULL_BASE {
+ @Override
+ HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+ return CompilerToVMHelper.getResolvedJavaMethod(
+ null, getPtrToMethod());
+ }
+ },
+ JAVA_METHOD_BASE {
+ @Override
+ HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+ HotSpotResolvedJavaMethodImpl methodInstance
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
+ TEST_CLASS, 0);
+ Field field;
+ try {
+ field = HotSpotResolvedJavaMethodImpl
+ .class.getDeclaredField("metaspaceMethod");
+ field.setAccessible(true);
+ field.set(methodInstance, getPtrToMethod());
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TEST BUG : " + e, e);
+ }
+ return CompilerToVMHelper.getResolvedJavaMethod(
+ methodInstance, 0L);
+ }
+ },
+ JAVA_METHOD_BASE_IN_TWO {
+ @Override
+ HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+ long ptr = getPtrToMethod();
+ HotSpotResolvedJavaMethodImpl methodInstance
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
+ TEST_CLASS, 0);
+ Field field;
+ try {
+ field = HotSpotResolvedJavaMethodImpl
+ .class.getDeclaredField("metaspaceMethod");
+ field.setAccessible(true);
+ field.set(methodInstance, ptr / 2L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getResolvedJavaMethod(methodInstance,
+ ptr - ptr / 2L);
+ }
+ },
+ JAVA_METHOD_BASE_ZERO {
+ @Override
+ HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+ long ptr = getPtrToMethod();
+ HotSpotResolvedJavaMethodImpl methodInstance
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
+ TEST_CLASS, 0);
+ Field field;
+ try {
+ field = HotSpotResolvedJavaMethodImpl
+ .class.getDeclaredField("metaspaceMethod");
+ field.setAccessible(true);
+ field.set(methodInstance, 0L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getResolvedJavaMethod(methodInstance,
+ ptr);
+ }
+ }
+ ;
+ abstract HotSpotResolvedJavaMethodImpl getResolvedJavaMethod();
+ }
+
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final Class<?> TEST_CLASS = GetResolvedJavaMethodTest.class;
+ private static final long PTR;
+ static {
+ HotSpotResolvedJavaMethodImpl method
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(TEST_CLASS, 0);
+ PTR = method.getMetaspacePointer();
+ }
+
+ private static long getPtrToMethod() {
+ Field field;
+ try {
+ field = TEST_CLASS.getDeclaredField("PTR");
+ } catch (NoSuchFieldException e) {
+ throw new Error("TEST BUG : " + e, e);
+ }
+ Object base = UNSAFE.staticFieldBase(field);
+ return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
+ }
+
+ public void test(TestCase testCase) {
+ System.out.println(testCase.name());
+ HotSpotResolvedJavaMethodImpl result = testCase.getResolvedJavaMethod();
+ Asserts.assertNotNull(result, testCase + " : got null");
+ Asserts.assertEQ(result.getDeclaringClass().mirror(), TEST_CLASS,
+ testCase + " : returned method has unexpected declaring class");
+ }
+
+ public static void main(String[] args) {
+ GetResolvedJavaMethodTest test = new GetResolvedJavaMethodTest();
+ for (TestCase testCase : TestCase.values()) {
+ test.test(testCase);
+ }
+ testObjectBase();
+ testMetaspaceWrapperBase();
+ }
+
+ private static void testMetaspaceWrapperBase() {
+ try {
+ HotSpotResolvedJavaMethodImpl method
+ = CompilerToVMHelper.getResolvedJavaMethod(
+ new MetaspaceWrapperObject() {
+ @Override
+ public long getMetaspacePointer() {
+ return getPtrToMethod();
+ }
+ }, 0L);
+ throw new AssertionError("Test METASPACE_WRAPPER_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ private static void testObjectBase() {
+ try {
+ HotSpotResolvedJavaMethodImpl method
+ = CompilerToVMHelper.getResolvedJavaMethod(new Object(), 0L);
+ throw new AssertionError("Test OBJECT_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ * @run main ClassFileInstaller
+ * sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UseCompressedOops
+ * compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:-UseCompressedOops
+ * compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.lang.reflect.Field;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+
+public class GetResolvedJavaTypeTest {
+ private static enum TestCase {
+ NULL_BASE {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ return CompilerToVMHelper.getResolvedJavaType(
+ null, getPtrToKlass(), COMPRESSED);
+ }
+ },
+ JAVA_METHOD_BASE {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ HotSpotResolvedJavaMethodImpl methodInstance
+ = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
+ TEST_CLASS, 0);
+ Field field;
+ try {
+ field = HotSpotResolvedJavaMethodImpl
+ .class.getDeclaredField("metaspaceMethod");
+ field.setAccessible(true);
+ field.set(methodInstance, getPtrToKlass());
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TEST BUG : " + e, e);
+ }
+
+ return CompilerToVMHelper.getResolvedJavaType(methodInstance,
+ 0L, COMPRESSED);
+ }
+ },
+ CONSTANT_POOL_BASE {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ HotSpotConstantPool cpInst;
+ try {
+ cpInst = CompilerToVMHelper.getConstantPool(null,
+ getPtrToKlass());
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, getPtrToKlass());
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getResolvedJavaType(cpInst,
+ 0L, COMPRESSED);
+ }
+ },
+ CONSTANT_POOL_BASE_IN_TWO {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ long ptr = getPtrToKlass();
+ HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl
+ .fromObjectClass(TEST_CLASS).getConstantPool();
+ try {
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, ptr / 2L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getResolvedJavaType(cpInst,
+ ptr - ptr / 2L, COMPRESSED);
+ }
+ },
+ CONSTANT_POOL_BASE_ZERO {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ long ptr = getPtrToKlass();
+ HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl
+ .fromObjectClass(TEST_CLASS).getConstantPool();
+ try {
+ Field field = HotSpotConstantPool.class
+ .getDeclaredField("metaspaceConstantPool");
+ field.setAccessible(true);
+ field.set(cpInst, 0L);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG : " + e.getMessage(), e);
+ }
+ return CompilerToVMHelper.getResolvedJavaType(cpInst,
+ ptr, COMPRESSED);
+ }
+ },
+ OBJECT_TYPE_BASE {
+ @Override
+ HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+ HotSpotResolvedObjectTypeImpl type
+ = HotSpotResolvedObjectTypeImpl.fromObjectClass(
+ OBJECT_TYPE_BASE.getClass());
+ long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE);
+ return CompilerToVMHelper.getResolvedJavaType(type,
+ getPtrToKlass() - ptrToClass, COMPRESSED);
+ }
+ },
+ ;
+ abstract HotSpotResolvedObjectTypeImpl getResolvedJavaType();
+ }
+
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final long PTR = UNSAFE.getKlassPointer(
+ new GetResolvedJavaTypeTest());
+ private static final Class TEST_CLASS = GetResolvedJavaTypeTest.class;
+ /* a compressed parameter for tested method is set to false because
+ unsafe.getKlassPointer always returns uncompressed pointer */
+ private static final boolean COMPRESSED = false;
+ // = WB.getBooleanVMFlag("UseCompressedClassPointers");
+
+ private static long getPtrToKlass() {
+ Field field;
+ try {
+ field = TEST_CLASS.getDeclaredField("PTR");
+ } catch (NoSuchFieldException e) {
+ throw new Error("TEST BUG : " + e, e);
+ }
+ Object base = UNSAFE.staticFieldBase(field);
+ return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
+ }
+
+ public void test(TestCase testCase) {
+ System.out.println(testCase.name());
+ HotSpotResolvedObjectTypeImpl type = testCase.getResolvedJavaType();
+ Asserts.assertEQ(type.mirror(), TEST_CLASS, testCase +
+ " Unexpected Class returned by getResolvedJavaType");
+ }
+
+ public static void main(String[] args) {
+ GetResolvedJavaTypeTest test = new GetResolvedJavaTypeTest();
+ for (TestCase testCase : TestCase.values()) {
+ test.test(testCase);
+ }
+ testObjectBase();
+ testMetaspaceWrapperBase();
+ }
+
+ private static void testMetaspaceWrapperBase() {
+ try {
+ HotSpotResolvedObjectTypeImpl type
+ = CompilerToVMHelper.getResolvedJavaType(
+ new MetaspaceWrapperObject() {
+ @Override
+ public long getMetaspacePointer() {
+ return getPtrToKlass();
+ }
+ }, 0L, COMPRESSED);
+ throw new AssertionError("Test METASPACE_WRAPPER_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ private static void testObjectBase() {
+ try {
+ HotSpotResolvedObjectTypeImpl type
+ = CompilerToVMHelper.getResolvedJavaType(new Object(), 0L,
+ COMPRESSED);
+ throw new AssertionError("Test OBJECT_BASE."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:. compiler.jvmci.compilerToVM.GetStackTraceElementTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class GetStackTraceElementTest {
+
+ public static void main(String[] args) {
+ Map<Executable, int[]> testCases = createTestCases();
+ testCases.forEach(GetStackTraceElementTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod, int[] bcis) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ String className = aMethod.getDeclaringClass().getName();
+ int lastDot = className.lastIndexOf('.');
+ int firstDol = className.contains("$")
+ ? className.indexOf('$')
+ : className.length();
+ String fileName = className.substring(lastDot + 1, firstDol) + ".java";
+ for (int bci : bcis) {
+ StackTraceElement ste = CompilerToVMHelper
+ .getStackTraceElement(method, bci);
+ Asserts.assertNotNull(ste);
+ Asserts.assertEQ(ste.getClassName(), className);
+ Asserts.assertEQ(ste.getFileName(), fileName);
+ Asserts.assertEQ(ste.getMethodName(), aMethod.getName());
+ Asserts.assertEQ(ste.isNativeMethod(), Modifier
+ .isNative(aMethod.getModifiers()));
+ }
+
+ }
+
+ private static Map<Executable, int[]> createTestCases() {
+ Map<Executable, int[]> testCases = new HashMap<>();
+
+ try {
+ Class<?> aClass = DummyClass.class;
+ Method aMethod = aClass.getDeclaredMethod("dummyInstanceFunction");
+ int[] bci = new int[] {0, 2, 3, 6, 7, 8, 11, 13, 15, 16, 17, 18};
+ testCases.put(aMethod, bci);
+
+ aMethod = aClass.getDeclaredMethod("dummyEmptyFunction");
+ bci = new int[] {0};
+ testCases.put(aMethod, bci);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG : test method not found", e);
+ }
+ return testCases;
+ }
+
+ private class DummyClass {
+ public int dummyInstanceFunction() {
+ String str1 = "123123123";
+ double x = 3.14;
+ int y = Integer.parseInt(str1);
+
+ return y / (int)x;
+ }
+
+ public void dummyEmptyFunction() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetSymbolTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * compiler.jvmci.common.testcases.SingleImplementer
+ * compiler.jvmci.common.testcases.SingleImplementerInterface
+ * compiler.jvmci.compilerToVM.GetSymbolTest
+ * compiler.jvmci.common.CTVMUtilities
+ * jdk.test.lib.Utils
+ * jdk.test.lib.Asserts
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:. compiler.jvmci.compilerToVM.GetSymbolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.test.lib.Utils;
+
+public class GetSymbolTest {
+ private static final int CONSTANT_POOL_UTF8_TAG = 1; // see jvms, section 4.4
+
+ private static final Function<Member[], List<String>> NAMES = members ->
+ Stream.of(members)
+ .map(Member::getName)
+ .collect(Collectors.toList());
+
+ public static void main(String[] args) {
+ new GetSymbolTest().test(SingleImplementer.class);
+ }
+
+ private void test(Class<?> aClass) {
+ Utils.ensureClassIsLoaded(aClass);
+ Method method;
+ try {
+ method = aClass.getDeclaredMethod("nonInterfaceMethod");
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find test method", e);
+ }
+ HotSpotResolvedJavaMethodImpl resolvedMethod
+ = CTVMUtilities.getResolvedMethod(aClass, method);
+ List<String> symbols;
+ try {
+ symbols = getSymbols(resolvedMethod);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TEST BUG: can't access private members", e);
+ }
+ List<String> classSymbols = new ArrayList<>();
+ classSymbols.addAll(NAMES.apply(aClass.getDeclaredFields()));
+ classSymbols.addAll(NAMES.apply(aClass.getDeclaredMethods()));
+ // Check that all members of test class have symbols from constant pool
+ for (String s : classSymbols) {
+ if (!symbols.contains(s)) {
+ // failed. print all symbols found by getSymbol
+ System.out.println("getSymbol data:");
+ for (String ctvmValue : symbols) {
+ System.out.println(ctvmValue);
+ }
+ throw new AssertionError("Unable to find symbol " + s
+ + " using CompilerToVM.getSymbol");
+ }
+ }
+ }
+
+ private List<String> getSymbols(HotSpotResolvedJavaMethodImpl
+ metaspaceMethod) throws ReflectiveOperationException {
+ List<String> symbols = new ArrayList<>();
+ ConstantPool pool = metaspaceMethod.getConstantPool();
+ long length = pool.length();
+ // jvms-4.1: The constant_pool table is indexed from 1 ...
+ for (int i = 1; i < length; i++) {
+ if (getTag(pool, i) == CONSTANT_POOL_UTF8_TAG) {
+ long entryPointer;
+ Method getEntryAt = pool.getClass()
+ .getDeclaredMethod("getEntryAt", int.class);
+ getEntryAt.setAccessible(true);
+ entryPointer = (Long) getEntryAt.invoke(pool, i);
+ String symbol = CompilerToVMHelper.getSymbol(entryPointer);
+ symbols.add(symbol);
+ }
+ }
+ return symbols;
+ }
+
+ private int getTag(ConstantPool pool, int index)
+ throws ReflectiveOperationException {
+ Object jvmConstant;
+ Method getTag = pool.getClass().getDeclaredMethod("getTagAt",
+ int.class);
+ getTag.setAccessible(true);
+ jvmConstant = getTag.invoke(pool, index);
+ Field tagCode = jvmConstant.getClass().getDeclaredField("tag");
+ tagCode.setAccessible(true);
+ return tagCode.getInt(jvmConstant);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.DoNotExtendClass;
+import compiler.jvmci.common.testcases.MultipleAbstractImplementer;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.common.testcases.MultipleImplementersInterfaceExtender;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import compiler.jvmci.common.testcases.SingleSubclassedClass;
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.AnotherSingleImplementer;
+import compiler.jvmci.common.testcases.AnotherSingleImplementerInterface;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class GetVtableIndexForInterfaceTest {
+ private static final int INVALID_VTABLE_INDEX = -4; // see method.hpp: VtableIndexFlag
+
+ public static void main(String args[]) {
+ GetVtableIndexForInterfaceTest test
+ = new GetVtableIndexForInterfaceTest();
+ try {
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find requested method", e);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ Stream.of(
+ AbstractClass.class,
+ SingleImplementer.class,
+ SingleImplementerInterface.class,
+ MultipleImplementersInterface.class,
+ MultipleImplementersInterfaceExtender.class,
+ SingleSubclass.class,
+ SingleSubclassedClass.class,
+ DoNotExtendClass.class,
+ MultipleAbstractImplementer.class
+ )
+ .forEach(Utils::ensureClassIsLoaded);
+ // non iface method
+ result.add(new TestCase(SingleImplementer.class,
+ SingleImplementer.class, "nonInterfaceMethod",
+ false, InternalError.class));
+ // iface method w/o default implementation
+ result.add(new TestCase(SingleImplementer.class,
+ SingleImplementerInterface.class, "interfaceMethod", false));
+ /* another iface which provides default implementation for the
+ original iface*/
+ result.add(new TestCase(MultipleImplementersInterfaceExtender.class,
+ MultipleImplementersInterface.class, "testMethod", false,
+ InternalError.class));
+ // iface method w/ default implementation
+ result.add(new TestCase(SingleImplementer.class,
+ SingleImplementerInterface.class, "defaultMethod", true));
+ // non iface class
+ result.add(new TestCase(SingleSubclass.class,
+ SingleSubclassedClass.class, "inheritedMethod", false,
+ InternalError.class));
+ // class not implementing iface
+ result.add(new TestCase(DoNotExtendClass.class,
+ SingleImplementerInterface.class, "defaultMethod", false));
+ // abstract class which doesn't implement iface
+ result.add(new TestCase(AbstractClass.class,
+ SingleImplementerInterface.class, "defaultMethod", false));
+ // abstract class which implements iface
+ result.add(new TestCase(MultipleAbstractImplementer.class,
+ MultipleImplementersInterface.class, "defaultMethod", true));
+ // class not initialized
+ result.add(new TestCase(AnotherSingleImplementer.class,
+ AnotherSingleImplementerInterface.class, "defaultMethod",
+ false, InternalError.class));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) throws NoSuchMethodException {
+ System.out.println(tcase);
+ Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
+ HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.receiver),
+ getClass(), /* resolve = */ true);
+ HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities
+ .getResolvedMethod(tcase.holder, method);
+ int index = 0;
+ try {
+ index = CompilerToVMHelper
+ .getVtableIndexForInterfaceMethod(metaspaceKlass,
+ metaspaceMethod);
+ } catch (Throwable t) {
+ if (tcase.isPositive || tcase.expectedException == null) {
+ throw new Error("Caught unexpected exception " + t);
+ }
+ if (!tcase.expectedException.equals(t.getClass())) {
+ throw new Error(String.format("Caught %s while expected %s",
+ t.getClass().getName(),
+ tcase.expectedException.getName()));
+ }
+ return;
+ }
+ if (tcase.expectedException != null) {
+ throw new AssertionError("Expected exception wasn't caught: "
+ + tcase.expectedException.getName());
+ }
+ if (tcase.isPositive) {
+ Asserts.assertNE(index, INVALID_VTABLE_INDEX,
+ "Unexpected: got invalid index");
+ } else {
+ Asserts.assertEQ(index, INVALID_VTABLE_INDEX,
+ "Unexpected: got valid index ");
+ }
+ }
+
+ private static class TestCase {
+ public final Class<?> receiver;
+ public final Class<?> holder;
+ public final String methodName;
+ public final boolean isPositive;
+ public final Class<? extends Throwable> expectedException;
+
+ public TestCase(Class<?> receiver, Class<?> holder, String methodName,
+ boolean isPositive,
+ Class<? extends Throwable> expectedException) {
+ this.receiver = receiver;
+ this.holder = holder;
+ this.methodName = methodName;
+ this.isPositive = isPositive;
+ this.expectedException = expectedException;
+ }
+
+ public TestCase(Class<?> receiver, Class<?> holder, String methodName,
+ boolean isPositive) {
+ this(receiver, holder, methodName, isPositive, null);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CASE: receiver=%s, holder=%s, method=%s,"
+ + " isPositive=%s%n", receiver.getName(), holder.getName(),
+ methodName, isPositive);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:-BackgroundCompilation
+ * compiler.jvmci.compilerToVM.HasCompiledCodeForOSRTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import compiler.testlibrary.CompilerUtils;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
+
+public class HasCompiledCodeForOSRTest {
+ public static void main(String[] args) {
+ List<CompileCodeTestCase>testCases = createTestCases();
+ testCases.forEach(HasCompiledCodeForOSRTest::runSanityTest);
+ }
+
+ public static List<CompileCodeTestCase> createTestCases() {
+ List<CompileCodeTestCase> testCases = new ArrayList<>();
+
+ try {
+ Class<?> aClass = DummyClass.class;
+ testCases.add(new CompileCodeTestCase(
+ aClass.getMethod("withLoop"), 17));
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG : " + e.getMessage(), e);
+ }
+ return testCases;
+ }
+
+ private static void runSanityTest(CompileCodeTestCase testCase) {
+ System.out.println(testCase);
+ Executable aMethod = testCase.executable;
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ testCase.deoptimize();
+ int[] levels = CompilerUtils.getAvailableCompilationLevels();
+ // not compiled
+ for (int level : levels) {
+ boolean isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR(
+ method, testCase.bci, level);
+ Asserts.assertFalse(isCompiled, String.format(
+ "%s : unexpected return value for non-compiled method at "
+ + "level %d", testCase, level));
+ }
+ NMethod nm = testCase.compile();
+ if (nm == null) {
+ throw new Error(String.format(
+ "TEST BUG : %s : cannot compile method", testCase));
+ }
+
+ boolean isCompiled;
+ int level = nm.comp_level;
+ for (int i : levels) {
+ isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR(
+ method, testCase.bci, i);
+ Asserts.assertEQ(isCompiled, level == i, String.format(
+ "%s : unexpected return value for compiled method at "
+ + "level %d", testCase, i));
+ }
+
+ for (int i : new int[] {-1, +1}) {
+ int bci = testCase.bci + i;
+ isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR(
+ method, bci, level);
+ Asserts.assertFalse(isCompiled, String.format(
+ "%s : unexpected return value for compiled method at "
+ + "level %d with bci = %d ",
+ testCase, level, bci));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.AbstractClassExtender;
+import compiler.jvmci.common.testcases.DoNotImplementInterface;
+import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class HasFinalizableSubclassTest {
+ public static void main(String args[]) {
+ HasFinalizableSubclassTest test = new HasFinalizableSubclassTest();
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Stream.of(
+ AbstractClassExtender.class,
+ SingleImplementerInterface.class,
+ MultipleImplementersInterface.class,
+ MultipleImplementer1.class,
+ DoNotImplementInterface.class)
+ .forEach(Utils::ensureClassIsLoaded);
+ Set<TestCase> result = new HashSet<>();
+ // iface with finalize method
+ result.add(new TestCase(SingleImplementerInterface.class, false));
+ // iface with default finalize method
+ result.add(new TestCase(MultipleImplementersInterface.class, false));
+ // class which implements iface w/ default finalize method
+ result.add(new TestCase(MultipleImplementer1.class, true));
+ // abstract class with finalizeable subclass
+ result.add(new TestCase(AbstractClass.class, true));
+ // non-implemented iface
+ result.add(new TestCase(DoNotImplementInterface.class, false));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) {
+ System.out.println(tcase);
+ HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.aClass),
+ getClass(), /* resolve = */ true);
+ Asserts.assertEQ(tcase.expected,
+ CompilerToVMHelper.hasFinalizableSubclass(metaspaceKlass),
+ "Unexpected finalizableSubclass state for "
+ + tcase.aClass.getName());
+ }
+
+ private static class TestCase {
+ public final Class<?> aClass;
+ public final boolean expected;
+
+ public TestCase(Class<?> clazz, boolean expected) {
+ this.aClass = clazz;
+ this.expected = expected;
+ }
+ @Override
+ public String toString() {
+ return "CASE: class= " + aClass.getName() + ", expected=" + expected;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.InitializeConfigurationTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.InitializeConfigurationTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Consumer;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.misc.Unsafe;
+
+public class InitializeConfigurationTest {
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+
+ public static void main(String args[]) {
+ new InitializeConfigurationTest().runTest(generateTestCases());
+ }
+
+ private static List<TestCase> generateTestCases() {
+ List<TestCase> result = new ArrayList<>();
+ result.add(new TestCase("CodeCache", "_high_bound", "address",
+ InitializeConfigurationTest::verifyLongIsNotZero));
+ result.add(new TestCase("StubRoutines", "_jint_arraycopy", "address",
+ InitializeConfigurationTest::verifyLongIsNotZero));
+ return result;
+ }
+
+ private static void verifyLongIsNotZero(Object o) {
+ Asserts.assertNotNull(o, "Got null value");
+ Asserts.assertEQ(o.getClass(), Long.class, "Unexpected value type");
+ Asserts.assertNE(o, 0L, "Got null address");
+ }
+
+ private void runTest(List<TestCase> tcases) {
+ VMStructDataReader reader = new VMStructDataReader(
+ CompilerToVMHelper.initializeConfiguration());
+ while (reader.hasNext()) {
+ VMFieldData data = reader.next();
+ for (TestCase tcase : tcases) {
+ tcase.check(data);
+ }
+ }
+ // now check if all passed
+ for (TestCase tcase: tcases) {
+ Asserts.assertTrue(tcase.isFound(), "Case failed: " + tcase);
+ }
+ }
+
+ private static class VMStructDataReader implements Iterator<VMFieldData> {
+ // see jvmciCompilerToVM:105 static uintptr_t ciHotSpotVMData[28];
+ private static final int HOTSPOT_VM_DATA_INDEX_COUNT = 28;
+ private final long addresses[];
+ private final long vmStructsBase;
+ private final long entityNameFieldOffset;
+ private final long nameFieldOffset;
+ private final long typeStringFieldOffset;
+ private final long addressOffset;
+ private final long entrySize;
+ private long nextElementAddress;
+ private VMFieldData nextElement;
+
+ public VMStructDataReader(long gHotSpotVMData) {
+ Asserts.assertNE(gHotSpotVMData, 0L, "Got null base address");
+ addresses = new long[HOTSPOT_VM_DATA_INDEX_COUNT];
+ for (int i = 0; i < HOTSPOT_VM_DATA_INDEX_COUNT; i++) {
+ addresses[i] = UNSAFE.getAddress(
+ gHotSpotVMData + Unsafe.ADDRESS_SIZE * i);
+ }
+ vmStructsBase = addresses[0];
+ entityNameFieldOffset = addresses[1];
+ nameFieldOffset = addresses[2];
+ typeStringFieldOffset = addresses[3];
+ addressOffset = addresses[6];
+ entrySize = addresses[7];
+ nextElementAddress = vmStructsBase;
+ nextElement = read();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return nextElement != null;
+ }
+
+ @Override
+ public VMFieldData next() {
+ if (nextElement == null) {
+ throw new NoSuchElementException("Next element is null");
+ }
+ VMFieldData toReturn = nextElement;
+ nextElementAddress += entrySize;
+ nextElement = read();
+ return toReturn;
+ }
+
+ private VMFieldData read() {
+ String entityFieldName = readCString(
+ UNSAFE.getAddress(nextElementAddress + nameFieldOffset));
+ if (entityFieldName == null) {
+ return null;
+ }
+ String fieldType = readCString(UNSAFE.getAddress(
+ nextElementAddress + typeStringFieldOffset));
+ String entityName = readCString(UNSAFE.getAddress(
+ nextElementAddress + entityNameFieldOffset));
+ Object value;
+ if ("address".equals(fieldType)) {
+ long address = UNSAFE.getAddress(
+ nextElementAddress + addressOffset);
+ value = address;
+ } else {
+ // non-address cases are not supported
+ value = null;
+ }
+ return new VMFieldData(entityName, entityFieldName, fieldType,
+ value);
+ }
+
+ private static String readCString(long address) {
+ if (address == 0) {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0;; i++) {
+ char c = (char) UNSAFE.getByte(address + i);
+ if (c == 0) {
+ break;
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+ }
+
+ private static class VMFieldData {
+ public final String entityFieldName;
+ public final String entityName;
+ public final String fieldType;
+ public final Object value;
+
+ private VMFieldData(String entityName, String entityFieldName,
+ String fieldType, Object value) {
+ this.entityName = entityName;
+ this.entityFieldName = entityFieldName;
+ this.fieldType = fieldType;
+ this.value = value;
+ }
+ }
+
+ private static class TestCase {
+ public final String entityName;
+ public final String fieldType;
+ public final String entityFieldName;
+ public final Consumer consumer;
+ private boolean found;
+
+ public TestCase(String entityName, String entityFieldName,
+ String fieldType, Consumer predicate) {
+ Objects.requireNonNull(entityName, "Got null entityName");
+ Objects.requireNonNull(entityFieldName, "Got null entityFieldName");
+ Objects.requireNonNull(fieldType, "Got null type");
+ if (!"address".equals(fieldType)) {
+ throw new Error("TESTBUG: unsupported testcase with fieldType="
+ + fieldType);
+ }
+ this.entityName = entityName;
+ this.fieldType = fieldType;
+ this.entityFieldName = entityFieldName;
+ this.consumer = predicate;
+ this.found = false;
+ }
+
+ public void check(VMFieldData data) {
+ if (entityFieldName.equals(data.entityFieldName)
+ && entityName.equals(data.entityName)
+ && fieldType.equals(data.fieldType)) {
+ Asserts.assertFalse(found, "Found 2 entries of " + this);
+ found = true;
+ consumer.accept(data.value);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CASE: entityName=" + entityName + " entityFieldName="
+ + entityFieldName + " fieldType=" + fieldType;
+ }
+
+ public boolean isFound() {
+ return found;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import sun.hotspot.code.NMethod;
+
+import java.util.List;
+
+public class InvalidateInstalledCodeTest {
+ public static void main(String[] args) {
+ InvalidateInstalledCodeTest test
+ = new InvalidateInstalledCodeTest();
+ List<CompileCodeTestCase> testCases
+ = CompileCodeTestCase.generate(/* bci = */ 0);
+ testCases.addAll(CompileCodeTestCase.generate(/* bci = */ -1));
+ testCases.forEach(test::check);
+ test.checkNull();
+ }
+
+ private void checkNull() {
+ InstalledCode installedCode = new InstalledCode("<null>");
+ installedCode.setAddress(0);
+ CompilerToVMHelper.invalidateInstalledCode(installedCode);
+ }
+
+ private void check(CompileCodeTestCase testCase) {
+ System.out.println(testCase);
+ // to have a clean state
+ NMethod beforeInvalidation = testCase.deoptimizeAndCompile();
+ if (beforeInvalidation == null) {
+ throw new Error("method is not compiled, testCase " + testCase);
+ }
+
+ // run twice to verify how it works if method is already invalidated
+ for (int i = 0; i < 2; ++i) {
+ InstalledCode installedCode = new InstalledCode(
+ testCase.executable.getName());
+ installedCode.setAddress(beforeInvalidation.address);
+
+ CompilerToVMHelper.invalidateInstalledCode(installedCode);
+ NMethod afterInvalidation = testCase.toNMethod();
+ if (afterInvalidation != null) {
+ System.err.println("before: " + beforeInvalidation);
+ System.err.println("after: " + afterInvalidation);
+ throw new AssertionError(testCase
+ + " : method hasn't been invalidated, i = " + i);
+ }
+ Asserts.assertFalse(installedCode.isValid(), testCase
+ + " : code is valid after invalidation, i = " + i);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox IsMatureTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.IsMatureTest
+ */
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.SimpleClass;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+
+public class IsMatureTest {
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) throws Exception {
+ new IsMatureTest().test();
+ }
+
+ public void test() throws Exception {
+ SimpleClass sclass = new SimpleClass();
+ Executable method = SimpleClass.class.getDeclaredMethod("testMethod");
+ long metaspaceMethodData = WB.getMethodData(method);
+ Asserts.assertEQ(metaspaceMethodData, 0L, "MDO should be null for "
+ + "never invoked method");
+ boolean isMature = CompilerToVMHelper.isMature(metaspaceMethodData);
+ Asserts.assertFalse(isMature, "null MDO can't be mature");
+ for (int i = 0; i < 1000; i++) {
+ sclass.testMethod();
+ }
+ // warmed up, mdo should be ready for now
+ metaspaceMethodData = WB.getMethodData(method);
+ Asserts.assertNE(metaspaceMethodData, 0L,
+ "MDO should be available after 1000 calls");
+ for (int i = 0; i < 100_000; i++) {
+ sclass.testMethod();
+ }
+ isMature = CompilerToVMHelper.isMature(metaspaceMethodData);
+ Asserts.assertTrue(isMature,
+ "a 100_000 times invoked method should be mature");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=true
+ * -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=false
+ * -XX:-EnableJVMCI
+ * compiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives
+
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVM;
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.test.lib.Asserts;
+
+import java.lang.reflect.Method;
+
+public class JVM_RegisterJVMCINatives {
+ private static final boolean IS_POSITIVE = Boolean.getBoolean(
+ "compiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive");
+
+ private final Method registerNatives;
+
+ public static void main(String[] args) {
+ new JVM_RegisterJVMCINatives().runTest();
+ }
+
+ private void runTest() {
+ Object result;
+ try {
+ result = invoke();
+ } catch (InternalError e) {
+ if (IS_POSITIVE) {
+ throw new AssertionError("unexpected exception", e);
+ }
+ return;
+ }
+ if (!IS_POSITIVE) {
+ throw new AssertionError("didn't get expected exception");
+ }
+ Asserts.assertNull(result,
+ "registerNatives()V returned non-null");
+ Asserts.assertEQ(result, invoke(),
+ "registerNatives returns different results");
+
+ }
+ private Object invoke() {
+ Object result;
+ try {
+ result = registerNatives.invoke(JVMCI.class);
+ } catch (ReflectiveOperationException e) {
+ throw new Error("can't invoke registerNatives", e);
+ }
+ return result;
+ }
+
+ private JVM_RegisterJVMCINatives() {
+ Method method;
+ try {
+ method = CompilerToVM.class.getDeclaredMethod("registerNatives");
+ method.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ throw new Error("can't find CompilerToVM::registerNatives", e);
+ }
+ registerNatives = method;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @summary Testing compiler.jvmci.CompilerToVM.lookupKlassInPool method
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.common.testcases.MultipleImplementersInterface
+ * compiler.jvmci.common.testcases.MultipleImplementer2
+ * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper
+ * compiler.jvmci.compilerToVM.ConstantPoolTestCase
+ * compiler.jvmci.compilerToVM.LookupKlassInPoolTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupKlassInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import sun.reflect.ConstantPool;
+
+/**
+ * Test for {@code compiler.jvmci.CompilerToVM.lookupKlassInPool} method
+ */
+public class LookupKlassInPoolTest {
+
+ public static void main(String[] args) {
+ Map<ConstantPoolTestsHelper.ConstantTypes,
+ ConstantPoolTestCase.Validator> typeTests = new HashMap<>(1);
+ typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS,
+ LookupKlassInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ }
+
+ public static void validate(HotSpotConstantPool constantPoolCTVM,
+ ConstantPool constantPoolSS,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
+ Object classToVerify = CompilerToVMHelper
+ .lookupKlassInPool(constantPoolCTVM, i);
+ if (!(classToVerify instanceof HotSpotResolvedObjectTypeImpl)
+ && !(classToVerify instanceof String)) {
+ String msg = String.format("Output of method"
+ + " CTVM.lookupKlassInPool is neither"
+ + " a HotSpotResolvedObjectTypeImpl, nor a String");
+ throw new AssertionError(msg);
+ }
+ int classNameIndex = (int) dummyClass.cp.get(i).value;
+ String classNameToRefer
+ = constantPoolSS.getUTF8At(classNameIndex);
+ String outputToVerify = classToVerify.toString();
+ if (!outputToVerify.contains(classNameToRefer)) {
+ String msg = String.format("Wrong class accessed by constant"
+ + " pool index %d: %s, but should be %s",
+ i, outputToVerify, classNameToRefer);
+ throw new AssertionError(msg);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.LookupTypeTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupTypeTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.DoNotExtendClass;
+import compiler.jvmci.common.testcases.MultiSubclassedClass;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class LookupTypeTest {
+ public static void main(String args[]) {
+ LookupTypeTest test = new LookupTypeTest();
+ for (TestCase tcase : createTestCases()) {
+ test.runTest(tcase);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ // a primitive class
+ result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
+ LookupTypeTest.class, true, false, InternalError.class));
+ // lookup not existing class
+ result.add(new TestCase("Lsome_not_existing;", LookupTypeTest.class,
+ true, false, ClassNotFoundException.class));
+ // lookup invalid classname
+ result.add(new TestCase("L!@#$%^&**()[]{}?;", LookupTypeTest.class,
+ true, false, ClassNotFoundException.class));
+ // lookup package private class
+ result.add(new TestCase(
+ "Lcompiler/jvmci/compilerToVM/testcases/PackagePrivateClass;",
+ LookupTypeTest.class, true, false,
+ ClassNotFoundException.class));
+ // lookup usual class with resolve=true
+ result.add(new TestCase(Utils.toJVMTypeSignature(SingleSubclass.class),
+ LookupTypeTest.class, true, true));
+ // lookup usual class with resolve=false
+ result.add(new TestCase(
+ Utils.toJVMTypeSignature(DoNotExtendClass.class),
+ LookupTypeTest.class, false, true));
+ // lookup usual class with null accessor
+ result.add(new TestCase(
+ Utils.toJVMTypeSignature(MultiSubclassedClass.class), null,
+ false, false, NullPointerException.class));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) {
+ System.out.println(tcase);
+ HotSpotResolvedObjectTypeImpl metaspaceKlass;
+ try {
+ metaspaceKlass = CompilerToVMHelper.lookupType(tcase.className,
+ tcase.accessing, tcase.resolve);
+ } catch (Throwable t) {
+ Asserts.assertNotNull(tcase.expectedException,
+ "Assumed no exception, but got " + t);
+ Asserts.assertFalse(tcase.isPositive,
+ "Got unexpected exception " + t);
+ Asserts.assertEQ(t.getClass(), tcase.expectedException,
+ "Unexpected exception");
+ // passed
+ return;
+ }
+ if (tcase.expectedException != null) {
+ throw new AssertionError("Expected exception was not thrown: "
+ + tcase.expectedException.getName());
+ }
+ if (tcase.isPositive) {
+ Asserts.assertNotNull(metaspaceKlass,
+ "Unexpected null metaspace klass");
+ Asserts.assertEQ(metaspaceKlass.getName(), tcase.className,
+ "Got unexpected resolved class name");
+ } else {
+ Asserts.assertNull(metaspaceKlass, "Unexpected metaspace klass");
+ }
+ }
+
+ private static class TestCase {
+ public final String className;
+ public final Class<?> accessing;
+ public final boolean resolve;
+ public final boolean isPositive;
+ public final Class<? extends Throwable> expectedException;
+
+ public TestCase(String className, Class<?> accessing, boolean resolve,
+ boolean isPositive,
+ Class<? extends Throwable> expectedException) {
+ this.className = className;
+ this.accessing = accessing;
+ this.resolve = resolve;
+ this.isPositive = isPositive;
+ this.expectedException = expectedException;
+ }
+
+ public TestCase(String className, Class<?> accessing, boolean resolve,
+ boolean isPositive) {
+ this.className = className;
+ this.accessing = accessing;
+ this.resolve = resolve;
+ this.isPositive = isPositive;
+ this.expectedException = null;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CASE: class=%s, accessing=%s,"
+ + " resolve=%s, positive=%s, expectedException=%s", className,
+ accessing, resolve, isPositive, expectedException);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox MaterializeVirtualObjectTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:CompileCommand=exclude,*::check -XX:+DoEscapeAnalysis
+ * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Method;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotStackFrameReference;
+
+public class MaterializeVirtualObjectTest {
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final int INVOCATIONS = 100_000;
+ private static final Method METHOD;
+ private static final HotSpotResolvedJavaMethodImpl RESOLVED_METHOD;
+ private final boolean invalidate;
+
+ static {
+ try {
+ METHOD = MaterializeVirtualObjectTest.class.getDeclaredMethod(
+ "testFrame", String.class, Integer.class);
+ } catch (NoSuchMethodException e) {
+ throw new Error("Can't get executable for test method", e);
+ }
+ RESOLVED_METHOD = CTVMUtilities.getResolvedMethod(METHOD);
+ }
+
+ public MaterializeVirtualObjectTest(boolean invalidate) {
+ this.invalidate = invalidate;
+ }
+
+ public static void main(String[] args) {
+ new MaterializeVirtualObjectTest(true).test();
+ new MaterializeVirtualObjectTest(false).test();
+ }
+
+ private void test() {
+ System.out.printf("CASE: invalidate=%b%n", invalidate);
+ for (int i = 0; i < INVOCATIONS; i++) {
+ testFrame("someString", i);
+ }
+ Utils.waitForCondition(() -> WB.isMethodCompiled(METHOD), 100L);
+ Asserts.assertTrue(WB.isMethodCompiled(METHOD));
+ testFrame("someString", INVOCATIONS);
+ }
+
+ private void testFrame(String str, Integer iteration) {
+ Helper helper = new Helper(str);
+ check(iteration);
+ Asserts.assertTrue((helper.string != null) && (this != null)
+ && (helper != null), "Some locals are null");
+ }
+
+ private void check(int iteration) {
+ // Materialize virtual objects on last invocation
+ if (iteration == INVOCATIONS) {
+ HotSpotStackFrameReference hsFrame = CompilerToVMHelper
+ .getNextStackFrame(/* topmost frame */ null,
+ new HotSpotResolvedJavaMethodImpl[]{
+ RESOLVED_METHOD}, /* don't skip any */ 0);
+ Asserts.assertNotNull(hsFrame, "Got null frame");
+ Asserts.assertTrue(WB.isMethodCompiled(METHOD),
+ "Expected test method to be compiled");
+ Asserts.assertTrue(hsFrame.hasVirtualObjects(),
+ "Has no virtual object before materialization");
+ CompilerToVMHelper.materializeVirtualObjects(hsFrame, invalidate);
+ Asserts.assertFalse(hsFrame.hasVirtualObjects(),
+ "Has virtual object after materialization");
+ Asserts.assertEQ(WB.isMethodCompiled(METHOD), !invalidate,
+ "Unexpected compiled status");
+ }
+ }
+
+ private class Helper {
+ public String string;
+
+ public Helper(String s) {
+ this.string = s;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.MethodIsIgnoredBySecurityStackWalkTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Method;
+import java.lang.reflect.Executable;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class MethodIsIgnoredBySecurityStackWalkTest {
+
+ public static void main(String[] args) {
+ Map<Executable, Boolean> testCases = createTestCases();
+ testCases.forEach(
+ MethodIsIgnoredBySecurityStackWalkTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod, Boolean expected) {
+ HotSpotResolvedJavaMethodImpl method
+ = CTVMUtilities.getResolvedMethod(aMethod);
+ boolean isIgnored = CompilerToVMHelper
+ .methodIsIgnoredBySecurityStackWalk(method);
+ String msg = String.format("%s is%s ignored but must%s", aMethod,
+ isIgnored ? "" : " not",
+ expected ? "" : " not");
+ Asserts.assertEQ(isIgnored, expected, msg);
+ }
+
+ private static Map<Executable, Boolean> createTestCases() {
+ Map<Executable, Boolean> testCases = new HashMap<>();
+
+ try {
+ Class<?> aClass = Method.class;
+ testCases.put(aClass.getMethod("invoke", Object.class,
+ Object[].class), true);
+
+ aClass = Class.forName("sun.reflect.NativeMethodAccessorImpl");
+ testCases.put(aClass.getMethod("invoke", Object.class,
+ Object[].class), true);
+ testCases.put(aClass.getDeclaredMethod("invoke0", Method.class,
+ Object.class, Object[].class), true);
+
+ aClass = MethodIsIgnoredBySecurityStackWalkTest.class;
+ for (Executable method : aClass.getMethods()) {
+ testCases.put(method, false);
+ }
+ for (Executable method : aClass.getDeclaredMethods()) {
+ testCases.put(method, false);
+ }
+ for (Executable method : aClass.getConstructors()) {
+ testCases.put(method, false);
+ }
+ } catch (NoSuchMethodException | ClassNotFoundException e) {
+ throw new Error("TEST BUG " + e.getMessage(), e);
+ }
+ return testCases;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib/
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ * @run main ClassFileInstaller
+ * sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:-UseCompressedOops
+ * compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UseCompressedOops
+ * compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+
+public class ReadUncompressedOopTest {
+
+ public static void main(String args[]) {
+ new ReadUncompressedOopTest().runTest();
+ }
+
+ private void runTest() {
+ long ptr = getPtr();
+ System.out.printf("calling readUncompressedOop(0x%x)%n", ptr);
+ Asserts.assertEQ(getClass(),
+ CompilerToVMHelper.readUncompressedOop(ptr),
+ String.format("unexpected class returned for 0x%x", ptr));
+ }
+
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final Class<?> CLASS = ReadUncompressedOopTest.class;
+ private static final long PTR = WB.getObjectAddress(CLASS);
+
+ private static long getPtr() {
+ Field field;
+ try {
+ field = CLASS.getDeclaredField("PTR");
+ } catch (NoSuchFieldException nsfe) {
+ throw new Error("TESTBUG : " + nsfe, nsfe);
+ }
+ Object base = UNSAFE.staticFieldBase(field);
+ return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller
+ * sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -Xmixed
+ * compiler.jvmci.compilerToVM.ReprofileTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+public class ReprofileTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Method> testCases = createTestCases();
+ testCases.forEach(ReprofileTest::runSanityTest);
+ }
+
+ private static List<Method> createTestCases() {
+ List<Method> testCases = new ArrayList<>();
+ try {
+
+ Class<?> aClass = DummyClass.class;
+ testCases.add(aClass.getMethod("withLoop"));
+
+ aClass = DummyClass.class;
+ testCases.add(aClass.getDeclaredMethod("dummyFunction"));
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG " + e.getMessage(), e);
+ }
+ return testCases;
+ }
+
+ private static void runSanityTest(Method aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ ProfilingInfo startProfile = method.getProfilingInfo();
+ Asserts.assertFalse(startProfile.isMature(), aMethod
+ + " : profiling info is mature in the begging");
+
+ long compileThreshold = (Long) WB.getVMFlag("CompileThreshold");
+ // make interpreter to profile this method
+ try {
+ Object obj = aMethod.getDeclaringClass().newInstance();
+ for (long i = 0; i < compileThreshold; i++) {
+ aMethod.invoke(obj);
+ }
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TEST BUG : " + e.getMessage(), e);
+ }
+ ProfilingInfo compProfile = method.getProfilingInfo();
+
+ Asserts.assertNE(startProfile.toString(), compProfile.toString(),
+ String.format("%s : profiling info wasn't changed after "
+ + "%d invocations",
+ aMethod, compileThreshold));
+ Asserts.assertTrue(compProfile.isMature(),
+ String.format("%s is not mature after %d invocations",
+ aMethod, compileThreshold));
+
+ CompilerToVMHelper.reprofile(method);
+ ProfilingInfo reprofiledProfile = method.getProfilingInfo();
+
+ Asserts.assertNE(startProfile.toString(), reprofiledProfile.toString(),
+ aMethod + " : profiling info wasn't changed after reprofiling");
+ Asserts.assertNE(compProfile.toString(), reprofiledProfile.toString(),
+ aMethod + " : profiling info didn't change after reprofile");
+ Asserts.assertFalse(reprofiledProfile.isMature(), aMethod
+ + " : profiling info is mature after reprofiling");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.test.lib.Asserts;
+import sun.reflect.ConstantPool;
+
+/**
+ * Test for {@code compiler.jvmci.CompilerToVM.resolveConstantInPool} method
+ */
+public class ResolveConstantInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantPoolTestsHelper.ConstantTypes,
+ ConstantPoolTestCase.Validator> typeTests = new HashMap<>(2);
+ typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODHANDLE,
+ ResolveConstantInPoolTest::validateMethodHandle);
+ typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODTYPE,
+ ResolveConstantInPoolTest::validateMethodType);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ }
+
+ private static void validateMethodHandle(HotSpotConstantPool constantPoolCTVM,
+ ConstantPool constantPoolSS,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
+ Object constantInPool = CompilerToVMHelper
+ .resolveConstantInPool(constantPoolCTVM, index);
+ if (!(constantInPool instanceof MethodHandle)) {
+ String msg = String.format(
+ "Wrong constant pool entry accessed by index"
+ + " %d: %s, but should be subclass of %s",
+ index + 1, constantInPool.getClass(),
+ MethodHandle.class.getName());
+ throw new AssertionError(msg);
+ }
+ }
+
+ private static void validateMethodType(HotSpotConstantPool constantPoolCTVM,
+ ConstantPool constantPoolSS,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
+ Object constantInPool = CompilerToVMHelper
+ .resolveConstantInPool(constantPoolCTVM, index);
+ Class mtToVerify = constantInPool.getClass();
+ Class mtToRefer = MethodType.class;
+ String msg = String.format("Wrong %s accessed by constant pool index"
+ + " %d: %s, but should be %s", "method type class",
+ index, mtToVerify, mtToRefer);
+ Asserts.assertEQ(mtToRefer, mtToVerify, msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.ResolveMethodTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.AbstractClassExtender;
+import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.MultipleImplementer2;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import compiler.jvmci.common.testcases.SingleSubclassedClass;
+import compiler.jvmci.common.CTVMUtilities;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.misc.Unsafe;
+
+public class ResolveMethodTest {
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+
+ public static void main(String args[]) {
+ ResolveMethodTest test = new ResolveMethodTest();
+ // positive cases
+ try {
+ for (TestCase tcase: createTestCases()) {
+ test.runTest(tcase);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: can't find requested method", e);
+ }
+ }
+
+ private static Set<TestCase> createTestCases() {
+ Set<TestCase> result = new HashSet<>();
+ // a usual class public method
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "usualMethod", ResolveMethodTest.class, true));
+ // an array method
+ result.add(new TestCase(int[].class, Object.class, "toString",
+ ResolveMethodTest.class, true));
+ // a method from base class, which was overriden in tested one
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "overridenMethod", ResolveMethodTest.class, true));
+ // a method from base class, which was not overriden in tested one
+ result.add(new TestCase(SingleSubclass.class,
+ SingleSubclassedClass.class, "inheritedMethod",
+ ResolveMethodTest.class, true));
+ /* a method from base class, which was overriden in tested one with
+ base class as holder */
+ result.add(new TestCase(SingleSubclass.class,
+ SingleSubclassedClass.class, "overridenMethod",
+ ResolveMethodTest.class, true));
+ // an interface method
+ result.add(new TestCase(SingleImplementer.class,
+ SingleImplementerInterface.class, "interfaceMethod",
+ ResolveMethodTest.class, true));
+ // an interface default method overriden in implementer
+ result.add(new TestCase(MultipleImplementer1.class,
+ MultipleImplementersInterface.class, "defaultMethod",
+ ResolveMethodTest.class, true));
+ // an interface default method not overriden in implementer
+ result.add(new TestCase(MultipleImplementer2.class,
+ MultipleImplementersInterface.class, "defaultMethod",
+ ResolveMethodTest.class, true));
+ // an abstract method
+ result.add(new TestCase(AbstractClassExtender.class, AbstractClass.class,
+ "abstractMethod", ResolveMethodTest.class, true));
+ // private method with right accessor
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "privateMethod", SingleSubclass.class, true));
+ // package-private method with right accessor
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "defaultAccessMethod", SingleSubclass.class, true));
+
+ // negative cases
+
+ // private method of another class
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "privateMethod", ResolveMethodTest.class, false));
+ // package-private method from another package
+ result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+ "defaultAccessMethod", ResolveMethodTest.class, false));
+ return result;
+ }
+
+ private void runTest(TestCase tcase) throws NoSuchMethodException {
+ System.out.println(tcase);
+ HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities
+ .getResolvedMethod(tcase.holder,
+ tcase.holder.getDeclaredMethod(tcase.methodName));
+ HotSpotResolvedObjectTypeImpl holderMetaspace = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.holder),
+ getClass(), /* resolve = */ true);
+ HotSpotResolvedObjectTypeImpl callerMetaspace = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(tcase.caller),
+ getClass(), /* resolve = */ true);
+ HotSpotResolvedJavaMethodImpl resolvedMetaspaceMethod
+ = CompilerToVMHelper.resolveMethod(holderMetaspace,
+ metaspaceMethod, callerMetaspace);
+ if (tcase.isPositive) {
+ Asserts.assertNotNull(resolvedMetaspaceMethod,
+ "Unexpected null resolved method value for "
+ + tcase.methodName);
+ Asserts.assertEQ(metaspaceMethod.getName(), tcase.methodName,
+ "Reflection and c2vm method names doesn't match");
+ } else {
+ Asserts.assertNull(resolvedMetaspaceMethod,
+ "Method unexpectedly resolved");
+ }
+ }
+
+ private static class TestCase {
+ public final Class<?> receiver;
+ public final Class<?> holder;
+ public final Class<?> caller;
+ public final String methodName;
+ public final boolean isPositive;
+
+ public TestCase(Class<?> recv, Class<?> holder, String methodName,
+ Class<?> caller, boolean isPositive) {
+ this.receiver = recv;
+ this.holder = holder;
+ this.caller = caller;
+ this.methodName = methodName;
+ this.isPositive = isPositive;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CASE: receiver=%s, holder=%s, method=%s,"
+ + "caller=%s, isPositive=%s%n", receiver.getName(),
+ holder.getName(), methodName, caller.getName(), isPositive);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @summary Testing compiler.jvmci.CompilerToVM.resolveTypeInPool method
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.common.testcases.MultipleImplementersInterface
+ * compiler.jvmci.common.testcases.MultipleImplementer2
+ * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper
+ * compiler.jvmci.compilerToVM.ConstantPoolTestCase
+ * compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import sun.reflect.ConstantPool;
+
+/**
+ * Test for {@code compiler.jvmci.CompilerToVM.resolveTypeInPool} method
+ */
+public class ResolveTypeInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantPoolTestsHelper.ConstantTypes,
+ ConstantPoolTestCase.Validator> typeTests = new HashMap<>(1);
+ typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS,
+ ResolveTypeInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ }
+
+ public static void validate(HotSpotConstantPool constantPoolCTVM,
+ ConstantPool constantPoolSS,
+ ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
+ HotSpotResolvedObjectTypeImpl typeToVerify = CompilerToVMHelper
+ .resolveTypeInPool(constantPoolCTVM, i);
+ int classNameIndex = (int) dummyClass.cp.get(i).value;
+ String classNameToRefer = constantPoolSS.getUTF8At(classNameIndex);
+ String outputToVerify = typeToVerify.toString();
+ if (!outputToVerify.contains(classNameToRefer)) {
+ String msg = String.format("Wrong class accessed by constant"
+ + " pool index %d: %s, but should be %s",
+ i, outputToVerify, classNameToRefer);
+ throw new AssertionError(msg);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib/
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
+ * @run main ClassFileInstaller
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+DebugNonSafepoints
+ * -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=true
+ * compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
+ * @run main/othervm
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:-DebugNonSafepoints
+ * -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=false
+ * compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.test.lib.Asserts;
+
+public class ShouldDebugNonSafepointsTest {
+ private static final boolean EXPECTED = Boolean.getBoolean("compiler"
+ + ".jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected");
+
+ public static void main(String args[]) {
+ new ShouldDebugNonSafepointsTest().runTest();
+ }
+
+ private void runTest() {
+ Asserts.assertEQ(CompilerToVMHelper.shouldDebugNonSafepoints(),
+ EXPECTED, "Unexpected shouldDebugnonSafepoints value");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /../../test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.jvmci.compilerToVM.ShouldInlineMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+public class ShouldInlineMethodTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Executable> testCases = createTestCases();
+ testCases.forEach(ShouldInlineMethodTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ boolean shouldInline = CompilerToVMHelper.shouldInlineMethod(method);
+ boolean expectedShouldInline = WB.testSetForceInlineMethod(aMethod,
+ true);
+ Asserts.assertEQ(shouldInline, expectedShouldInline,
+ "Unexpected value of property 'should inline'");
+
+ shouldInline = CompilerToVMHelper.shouldInlineMethod(method);
+ Asserts.assertTrue(shouldInline, "Unexpected value of property "
+ + "'should inline' after setting 'force inline' to true");
+ WB.testSetForceInlineMethod(aMethod, false);
+ shouldInline = CompilerToVMHelper.shouldInlineMethod(method);
+ Asserts.assertFalse(shouldInline, "Unexpected value of property "
+ + "'should inline' after setting 'force inline' to false");
+ }
+
+ private static List<Executable> createTestCases() {
+ List<Executable> testCases = new ArrayList<>();
+
+ Class<?> aClass = DummyClass.class;
+ testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
+ testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
+ return testCases;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.events.JvmciCompleteInitializationTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary
+ * @build compiler.jvmci.common.JVMCIHelpers
+ * compiler.jvmci.events.JvmciCompleteInitializationTest
+ * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
+ * @run main jdk.test.lib.FileInstaller ./JvmciCompleteInitializationTest.config
+ * ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener
+ * @run main ClassFileInstaller
+ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
+ * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
+ * compiler.jvmci.events.JvmciCompleteInitializationTest
+ * jdk.test.lib.Asserts
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Xbootclasspath/a:.
+ * -XX:+EnableJVMCI
+ * -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=true
+ * compiler.jvmci.events.JvmciCompleteInitializationTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * -Xbootclasspath/a:.
+ * -XX:-EnableJVMCI
+ * -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=false
+ * compiler.jvmci.events.JvmciCompleteInitializationTest
+ */
+
+package compiler.jvmci.events;
+
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+
+public class JvmciCompleteInitializationTest implements HotSpotVMEventListener {
+ private static final boolean IS_POSITIVE = Boolean.getBoolean(
+ "compiler.jvmci.events.JvmciCompleteInitializationTest.positive");
+ private static volatile int completeInitializationCount = 0;
+ private static volatile String errorMessage = "";
+
+ public static void main(String args[]) {
+ if (completeInitializationCount != 0) {
+ throw new Error("Unexpected completeInitialization events"
+ + " count at start");
+ }
+ initializeRuntime();
+ int expectedEventCount = IS_POSITIVE ? 1 : 0;
+ Asserts.assertEQ(completeInitializationCount, expectedEventCount,
+ "Unexpected completeInitialization events count"
+ + " after JVMCI init");
+ initializeRuntime();
+ Asserts.assertEQ(completeInitializationCount, expectedEventCount,
+ "Unexpected completeInitialization events count"
+ + " after 2nd JVMCI init");
+ Asserts.assertTrue(errorMessage.isEmpty(), errorMessage);
+ }
+
+ private static void initializeRuntime() {
+ Error t = null;
+ try {
+ /* in case JVMCI disabled, an InternalError on initialization
+ and NoClassDefFound on 2nd try */
+ HotSpotJVMCIRuntime.runtime();
+ } catch (Error e) {
+ t = e;
+ }
+ if (IS_POSITIVE) {
+ Asserts.assertNull(t, "Caught unexpected exception");
+ } else {
+ Asserts.assertNotNull(t, "Got no expected error");
+ }
+ }
+
+ @Override
+ public void completeInitialization(HotSpotJVMCIRuntime
+ hotSpotJVMCIRuntime) {
+ completeInitializationCount++;
+ if (hotSpotJVMCIRuntime == null) {
+ errorMessage += " HotSpotJVMCIRuntime is null.";
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.config Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.events.JvmciCreateMetaAccessContextTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary
+ * @compile ./MetaAccessWrapper.java
+ * @build compiler.jvmci.common.JVMCIHelpers
+ * compiler.jvmci.events.JvmciCreateMetaAccessContextTest
+ * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
+ * @run main jdk.test.lib.FileInstaller
+ * ./JvmciCreateMetaAccessContextTest.config
+ * ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener
+ * @run main ClassFileInstaller
+ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
+ * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
+ * compiler.jvmci.events.JvmciCreateMetaAccessContextTest
+ * jdk.vm.ci.hotspot.MetaAccessWrapper
+ * jdk.test.lib.Asserts
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * -Dcompiler.jvmci.events.JvmciCreateMetaAccessContextTest.providenull=true
+ * compiler.jvmci.events.JvmciCreateMetaAccessContextTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Xbootclasspath/a:.
+ * -Dcompiler.jvmci.events.JvmciCreateMetaAccessContextTest.providenull=false
+ * compiler.jvmci.events.JvmciCreateMetaAccessContextTest
+ */
+
+package compiler.jvmci.events;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+import jdk.vm.ci.hotspot.MetaAccessWrapper;
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.test.lib.Asserts;
+
+public class JvmciCreateMetaAccessContextTest
+ implements HotSpotVMEventListener {
+ private static final boolean PROVIDE_NULL_CONTEXT = Boolean.getBoolean(
+ "compiler.jvmci.events.JvmciCreateMetaAccessContextTest"
+ + ".providenull");
+ private static volatile int createMetaAccessContextCount = 0;
+ private static volatile String errorMessage = "";
+
+ public static void main(String args[]) {
+ if (createMetaAccessContextCount != 0) {
+ throw new Error("Unexpected createMetaAccessContextevents count"
+ + " at test start");
+ }
+ JVMCIMetaAccessContext context;
+ context = HotSpotJVMCIRuntime.runtime().getMetaAccessContext();
+ Asserts.assertNotNull(context,
+ "JVMCIMetaAccessContext is null after 1st request");
+ Asserts.assertEQ(createMetaAccessContextCount, 1,
+ "Unexpected createMetaAccessContext events count after 1st"
+ + " JVMCI runtime request");
+ context = HotSpotJVMCIRuntime.runtime().getMetaAccessContext();
+ Asserts.assertNotNull(context,
+ "JVMCIMetaAccessContext is null after 2nd request");
+ Asserts.assertEQ(createMetaAccessContextCount, 1,
+ "Unexpected createMetaAccessContext events count after 2nd"
+ + " JVMCI runtime request");
+ Asserts.assertTrue(errorMessage.isEmpty(), errorMessage);
+ if (PROVIDE_NULL_CONTEXT) {
+ Asserts.assertFalse(context instanceof MetaAccessWrapper,
+ "Got unexpected context: " + context.getClass());
+ } else {
+ Asserts.assertTrue(context instanceof MetaAccessWrapper,
+ "Got unexpected context: " + context.getClass());
+ }
+ }
+
+ @Override
+ public JVMCIMetaAccessContext createMetaAccessContext(HotSpotJVMCIRuntime
+ hotSpotJVMCIRuntime) {
+ createMetaAccessContextCount++;
+ if (hotSpotJVMCIRuntime == null) {
+ errorMessage += " HotSpotJVMCIRuntime is null.";
+ }
+ if (PROVIDE_NULL_CONTEXT) {
+ return null;
+ }
+ return new MetaAccessWrapper();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.config Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.events.JvmciNotifyInstallEventTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.common.JVMCIHelpers
+ * compiler.jvmci.events.JvmciNotifyInstallEventTest
+ * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
+ * @run main jdk.test.lib.FileInstaller ./JvmciNotifyInstallEventTest.config
+ * ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener
+ * @run main ClassFileInstaller
+ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
+ * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
+ * compiler.jvmci.events.JvmciNotifyInstallEventTest
+ * compiler.jvmci.common.CTVMUtilities
+ * compiler.jvmci.common.testcases.SimpleClass
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * jdk.test.lib.Asserts
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
+ * -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI
+ * -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.noevent=false
+ * compiler.jvmci.events.JvmciNotifyInstallEventTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-EnableJVMCI
+ * -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
+ * -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.noevent=true
+ * compiler.jvmci.events.JvmciNotifyInstallEventTest
+ */
+
+package compiler.jvmci.events;
+
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.SimpleClass;
+import jdk.test.lib.Asserts;
+import java.lang.reflect.Method;
+import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+
+public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener {
+ private static final String METHOD_NAME = "testMethod";
+ private static final boolean IS_POSITIVE = !Boolean.getBoolean(
+ "compiler.jvmci.events.JvmciNotifyInstallEventTest.noevent");
+ private static volatile int gotInstallNotification = 0;
+
+ public static void main(String args[]) {
+ new JvmciNotifyInstallEventTest().runTest();
+ }
+
+ private void runTest() {
+ if (gotInstallNotification != 0) {
+ throw new Error("Got install notification before test actions");
+ }
+ HotSpotCodeCacheProvider codeCache = null;
+ try {
+ codeCache = (HotSpotCodeCacheProvider) HotSpotJVMCIRuntime.runtime()
+ .getHostJVMCIBackend().getCodeCache();
+ } catch (InternalError ie) {
+ if (IS_POSITIVE) {
+ throw new AssertionError(
+ "Got unexpected InternalError trying to get code cache",
+ ie);
+ }
+ // passed
+ return;
+ }
+ Asserts.assertTrue(IS_POSITIVE,
+ "Haven't caught InternalError in negative case");
+ Method testMethod;
+ try {
+ testMethod = SimpleClass.class.getDeclaredMethod(METHOD_NAME);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TEST BUG: Can't find " + METHOD_NAME, e);
+ }
+ HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+ .getResolvedMethod(SimpleClass.class, testMethod);
+ CompilationResult compResult = new CompilationResult(METHOD_NAME);
+ // to pass sanity check of default -1
+ compResult.setTotalFrameSize(0);
+ codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L,
+ /* isDefault = */ false);
+ Asserts.assertEQ(gotInstallNotification, 1,
+ "Got unexpected event count after 1st install attempt");
+ // since "empty" compilation result is ok, a second attempt should be ok
+ codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L,
+ /* isDefault = */ false);
+ Asserts.assertEQ(gotInstallNotification, 2,
+ "Got unexpected event count after 2nd install attempt");
+ }
+
+ @Override
+ public void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider,
+ InstalledCode installedCode, CompilationResult compResult) {
+ gotInstallNotification++;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventListener.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package compiler.jvmci.events;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+
+public class JvmciShutdownEventListener implements HotSpotVMEventListener {
+ public static final String MESSAGE = "Shutdown notified";
+ public static final String GOT_INTERNAL_ERROR = "Got internal error";
+
+ public static void main(String args[]) {
+ try {
+ HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
+ } catch (InternalError e) {
+ System.out.println(GOT_INTERNAL_ERROR);
+ }
+ }
+
+ @Override
+ public void notifyShutdown() {
+ System.out.println(MESSAGE);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.config Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,1 @@
+compiler.jvmci.events.JvmciShutdownEventListener
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library /testlibrary /
+ * @build compiler.jvmci.common.JVMCIHelpers
+ * compiler.jvmci.events.JvmciShutdownEventListener
+ * compiler.jvmci.events.JvmciShutdownEventTest
+ * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
+ * @run main jdk.test.lib.FileInstaller ./JvmciShutdownEventTest.config
+ * ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener
+ * @run main ClassFileInstaller
+ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
+ * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
+ * compiler.jvmci.events.JvmciShutdownEventListener
+ * @run driver
+ * compiler.jvmci.events.JvmciShutdownEventTest
+ */
+
+package compiler.jvmci.events;
+
+import jdk.test.lib.ExitCode;
+import jdk.test.lib.cli.CommandLineOptionTest;
+
+public class JvmciShutdownEventTest {
+ private final static String[] MESSAGE = new String[]{
+ JvmciShutdownEventListener.MESSAGE
+ };
+
+ private final static String[] ERROR_MESSAGE = new String[]{
+ JvmciShutdownEventListener.GOT_INTERNAL_ERROR
+ };
+
+ public static void main(String args[]) throws Throwable {
+ boolean addTestVMOptions = true;
+ CommandLineOptionTest.verifyJVMStartup(MESSAGE, ERROR_MESSAGE,
+ "Unexpected exit code with +EnableJVMCI",
+ "Unexpected output with +EnableJVMCI", ExitCode.OK,
+ addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
+ "-XX:+EnableJVMCI", "-Xbootclasspath/a:.",
+ JvmciShutdownEventListener.class.getName()
+ );
+
+ CommandLineOptionTest.verifyJVMStartup(ERROR_MESSAGE, MESSAGE,
+ "Unexpected exit code with -EnableJVMCI",
+ "Unexpected output with -EnableJVMCI", ExitCode.OK,
+ addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
+ "-XX:-EnableJVMCI", "-Xbootclasspath/a:.",
+ JvmciShutdownEventListener.class.getName()
+ );
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/events/MetaAccessWrapper.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/*
+ * A JVMCIMetaAccessContext wrapper class to mark context
+ * being provided/returned
+ */
+public class MetaAccessWrapper implements JVMCIMetaAccessContext {
+ private static final HotSpotJVMCIMetaAccessContext CONTEXT
+ = new HotSpotJVMCIMetaAccessContext();
+ @Override
+ public ResolvedJavaType fromClass(Class<?> clazz) {
+ return CONTEXT.fromClass(clazz);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013, 2015, 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"
+ * @run junit jdk.vm.ci.options.test.NestedBooleanOptionValueTest
+ */
+
+package jdk.vm.ci.options.test;
+
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.*;
+import static org.junit.Assert.*;
+import jdk.vm.ci.options.*;
+import jdk.vm.ci.options.OptionValue.*;
+
+import org.junit.*;
+
+public class NestedBooleanOptionValueTest {
+
+ public static class Options {
+ public static final OptionValue<Boolean> Master0 = new OptionValue<>(true);
+ public static final OptionValue<Boolean> NestedOption0 = new NestedBooleanOptionValue(Master0, true);
+ public static final OptionValue<Boolean> Master1 = new OptionValue<>(true);
+ public static final OptionValue<Boolean> NestedOption1 = new NestedBooleanOptionValue(Master1, true);
+ public static final OptionValue<Boolean> Master2 = new OptionValue<>(true);
+ public static final OptionValue<Boolean> NestedOption2 = new NestedBooleanOptionValue(Master2, false);
+ }
+
+ static final OptionDescriptor master0 = OptionDescriptor.create("Master0", Boolean.class, "", Options.class, "Master0", Master0);
+ static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
+ static final OptionDescriptor master1 = OptionDescriptor.create("Master1", Boolean.class, "", Options.class, "Master1", Master1);
+ static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
+ static final OptionDescriptor master2 = OptionDescriptor.create("Master2", Boolean.class, "", Options.class, "Master2", Master2);
+ static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
+
+ @SuppressWarnings("try")
+ @Test
+ public void runOverrides() {
+ assertTrue(Master0.getValue());
+ assertTrue(NestedOption0.getValue());
+ try (OverrideScope s1 = OptionValue.override(Master0, false)) {
+ assertFalse(Master0.getValue());
+ assertFalse(NestedOption0.getValue());
+ try (OverrideScope s2 = OptionValue.override(NestedOption0, false)) {
+ assertFalse(NestedOption0.getValue());
+ }
+ try (OverrideScope s2 = OptionValue.override(NestedOption0, true)) {
+ assertTrue(NestedOption0.getValue());
+ }
+ }
+ assertTrue(Master0.getValue());
+ try (OverrideScope s1 = OptionValue.override(NestedOption0, false)) {
+ assertFalse(NestedOption0.getValue());
+ }
+ try (OverrideScope s1 = OptionValue.override(NestedOption0, true)) {
+ assertTrue(NestedOption0.getValue());
+ }
+ }
+
+ @Test
+ public void runDefaultTrue() {
+ Master1.setValue(true);
+ assertTrue(Master1.getValue());
+ assertTrue(NestedOption1.getValue());
+ // nested value unset
+ Master1.setValue(false);
+ assertFalse(Master1.getValue());
+ assertFalse(NestedOption1.getValue());
+ // set false
+ Master1.setValue(false);
+ NestedOption1.setValue(false);
+ assertFalse(Master1.getValue());
+ assertFalse(NestedOption1.getValue());
+ Master1.setValue(true);
+ assertTrue(Master1.getValue());
+ assertFalse(NestedOption1.getValue());
+ // set true
+ Master1.setValue(false);
+ NestedOption1.setValue(true);
+ assertFalse(Master1.getValue());
+ assertTrue(NestedOption1.getValue());
+ Master1.setValue(true);
+ assertTrue(Master1.getValue());
+ assertTrue(NestedOption1.getValue());
+ }
+
+ @Test
+ public void runDefaultFalse() {
+ Master2.setValue(true);
+ assertTrue(Master2.getValue());
+ assertFalse(NestedOption2.getValue());
+ // nested value unset
+ Master2.setValue(false);
+ assertFalse(Master2.getValue());
+ assertFalse(NestedOption2.getValue());
+ // set false
+ Master2.setValue(false);
+ NestedOption2.setValue(false);
+ assertFalse(Master2.getValue());
+ assertFalse(NestedOption2.getValue());
+ Master2.setValue(true);
+ assertTrue(Master2.getValue());
+ assertFalse(NestedOption2.getValue());
+ // set true
+ Master2.setValue(false);
+ NestedOption2.setValue(true);
+ assertFalse(Master2.getValue());
+ assertTrue(NestedOption2.getValue());
+ Master2.setValue(true);
+ assertTrue(Master2.getValue());
+ assertTrue(NestedOption2.getValue());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013, 2015, 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"
+ * @run junit jdk.vm.ci.options.test.TestOptionValue
+ */
+
+package jdk.vm.ci.options.test;
+
+import static jdk.vm.ci.options.test.TestOptionValue.Options.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import jdk.vm.ci.options.*;
+import jdk.vm.ci.options.OptionValue.*;
+
+import org.junit.*;
+
+@SuppressWarnings("try")
+public class TestOptionValue {
+
+ public static class Options {
+ public static final OptionValue<Boolean> Stable = new StableOptionValue<>(true);
+ public static final OptionValue<String> Mutable = new OptionValue<>("original");
+ public static final OptionValue<String> SecondMutable = new OptionValue<>("second");
+ }
+
+ static final OptionDescriptor stable = OptionDescriptor.create("Stable", Boolean.class, "", Options.class, "Stable", Stable);
+ static final OptionDescriptor mutable = OptionDescriptor.create("Mutable", String.class, "", Options.class, "Mutable", Mutable);
+ static final OptionDescriptor secondMutable = OptionDescriptor.create("SecondMutable", String.class, "", Options.class, "SecondMutable", SecondMutable);
+
+ @Test
+ public void testMutable() {
+ assertEquals("original", Mutable.getValue());
+ try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+ assertEquals("override1", Mutable.getValue());
+ try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+ assertEquals("override2", Mutable.getValue());
+ }
+ assertEquals("override1", Mutable.getValue());
+ try (OverrideScope s3 = OptionValue.override(Mutable, "override3")) {
+ assertEquals("override3", Mutable.getValue());
+ }
+ assertEquals("override1", Mutable.getValue());
+ }
+ assertEquals("original", Mutable.getValue());
+ try (OverrideScope s1 = OptionValue.override(Mutable, "original")) {
+ assertEquals("original", Mutable.getValue());
+ }
+ }
+
+ @Test
+ public void testMultiple() {
+ assertEquals("original", Mutable.getValue());
+ assertEquals("second", SecondMutable.getValue());
+ try (OverrideScope s1 = OptionValue.override(Mutable, "override1", SecondMutable, "secondOverride1")) {
+ assertEquals("override1", Mutable.getValue());
+ assertEquals("secondOverride1", SecondMutable.getValue());
+ try (OverrideScope s2 = OptionValue.override(Mutable, "override2", SecondMutable, "secondOverride2")) {
+ assertEquals("override2", Mutable.getValue());
+ assertEquals("secondOverride2", SecondMutable.getValue());
+ }
+ assertEquals("override1", Mutable.getValue());
+ assertEquals("secondOverride1", SecondMutable.getValue());
+ try (OverrideScope s3 = OptionValue.override(Mutable, "override3", SecondMutable, "secondOverride3")) {
+ assertEquals("override3", Mutable.getValue());
+ assertEquals("secondOverride3", SecondMutable.getValue());
+ }
+ assertEquals("override1", Mutable.getValue());
+ assertEquals("secondOverride1", SecondMutable.getValue());
+ }
+ assertEquals("original", Mutable.getValue());
+ assertEquals("second", SecondMutable.getValue());
+ try (OverrideScope s1 = OptionValue.override(Mutable, "original", SecondMutable, "second")) {
+ assertEquals("original", Mutable.getValue());
+ assertEquals("second", SecondMutable.getValue());
+ }
+ }
+
+ @Test
+ public void testStable() {
+ assertTrue(Stable.getValue());
+ try (OverrideScope s = OptionValue.override(Stable, false)) {
+ fail("cannot override stable option");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void toStringTest() {
+ assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=original", Mutable.toString());
+ try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+ assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=override1", Mutable.toString());
+ try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+ assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=override2", Mutable.toString());
+ }
+ }
+ }
+
+ @Test
+ public void getValuesTest() {
+ assertEquals(Arrays.asList("original"), Mutable.getValues(null));
+ assertEquals(Arrays.asList(true), Stable.getValues(null));
+ try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+ assertEquals(Arrays.asList("override1", "original"), Mutable.getValues(null));
+ try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+ assertEquals(Arrays.asList("override2", "override1", "original"), Mutable.getValues(null));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2015, 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 ConstantTest.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ConstantTest
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+public class ConstantTest extends FieldUniverse {
+
+ @Test
+ public void testNegativeZero() {
+ Assert.assertTrue("Constant for 0.0f must be different from -0.0f", JavaConstant.FLOAT_0 != JavaConstant.forFloat(-0.0F));
+ Assert.assertTrue("Constant for 0.0d must be different from -0.0d", JavaConstant.DOUBLE_0 != JavaConstant.forDouble(-0.0d));
+ }
+
+ @Test
+ public void testNullIsNull() {
+ Assert.assertTrue(JavaConstant.NULL_POINTER.isNull());
+ }
+
+ @Test
+ public void testOne() {
+ for (JavaKind kind : JavaKind.values()) {
+ if (kind.isNumericInteger() || kind.isNumericFloat()) {
+ Assert.assertTrue(JavaConstant.one(kind).getJavaKind() == kind);
+ }
+ }
+ Assert.assertEquals(1, JavaConstant.one(JavaKind.Int).asInt());
+ Assert.assertEquals(1L, JavaConstant.one(JavaKind.Long).asLong());
+ Assert.assertEquals(1, JavaConstant.one(JavaKind.Byte).asInt());
+ Assert.assertEquals(1, JavaConstant.one(JavaKind.Short).asInt());
+ Assert.assertEquals(1, JavaConstant.one(JavaKind.Char).asInt());
+ Assert.assertTrue(1F == JavaConstant.one(JavaKind.Float).asFloat());
+ Assert.assertTrue(1D == JavaConstant.one(JavaKind.Double).asDouble());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalOne() {
+ JavaConstant.one(JavaKind.Illegal);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testVoidOne() {
+ JavaConstant.one(JavaKind.Void);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Context for field related tests.
+ */
+public class FieldUniverse extends TypeUniverse {
+
+ public static final Map<Field, ResolvedJavaField> fields = new HashMap<>();
+
+ {
+ for (Class<?> c : classes) {
+ for (Field f : c.getDeclaredFields()) {
+ ResolvedJavaField field = metaAccess.lookupJavaField(f);
+ fields.put(f, field);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Context for method related tests.
+ */
+public class MethodUniverse extends TypeUniverse {
+
+ public static final Map<Method, ResolvedJavaMethod> methods = new HashMap<>();
+ public static final Map<Constructor<?>, ResolvedJavaMethod> constructors = new HashMap<>();
+
+ {
+ for (Class<?> c : classes) {
+ for (Method m : c.getDeclaredMethods()) {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
+ methods.put(m, method);
+ }
+ for (Constructor<?> m : c.getDeclaredConstructors()) {
+ constructors.put(m, metaAccess.lookupJavaMethod(m));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+package jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+
+class NameAndSignature {
+
+ public static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+
+ final String name;
+ final Class<?> returnType;
+ final Class<?>[] parameterTypes;
+
+ public NameAndSignature(Method m) {
+ this.name = m.getName();
+ this.returnType = m.getReturnType();
+ this.parameterTypes = m.getParameterTypes();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NameAndSignature) {
+ NameAndSignature s = (NameAndSignature) obj;
+ return s.returnType == returnType && name.equals(s.name) && Arrays.equals(s.parameterTypes, parameterTypes);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(name + "(");
+ String sep = "";
+ for (Class<?> p : parameterTypes) {
+ sb.append(sep);
+ sep = ", ";
+ sb.append(p.getName());
+ }
+ return sb.append(')').append(returnType.getName()).toString();
+ }
+
+ public boolean signatureEquals(ResolvedJavaMethod m) {
+ Signature s = m.getSignature();
+ ResolvedJavaType declaringClass = m.getDeclaringClass();
+ if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(returnType))) {
+ return false;
+ }
+ if (s.getParameterCount(false) != parameterTypes.length) {
+ return false;
+ }
+ for (int i = 0; i < parameterTypes.length; i++) {
+ if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(parameterTypes[i]))) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011, 2015, 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 RedefineClassTest.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.RedefineClassTest
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assume.*;
+
+import java.io.*;
+import java.lang.instrument.*;
+import java.lang.management.*;
+import java.lang.reflect.*;
+import java.nio.file.*;
+import java.security.*;
+import java.util.*;
+import java.util.jar.*;
+
+import javax.tools.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests that {@link ResolvedJavaMethod}s are safe in the context of class redefinition being used
+ * to redefine the method to which they refer.
+ */
+public class RedefineClassTest extends TypeUniverse {
+
+ static class Foo {
+ public static Object getName() {
+ return "foo";
+ }
+ }
+
+ @Test
+ public void test() throws Throwable {
+
+ Method fooMethod = Foo.class.getDeclaredMethod("getName");
+
+ ResolvedJavaMethod foo1 = metaAccess.lookupJavaMethod(fooMethod);
+ ResolvedJavaMethod foo2 = metaAccess.lookupJavaMethod(fooMethod);
+
+ String foo1Code = Arrays.toString(foo1.getCode());
+ String foo2Code = Arrays.toString(foo2.getCode());
+
+ Assert.assertEquals("foo", Foo.getName());
+
+ redefineFoo();
+ System.gc();
+
+ // Make sure the transformation happened
+ Assert.assertEquals("bar", Foo.getName());
+
+ Assert.assertEquals(foo1Code, Arrays.toString(foo1.getCode()));
+ Assert.assertEquals(foo2Code, Arrays.toString(foo1.getCode()));
+ }
+
+ /**
+ * Adds the class file bytes for a given class to a JAR stream.
+ */
+ static void add(JarOutputStream jar, Class<?> c) throws IOException {
+ String name = c.getName();
+ String classAsPath = name.replace('.', '/') + ".class";
+ jar.putNextEntry(new JarEntry(classAsPath));
+
+ InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
+
+ int nRead;
+ byte[] buf = new byte[1024];
+ while ((nRead = stream.read(buf, 0, buf.length)) != -1) {
+ jar.write(buf, 0, nRead);
+ }
+
+ jar.closeEntry();
+ }
+
+ protected void redefineFoo() throws Exception {
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ Attributes mainAttrs = manifest.getMainAttributes();
+ mainAttrs.putValue("Agent-Class", FooAgent.class.getName());
+ mainAttrs.putValue("Can-Redefine-Classes", "true");
+ mainAttrs.putValue("Can-Retransform-Classes", "true");
+
+ Path jar = Files.createTempFile("myagent", ".jar");
+ try {
+ JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jar.toFile()), manifest);
+ add(jarStream, FooAgent.class);
+ add(jarStream, FooTransformer.class);
+ jarStream.close();
+
+ loadAgent(jar);
+ } finally {
+ Files.deleteIfExists(jar);
+ }
+ }
+
+ public static void loadAgent(Path agent) throws Exception {
+ String vmName = ManagementFactory.getRuntimeMXBean().getName();
+ int p = vmName.indexOf('@');
+ assumeTrue(p != -1);
+ String pid = vmName.substring(0, p);
+ ClassLoader cl = ToolProvider.getSystemToolClassLoader();
+ Class<?> c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
+ Method attach = c.getDeclaredMethod("attach", String.class);
+ Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class);
+ Method detach = c.getDeclaredMethod("detach");
+ Object vm = attach.invoke(null, pid);
+ loadAgent.invoke(vm, agent.toString(), "");
+ detach.invoke(vm);
+ }
+
+ public static class FooAgent {
+
+ public static void agentmain(@SuppressWarnings("unused") String args, Instrumentation inst) throws Exception {
+ if (inst.isRedefineClassesSupported() && inst.isRetransformClassesSupported()) {
+ inst.addTransformer(new FooTransformer(), true);
+ Class<?>[] allClasses = inst.getAllLoadedClasses();
+ for (int i = 0; i < allClasses.length; i++) {
+ Class<?> c = allClasses[i];
+ if (c == Foo.class) {
+ inst.retransformClasses(new Class<?>[]{c});
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * This transformer replaces the first instance of the constant "foo" in the class file for
+ * {@link Foo} with "bar".
+ */
+ static class FooTransformer implements ClassFileTransformer {
+
+ @Override
+ public byte[] transform(ClassLoader cl, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+ if (Foo.class.equals(classBeingRedefined)) {
+ String cf = new String(classfileBuffer);
+ int i = cf.indexOf("foo");
+ Assert.assertTrue("cannot find \"foo\" constant in " + Foo.class.getSimpleName() + "'s class file", i > 0);
+ classfileBuffer[i] = 'b';
+ classfileBuffer[i + 1] = 'a';
+ classfileBuffer[i + 2] = 'r';
+ }
+ return classfileBuffer;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2014, 2015, 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"
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+
+import org.junit.*;
+
+public class ResolvedJavaTypeResolveConcreteMethodTest {
+ public final MetaAccessProvider metaAccess;
+
+ public ResolvedJavaTypeResolveConcreteMethodTest() {
+ metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ }
+
+ protected abstract static class A {
+ @SuppressWarnings("unused")
+ private void priv() {
+ }
+
+ public void v1() {
+ }
+
+ public void v2() {
+ }
+
+ public abstract void abs();
+ }
+
+ protected static class B extends A implements I {
+ public void i() {
+ }
+
+ @Override
+ public void v2() {
+ }
+
+ @Override
+ public void abs() {
+
+ }
+ }
+
+ protected static class C extends B {
+ public void d() {
+ }
+ }
+
+ protected abstract static class D extends A {
+
+ }
+
+ protected static class E extends D {
+ @Override
+ public void abs() {
+ }
+ }
+
+ protected interface I {
+ void i();
+
+ default void d() {
+ }
+ }
+
+ @Test
+ public void testDefaultMethod() {
+ ResolvedJavaType i = getType(I.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod di = getMethod(i, "d");
+ ResolvedJavaMethod dc = getMethod(c, "d");
+
+ assertEquals(di, i.resolveConcreteMethod(di, c));
+ assertEquals(di, b.resolveConcreteMethod(di, c));
+ assertEquals(dc, c.resolveConcreteMethod(di, c));
+ }
+
+ @Test
+ public void testPrivateMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod priv = getMethod(a, "priv");
+
+ assertNull(a.resolveConcreteMethod(priv, c));
+ assertNull(b.resolveConcreteMethod(priv, c));
+ }
+
+ @Test
+ public void testAbstractMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaType d = getType(D.class);
+ ResolvedJavaType e = getType(E.class);
+ ResolvedJavaMethod absa = getMethod(a, "abs");
+ ResolvedJavaMethod absb = getMethod(b, "abs");
+ ResolvedJavaMethod abse = getMethod(e, "abs");
+
+ assertNull(a.resolveConcreteMethod(absa, c));
+ assertNull(d.resolveConcreteMethod(absa, c));
+
+ assertEquals(absb, b.resolveConcreteMethod(absa, c));
+ assertEquals(absb, b.resolveConcreteMethod(absb, c));
+ assertEquals(absb, c.resolveConcreteMethod(absa, c));
+ assertEquals(absb, c.resolveConcreteMethod(absb, c));
+ assertEquals(abse, e.resolveConcreteMethod(absa, c));
+ assertNull(e.resolveConcreteMethod(absb, c));
+ assertEquals(abse, e.resolveConcreteMethod(abse, c));
+ }
+
+ @Test
+ public void testVirtualMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod v1a = getMethod(a, "v1");
+ ResolvedJavaMethod v2a = getMethod(a, "v2");
+ ResolvedJavaMethod v2b = getMethod(b, "v2");
+
+ assertEquals(v1a, a.resolveConcreteMethod(v1a, c));
+ assertEquals(v1a, b.resolveConcreteMethod(v1a, c));
+ assertEquals(v1a, c.resolveConcreteMethod(v1a, c));
+ assertEquals(v2a, a.resolveConcreteMethod(v2a, c));
+ assertEquals(v2b, b.resolveConcreteMethod(v2a, c));
+ assertEquals(v2b, b.resolveConcreteMethod(v2b, c));
+ assertEquals(v2b, c.resolveConcreteMethod(v2a, c));
+ assertEquals(v2b, c.resolveConcreteMethod(v2b, c));
+
+ }
+
+ static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+ for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+ if (method.getName().equals(methodName)) {
+ return method;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ protected ResolvedJavaType getType(Class<?> clazz) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
+ type.initialize();
+ return type;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2014, 2015, 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"
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+
+import org.junit.*;
+
+public class ResolvedJavaTypeResolveMethodTest {
+ public final MetaAccessProvider metaAccess;
+
+ public ResolvedJavaTypeResolveMethodTest() {
+ metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ }
+
+ protected abstract static class A {
+ @SuppressWarnings("unused")
+ private void priv() {
+ }
+
+ public void v1() {
+ }
+
+ public void v2() {
+ }
+
+ public abstract void abs();
+ }
+
+ protected static class B extends A implements I {
+ public void i() {
+ }
+
+ @Override
+ public void v2() {
+ }
+
+ @Override
+ public void abs() {
+
+ }
+ }
+
+ protected static class C extends B {
+ public void d() {
+ }
+ }
+
+ protected abstract static class D extends A {
+
+ }
+
+ protected static class E extends D {
+ @Override
+ public void abs() {
+ }
+ }
+
+ protected interface I {
+ void i();
+
+ default void d() {
+ }
+ }
+
+ @Test
+ public void testDefaultMethod() {
+ ResolvedJavaType i = getType(I.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod di = getMethod(i, "d");
+ ResolvedJavaMethod dc = getMethod(c, "d");
+
+ assertEquals(di, i.resolveMethod(di, c));
+ assertEquals(di, b.resolveMethod(di, c));
+ assertEquals(dc, c.resolveMethod(di, c));
+ }
+
+ @Test
+ public void testPrivateMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod priv = getMethod(a, "priv");
+
+ assertNull(a.resolveMethod(priv, c));
+ assertNull(b.resolveMethod(priv, c));
+ }
+
+ @Test
+ public void testAbstractMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaType d = getType(D.class);
+ ResolvedJavaType e = getType(E.class);
+ ResolvedJavaMethod absa = getMethod(a, "abs");
+ ResolvedJavaMethod absb = getMethod(b, "abs");
+ ResolvedJavaMethod abse = getMethod(e, "abs");
+
+ assertEquals(absa, a.resolveMethod(absa, c));
+ assertEquals(absa, d.resolveMethod(absa, c));
+
+ assertEquals(absb, b.resolveMethod(absa, c));
+ assertEquals(absb, b.resolveMethod(absb, c));
+ assertEquals(absb, c.resolveMethod(absa, c));
+ assertEquals(absb, c.resolveMethod(absb, c));
+ assertEquals(abse, e.resolveMethod(absa, c));
+ assertNull(e.resolveMethod(absb, c));
+ assertEquals(abse, e.resolveMethod(abse, c));
+ }
+
+ @Test
+ public void testVirtualMethod() {
+ ResolvedJavaType a = getType(A.class);
+ ResolvedJavaType b = getType(B.class);
+ ResolvedJavaType c = getType(C.class);
+ ResolvedJavaMethod v1a = getMethod(a, "v1");
+ ResolvedJavaMethod v2a = getMethod(a, "v2");
+ ResolvedJavaMethod v2b = getMethod(b, "v2");
+
+ assertEquals(v1a, a.resolveMethod(v1a, c));
+ assertEquals(v1a, b.resolveMethod(v1a, c));
+ assertEquals(v1a, c.resolveMethod(v1a, c));
+ assertEquals(v2a, a.resolveMethod(v2a, c));
+ assertEquals(v2b, b.resolveMethod(v2a, c));
+ assertEquals(v2b, b.resolveMethod(v2b, c));
+ assertEquals(v2b, c.resolveMethod(v2a, c));
+ assertEquals(v2b, c.resolveMethod(v2b, c));
+
+ }
+
+ static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+ for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+ if (method.getName().equals(methodName)) {
+ return method;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ protected ResolvedJavaType getType(Class<?> clazz) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
+ type.initialize();
+ return type;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestConstantReflectionProvider.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestConstantReflectionProvider
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that
+ * actually returns non-null results for access operations that are possible, i.e., the tests will
+ * fail for an implementation that spuriously returns null (which is allowed by the specification).
+ */
+public class TestConstantReflectionProvider extends TypeUniverse {
+
+ @Test
+ public void constantEqualsTest() {
+ for (ConstantValue c1 : constants()) {
+ for (ConstantValue c2 : constants()) {
+ // test symmetry
+ assertEquals(constantReflection.constantEquals(c1.value, c2.value), constantReflection.constantEquals(c2.value, c1.value));
+ if (c1.value.getJavaKind() != JavaKind.Object && c2.value.getJavaKind() != JavaKind.Object) {
+ assertEquals(c1.value.equals(c2.value), constantReflection.constantEquals(c2.value, c1.value));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void readArrayLengthTest() {
+ for (ConstantValue cv : constants()) {
+ JavaConstant c = cv.value;
+ Integer actual = constantReflection.readArrayLength(c);
+ if (c.getJavaKind() != JavaKind.Object || c.isNull() || !cv.boxed.getClass().isArray()) {
+ assertNull(actual);
+ } else {
+ assertNotNull(actual);
+ int actualInt = actual;
+ assertEquals(Array.getLength(cv.boxed), actualInt);
+ }
+ }
+ }
+
+ static class PrimitiveConstants {
+ static final long LONG_CONST = 42;
+ static final int INT_CONST = 66;
+ static final byte BYTE_CONST = 123;
+ static final boolean BOOL_CONST = true;
+ }
+
+ static class BoxedConstants {
+ static final Long LONG_CONST = 42L;
+ static final Integer INT_CONST = 66;
+ static final Byte BYTE_CONST = 123;
+ static final Boolean BOOL_CONST = true;
+ }
+
+ @Test
+ public void boxTest() {
+ for (ConstantValue cv : constants()) {
+ JavaConstant c = cv.value;
+ JavaConstant boxed = constantReflection.boxPrimitive(c);
+ if (boxed != null && c.getJavaKind().isPrimitive()) {
+ assertTrue(boxed.getJavaKind().isObject());
+ assertFalse(boxed.isNull());
+ }
+ }
+
+ List<ConstantValue> primitiveConstants = readConstants(PrimitiveConstants.class);
+ List<ConstantValue> boxedConstants = readConstants(BoxedConstants.class);
+ for (int i = 0; i < primitiveConstants.size(); i++) {
+ ConstantValue prim = primitiveConstants.get(i);
+ ConstantValue box = boxedConstants.get(i);
+ assertEquals(box.value, constantReflection.boxPrimitive(prim.value));
+ }
+
+ assertNull(constantReflection.boxPrimitive(JavaConstant.NULL_POINTER));
+ }
+
+ @Test
+ public void unboxTest() {
+ for (ConstantValue cv : constants()) {
+ JavaConstant c = cv.value;
+ JavaConstant unboxed = c.isNull() ? null : constantReflection.unboxPrimitive(c);
+ if (unboxed != null) {
+ assertFalse(unboxed.getJavaKind().isObject());
+ }
+ }
+ List<ConstantValue> primitiveConstants = readConstants(PrimitiveConstants.class);
+ List<ConstantValue> boxedConstants = readConstants(BoxedConstants.class);
+ for (int i = 0; i < primitiveConstants.size(); i++) {
+ ConstantValue prim = primitiveConstants.get(i);
+ ConstantValue box = boxedConstants.get(i);
+ assert prim.getSimpleName().equals(box.getSimpleName());
+ assertEquals(prim.value, constantReflection.unboxPrimitive(box.value));
+ }
+
+ assertNull(constantReflection.unboxPrimitive(JavaConstant.NULL_POINTER));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestJavaField.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaField
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link JavaField}.
+ */
+public class TestJavaField extends FieldUniverse {
+
+ @Test
+ public void getNameTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ String expected = e.getKey().getName();
+ String actual = e.getValue().getName();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getTypeTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ // Must resolve types first as a resolved types != unresolved types
+ ResolvedJavaField rf = e.getValue();
+ JavaType expected = metaAccess.lookupJavaType(e.getKey().getType()).resolve(rf.getDeclaringClass());
+ JavaType actual = rf.getType().resolve(rf.getDeclaringClass());
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getJavaKindTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ JavaKind expected = metaAccess.lookupJavaType(e.getKey().getType()).getJavaKind();
+ JavaKind actual = e.getValue().getJavaKind();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getDeclaringClassTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ Class<?> expected = e.getKey().getDeclaringClass();
+ ResolvedJavaType actual = e.getValue().getDeclaringClass();
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java NameAndSignature.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaMethod
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link JavaMethod}.
+ */
+public class TestJavaMethod extends MethodUniverse {
+
+ @Test
+ public void getNameTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ String expected = e.getKey().getName();
+ String actual = e.getValue().getName();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getDeclaringClassTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ Class<?> expected = e.getKey().getDeclaringClass();
+ ResolvedJavaType actual = e.getValue().getDeclaringClass();
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+
+ @Test
+ public void getSignatureTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ assertTrue(new NameAndSignature(e.getKey()).signatureEquals(e.getValue()));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestJavaType.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaType
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import jdk.vm.ci.meta.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link JavaType}.
+ */
+public class TestJavaType extends TypeUniverse {
+
+ public TestJavaType() {
+ }
+
+ @Test
+ public void getJavaKindTest() {
+ for (Class<?> c : classes) {
+ JavaType type = metaAccess.lookupJavaType(c);
+ JavaKind expected = JavaKind.fromJavaClass(c);
+ JavaKind actual = type.getJavaKind();
+ assertEquals(expected, actual);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestMetaAccessProvider.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestMetaAccessProvider
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static jdk.vm.ci.meta.MetaUtil.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link MetaAccessProvider}.
+ */
+public class TestMetaAccessProvider extends TypeUniverse {
+
+ @Test
+ public void lookupJavaTypeTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ assertNotNull(c.toString(), type);
+ assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
+ assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
+ assertEquals(c.toString(), c.getName(), type.toClassName());
+ if (!type.isArray()) {
+ assertEquals(c.toString(), c.getName(), type.toJavaName());
+ }
+ }
+ }
+
+ @Test
+ public void lookupJavaMethodTest() {
+ for (Class<?> c : classes) {
+ for (Method reflect : c.getDeclaredMethods()) {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflect);
+ assertNotNull(method);
+ assertTrue(method.getDeclaringClass().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
+ }
+ }
+ }
+
+ @Test
+ public void lookupJavaFieldTest() {
+ for (Class<?> c : classes) {
+ for (Field reflect : c.getDeclaredFields()) {
+ ResolvedJavaField field = metaAccess.lookupJavaField(reflect);
+ assertNotNull(field);
+ assertTrue(field.getDeclaringClass().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
+ }
+ }
+ }
+
+ @Test
+ public void lookupJavaTypeConstantTest() {
+ for (ConstantValue cv : constants()) {
+ JavaConstant c = cv.value;
+ if (c.getJavaKind() == JavaKind.Object && !c.isNull()) {
+ Object o = cv.boxed;
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ assertNotNull(type);
+ assertTrue(type.equals(metaAccess.lookupJavaType(o.getClass())));
+ } else {
+ assertEquals(metaAccess.lookupJavaType(c), null);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestResolvedJavaField.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaField
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link ResolvedJavaField}.
+ */
+public class TestResolvedJavaField extends FieldUniverse {
+
+ public TestResolvedJavaField() {
+ }
+
+ @Test
+ public void getModifiersTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ int expected = e.getKey().getModifiers();
+ int actual = e.getValue().getModifiers();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void isSyntheticTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ boolean expected = e.getKey().isSynthetic();
+ boolean actual = e.getValue().isSynthetic();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getAnnotationsTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ Annotation[] expected = e.getKey().getAnnotations();
+ Annotation[] actual = e.getValue().getAnnotations();
+ assertArrayEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getAnnotationTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ for (Annotation expected : e.getKey().getAnnotations()) {
+ if (expected != null) {
+ Annotation actual = e.getValue().getAnnotation(expected.annotationType());
+ assertEquals(expected, actual);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void getLocationIdentityTest() {
+ for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+ LocationIdentity identity = e.getValue().getLocationIdentity();
+ assertTrue(identity != null);
+ }
+ }
+
+ static class ReadConstantValueTestConstants {
+ String stringField = "field";
+ final String constantStringField = "constantField";
+
+ static final Object CONST1 = new ReadConstantValueTestConstants();
+ static final Object CONST2 = null;
+ static final Object CONST3 = new String();
+ }
+
+ @Test
+ public void readConstantValueTest() throws NoSuchFieldException {
+ ResolvedJavaField field = metaAccess.lookupJavaField(ReadConstantValueTestConstants.class.getDeclaredField("stringField"));
+ List<ConstantValue> receiverConstants = readConstants(ReadConstantValueTestConstants.class);
+ for (ConstantValue receiver : receiverConstants) {
+ JavaConstant value = constantReflection.readConstantFieldValue(field, receiver.value);
+ assertNull(value);
+ }
+
+ ResolvedJavaField constField = metaAccess.lookupJavaField(ReadConstantValueTestConstants.class.getDeclaredField("constantStringField"));
+ for (ConstantValue receiver : receiverConstants) {
+ JavaConstant value = constantReflection.readConstantFieldValue(constField, receiver.value);
+ if (value != null) {
+ Object expected = "constantField";
+ String actual = ((ReadConstantValueTestConstants) receiver.boxed).constantStringField;
+ assertTrue(actual + " != " + expected, actual == expected);
+ }
+ }
+ }
+
+ private Method findTestMethod(Method apiMethod) {
+ String testName = apiMethod.getName() + "Test";
+ for (Method m : getClass().getDeclaredMethods()) {
+ if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ // @formatter:off
+ private static final String[] untestedApiMethods = {
+ "getDeclaringClass",
+ "isInternal",
+ "isFinal"
+ };
+ // @formatter:on
+
+ /**
+ * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+ * for them or are added to {@link #untestedApiMethods}.
+ */
+ @Test
+ public void testCoverage() {
+ Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+ for (Method m : ResolvedJavaField.class.getDeclaredMethods()) {
+ if (m.isSynthetic()) {
+ continue;
+ }
+ if (findTestMethod(m) == null) {
+ assertTrue("test missing for " + m, known.contains(m.getName()));
+ } else {
+ assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestResolvedJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaMethod
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.annotation.*;
+import java.lang.invoke.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+import org.junit.*;
+
+/**
+ * Tests for {@link ResolvedJavaMethod}.
+ */
+public class TestResolvedJavaMethod extends MethodUniverse {
+
+ public TestResolvedJavaMethod() {
+ }
+
+ /**
+ * @see ResolvedJavaMethod#getCode()
+ */
+ @Test
+ public void getCodeTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ byte[] code = m.getCode();
+ if (code == null) {
+ assertTrue(m.getCodeSize() == 0);
+ } else {
+ if (m.isAbstract()) {
+ assertTrue(code.length == 0);
+ } else if (!m.isNative()) {
+ assertTrue(code.length > 0);
+ }
+ }
+ }
+ }
+
+ /**
+ * @see ResolvedJavaMethod#getCodeSize()
+ */
+ @Test
+ public void getCodeSizeTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ int codeSize = m.getCodeSize();
+ if (m.isAbstract()) {
+ assertTrue(codeSize == 0);
+ } else if (!m.isNative()) {
+ assertTrue(codeSize > 0);
+ }
+ }
+ }
+
+ @Test
+ public void getModifiersTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ int expected = e.getKey().getModifiers();
+ int actual = m.getModifiers();
+ assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ int expected = e.getKey().getModifiers();
+ int actual = m.getModifiers();
+ assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
+ }
+ }
+
+ /**
+ * @see ResolvedJavaMethod#isClassInitializer()
+ */
+ @Test
+ public void isClassInitializerTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ // Class initializers are hidden from reflection
+ ResolvedJavaMethod m = e.getValue();
+ assertFalse(m.isClassInitializer());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertFalse(m.isClassInitializer());
+ }
+ }
+
+ @Test
+ public void isConstructorTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertFalse(m.isConstructor());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertTrue(m.isConstructor());
+ }
+ }
+
+ @Test
+ public void isSyntheticTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+ }
+ }
+
+ @Test
+ public void isBridgeTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isBridge(), m.isBridge());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(false, m.isBridge());
+ }
+ }
+
+ @Test
+ public void isVarArgsTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+ }
+ }
+
+ @Test
+ public void isSynchronizedTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
+ }
+ }
+
+ @Test
+ public void canBeStaticallyBoundTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+ }
+ }
+
+ private static boolean canBeStaticallyBound(Member method) {
+ int modifiers = method.getModifiers();
+ return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
+ !Modifier.isAbstract(modifiers);
+ }
+
+ private static String methodWithExceptionHandlers(String p1, Object o2) {
+ try {
+ return p1.substring(100) + o2.toString();
+ } catch (IndexOutOfBoundsException e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Test
+ public void getExceptionHandlersTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithExceptionHandlers", String.class, Object.class));
+ ExceptionHandler[] handlers = method.getExceptionHandlers();
+ assertNotNull(handlers);
+ assertEquals(handlers.length, 3);
+ handlers[0].getCatchType().equals(metaAccess.lookupJavaType(IndexOutOfBoundsException.class));
+ handlers[1].getCatchType().equals(metaAccess.lookupJavaType(NullPointerException.class));
+ handlers[2].getCatchType().equals(metaAccess.lookupJavaType(RuntimeException.class));
+ }
+
+ private static String nullPointerExceptionOnFirstLine(Object o, String ignored) {
+ return o.toString() + ignored;
+ }
+
+ @Test
+ public void asStackTraceElementTest() throws NoSuchMethodException {
+ try {
+ nullPointerExceptionOnFirstLine(null, "ignored");
+ Assert.fail("should not reach here");
+ } catch (NullPointerException e) {
+ StackTraceElement expected = e.getStackTrace()[0];
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+ StackTraceElement actual = method.asStackTraceElement(0);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getConstantPoolTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ ConstantPool cp = m.getConstantPool();
+ assertTrue(cp.length() > 0);
+ }
+ }
+
+ @Test(timeout = 1000L)
+ public void getAnnotationTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationTest"));
+ Test annotation = method.getAnnotation(Test.class);
+ assertNotNull(annotation);
+ assertEquals(1000L, annotation.timeout());
+ }
+
+ @Test(timeout = 1000L)
+ public void getAnnotationsTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationsTest"));
+ Annotation[] annotations = method.getAnnotations();
+ assertNotNull(annotations);
+ assertEquals(1, annotations.length);
+ assertEquals(1000L, ((Test) annotations[0]).timeout());
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.PARAMETER)
+ @interface NonNull {
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.PARAMETER)
+ @interface Special {
+ }
+
+ private static native void methodWithAnnotatedParameters(@NonNull HashMap<String, String> p1, @Special @NonNull Class<? extends Annotation> p2);
+
+ @Test
+ public void getParameterAnnotationsTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+ Annotation[][] annotations = method.getParameterAnnotations();
+ assertEquals(2, annotations.length);
+ assertEquals(1, annotations[0].length);
+ assertEquals(NonNull.class, annotations[0][0].annotationType());
+ assertEquals(2, annotations[1].length);
+ assertEquals(Special.class, annotations[1][0].annotationType());
+ assertEquals(NonNull.class, annotations[1][1].annotationType());
+ }
+
+ @Test
+ public void getGenericParameterTypesTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+ Type[] genericParameterTypes = method.getGenericParameterTypes();
+ assertEquals(2, genericParameterTypes.length);
+ assertEquals("java.util.HashMap<java.lang.String, java.lang.String>", genericParameterTypes[0].toString());
+ assertEquals("java.lang.Class<? extends java.lang.annotation.Annotation>", genericParameterTypes[1].toString());
+ }
+
+ @Test
+ public void getMaxLocalsTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+ ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+ assertEquals(0, method1.getMaxLocals());
+ assertEquals(2, method2.getMaxLocals());
+
+ }
+
+ @Test
+ public void getMaxStackSizeTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+ ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+ assertEquals(0, method1.getMaxStackSize());
+ // some versions of javac produce bytecode with a stacksize of 2 for this method
+ // JSR 292 also sometimes need one more stack slot
+ int method2StackSize = method2.getMaxStackSize();
+ assertTrue(2 <= method2StackSize && method2StackSize <= 4);
+ }
+
+ @Test
+ public void isDefaultTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertEquals(e.getKey().isDefault(), m.isDefault());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertFalse(m.isDefault());
+ }
+ }
+
+ @Test
+ public void hasReceiverTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertTrue(m.hasReceiver() != Modifier.isStatic(e.getKey().getModifiers()));
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertTrue(m.hasReceiver());
+ }
+ }
+
+ @Test
+ public void hasBytecodesTest() {
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertTrue(m.hasBytecodes() == (m.isConcrete() && !m.isNative()));
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertTrue(m.hasBytecodes());
+ }
+ }
+
+ @Test
+ public void isJavaLangObjectInitTest() throws NoSuchMethodException {
+ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Object.class.getConstructor());
+ assertTrue(method.isJavaLangObjectInit());
+ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ assertFalse(m.isJavaLangObjectInit());
+ }
+ for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+ ResolvedJavaMethod m = e.getValue();
+ Constructor<?> key = e.getKey();
+ if (key.getDeclaringClass() == Object.class && key.getParameters().length == 0) {
+ assertTrue(m.isJavaLangObjectInit());
+ } else {
+ assertFalse(m.isJavaLangObjectInit());
+ }
+ }
+ }
+
+ @Test
+ public void isSignaturePolymorphicTest() {
+ ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeExact", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invoke", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeBasic", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToVirtual", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToStatic", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToSpecial", metaAccess));
+ assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToInterface", metaAccess));
+ assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "type", metaAccess));
+ assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(metaAccess.lookupJavaType(Object.class), "toString", metaAccess));
+ }
+
+ private Method findTestMethod(Method apiMethod) {
+ String testName = apiMethod.getName() + "Test";
+ for (Method m : getClass().getDeclaredMethods()) {
+ if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ // @formatter:off
+ private static final String[] untestedApiMethods = {
+ "invoke",
+ "newInstance",
+ "getDeclaringClass",
+ "getEncoding",
+ "getProfilingInfo",
+ "reprofile",
+ "getCompilerStorage",
+ "canBeInlined",
+ "shouldBeInlined",
+ "getLineNumberTable",
+ "getLocalVariableTable",
+ "isInVirtualMethodTable",
+ "toParameterTypes",
+ "getParameterAnnotation",
+ "getSpeculationLog",
+ "isFinal",
+ "$jacocoInit"
+ };
+ // @formatter:on
+
+ /**
+ * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+ * for them or are added to {@link #untestedApiMethods}.
+ */
+ @Test
+ public void testCoverage() {
+ Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+ for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) {
+ if (Modifier.isStatic(m.getModifiers())) {
+ continue;
+ }
+ if (findTestMethod(m) == null) {
+ assertTrue("test missing for " + m, known.contains(m.getName()));
+ } else {
+ assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,947 @@
+/*
+ * Copyright (c) 2012, 2015, 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 TestResolvedJavaType.java TypeUniverse.java TestMetaAccessProvider.java NameAndSignature.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaType
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static java.lang.reflect.Modifier.*;
+import static org.junit.Assert.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+import jdk.vm.ci.common.*;
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions.*;
+
+import org.junit.*;
+
+import sun.reflect.ConstantPool;
+
+/**
+ * Tests for {@link ResolvedJavaType}.
+ */
+public class TestResolvedJavaType extends TypeUniverse {
+
+ public TestResolvedJavaType() {
+ }
+
+ @Test
+ public void findInstanceFieldWithOffsetTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Set<Field> reflectionFields = getInstanceFields(c, true);
+ for (Field f : reflectionFields) {
+ ResolvedJavaField rf = lookupField(type.getInstanceFields(true), f);
+ assertNotNull(rf);
+ long offset = isStatic(f.getModifiers()) ? unsafe.staticFieldOffset(f) : unsafe.objectFieldOffset(f);
+ ResolvedJavaField result = type.findInstanceFieldWithOffset(offset, rf.getJavaKind());
+ assertNotNull(result);
+ assertTrue(fieldsEqual(f, result));
+ }
+ }
+ }
+
+ @Test
+ public void isInterfaceTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ boolean expected = c.isInterface();
+ boolean actual = type.isInterface();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void isInstanceClassTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ boolean expected = !c.isArray() && !c.isPrimitive() && !c.isInterface();
+ boolean actual = type.isInstanceClass();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void isArrayTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ boolean expected = c.isArray();
+ boolean actual = type.isArray();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void getModifiersTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ int expected = c.getModifiers() & ModifiersProvider.jvmClassModifiers();
+ int actual = type.getModifiers() & ModifiersProvider.jvmClassModifiers();
+ Class<?> elementalType = c;
+ while (elementalType.isArray()) {
+ elementalType = elementalType.getComponentType();
+ }
+ if (elementalType.isMemberClass()) {
+ // member class get their modifiers from the inner-class attribute in the JVM and
+ // from the classfile header in jvmci
+ expected &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+ actual &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+ }
+ assertEquals(String.format("%s: 0x%x != 0x%x", type, expected, actual), expected, actual);
+ }
+ }
+
+ @Test
+ public void isAssignableFromTest() {
+ Class<?>[] all = classes.toArray(new Class<?>[classes.size()]);
+ for (int i = 0; i < all.length; i++) {
+ Class<?> c1 = all[i];
+ for (int j = i; j < all.length; j++) {
+ Class<?> c2 = all[j];
+ ResolvedJavaType t1 = metaAccess.lookupJavaType(c1);
+ ResolvedJavaType t2 = metaAccess.lookupJavaType(c2);
+ boolean expected = c1.isAssignableFrom(c2);
+ boolean actual = t1.isAssignableFrom(t2);
+ assertEquals(expected, actual);
+ if (expected && t1 != t2) {
+ assertFalse(t2.isAssignableFrom(t1));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void isInstanceTest() {
+ for (ConstantValue cv : constants()) {
+ JavaConstant c = cv.value;
+ if (c.getJavaKind() == JavaKind.Object && !c.isNull()) {
+ ResolvedJavaType cType = metaAccess.lookupJavaType(c);
+ for (ResolvedJavaType t : javaTypes) {
+ if (t.isAssignableFrom(cType)) {
+ assertTrue(t.isInstance(c));
+ } else {
+ assertFalse(t.isInstance(c));
+ }
+ }
+ }
+ }
+ }
+
+ private static Class<?> asExactClass(Class<?> c) {
+ if (c.isArray()) {
+ if (asExactClass(c.getComponentType()) != null) {
+ return c;
+ }
+ } else {
+ if (c.isPrimitive() || Modifier.isFinal(c.getModifiers())) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ @Test
+ public void asExactTypeTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ ResolvedJavaType exactType = type.asExactType();
+ Class<?> expected = asExactClass(c);
+ if (expected == null) {
+ assertTrue("exact(" + c.getName() + ") != null", exactType == null);
+ } else {
+ assertNotNull(exactType);
+ assertTrue(exactType.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+ }
+
+ @Test
+ public void getSuperclassTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Class<?> expected = c.getSuperclass();
+ ResolvedJavaType actual = type.getSuperclass();
+ if (expected == null) {
+ assertTrue(actual == null);
+ } else {
+ assertNotNull(actual);
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+ }
+
+ @Test
+ public void getInterfacesTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Class<?>[] expected = c.getInterfaces();
+ ResolvedJavaType[] actual = type.getInterfaces();
+ assertEquals(expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertTrue(actual[i].equals(metaAccess.lookupJavaType(expected[i])));
+ }
+ }
+ }
+
+ public Class<?> getSupertype(Class<?> c) {
+ assert !c.isPrimitive();
+ if (c.isArray()) {
+ Class<?> componentType = c.getComponentType();
+ if (componentType.isPrimitive() || componentType == Object.class) {
+ return Object.class;
+ }
+ return getArrayClass(getSupertype(componentType));
+ }
+ if (c.isInterface()) {
+ return Object.class;
+ }
+ return c.getSuperclass();
+ }
+
+ public Class<?> findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
+ if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) {
+ return null;
+ } else {
+ Class<?> c1 = c1Initial;
+ Class<?> c2 = c2Initial;
+ while (true) {
+ if (c1.isAssignableFrom(c2)) {
+ return c1;
+ }
+ if (c2.isAssignableFrom(c1)) {
+ return c2;
+ }
+ c1 = getSupertype(c1);
+ c2 = getSupertype(c2);
+ }
+ }
+ }
+
+ @Test
+ public void findLeastCommonAncestorTest() {
+ Class<?>[] all = classes.toArray(new Class<?>[classes.size()]);
+ for (int i = 0; i < all.length; i++) {
+ Class<?> c1 = all[i];
+ for (int j = i; j < all.length; j++) {
+ Class<?> c2 = all[j];
+ ResolvedJavaType t1 = metaAccess.lookupJavaType(c1);
+ ResolvedJavaType t2 = metaAccess.lookupJavaType(c2);
+ Class<?> expected = findLeastCommonAncestor(c1, c2);
+ ResolvedJavaType actual = t1.findLeastCommonAncestor(t2);
+ if (expected == null) {
+ assertTrue(actual == null);
+ } else {
+ assertNotNull(actual);
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+ }
+ }
+
+ private static class Base {
+ }
+
+ abstract static class Abstract1 extends Base {
+ }
+
+ interface Interface1 {
+ }
+
+ static class Concrete1 extends Abstract1 {
+ }
+
+ static class Concrete2 extends Abstract1 implements Interface1 {
+ }
+
+ static class Concrete3 extends Concrete2 {
+ }
+
+ static final class Final1 extends Abstract1 {
+ }
+
+ abstract static class Abstract4 extends Concrete3 {
+ }
+
+ void checkConcreteSubtype(ResolvedJavaType type, ResolvedJavaType expected) {
+ AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+ if (leafConcreteSubtype == null) {
+ // findLeafConcreteSubtype() is conservative
+ } else {
+ if (expected == null) {
+ assertNull(leafConcreteSubtype);
+ } else {
+ assertTrue(leafConcreteSubtype.getResult().equals(expected));
+ }
+ }
+
+ if (!type.isArray()) {
+ ResolvedJavaType arrayType = type.getArrayClass();
+ AssumptionResult<ResolvedJavaType> arraySubtype = arrayType.findLeafConcreteSubtype();
+ if (arraySubtype != null) {
+ assertEquals(arraySubtype.getResult(), arrayType);
+ } else {
+ // findLeafConcreteSubtype() method is conservative
+ }
+ }
+ }
+
+ @Test
+ public void findLeafConcreteSubtypeTest() {
+ ResolvedJavaType base = metaAccess.lookupJavaType(Base.class);
+ checkConcreteSubtype(base, base);
+
+ ResolvedJavaType a1 = metaAccess.lookupJavaType(Abstract1.class);
+ ResolvedJavaType c1 = metaAccess.lookupJavaType(Concrete1.class);
+
+ checkConcreteSubtype(base, null);
+ checkConcreteSubtype(a1, c1);
+ checkConcreteSubtype(c1, c1);
+
+ ResolvedJavaType i1 = metaAccess.lookupJavaType(Interface1.class);
+ ResolvedJavaType c2 = metaAccess.lookupJavaType(Concrete2.class);
+
+ checkConcreteSubtype(base, null);
+ checkConcreteSubtype(a1, null);
+ checkConcreteSubtype(c1, c1);
+ checkConcreteSubtype(i1, c2);
+ checkConcreteSubtype(c2, c2);
+
+ ResolvedJavaType c3 = metaAccess.lookupJavaType(Concrete3.class);
+ checkConcreteSubtype(c2, null);
+ checkConcreteSubtype(c3, c3);
+
+ ResolvedJavaType a4 = metaAccess.lookupJavaType(Abstract4.class);
+ checkConcreteSubtype(c3, null);
+ checkConcreteSubtype(a4, null);
+
+ ResolvedJavaType a1a = metaAccess.lookupJavaType(Abstract1[].class);
+ checkConcreteSubtype(a1a, null);
+ ResolvedJavaType c1a = metaAccess.lookupJavaType(Concrete1[].class);
+ checkConcreteSubtype(c1a, null);
+ ResolvedJavaType f1a = metaAccess.lookupJavaType(Final1[].class);
+ checkConcreteSubtype(f1a, f1a);
+
+ ResolvedJavaType obja = metaAccess.lookupJavaType(Object[].class);
+ checkConcreteSubtype(obja, null);
+
+ ResolvedJavaType inta = metaAccess.lookupJavaType(int[].class);
+ checkConcreteSubtype(inta, inta);
+ }
+
+ interface NoImplementor {
+ }
+
+ interface SingleImplementorInterface {
+ }
+
+ static class SingleConcreteImplementor implements SingleImplementorInterface {
+ }
+
+ interface SingleAbstractImplementorInterface {
+ }
+
+ abstract static class SingleAbstractImplementor implements SingleAbstractImplementorInterface {
+ }
+
+ interface MultiImplementorInterface {
+ }
+
+ static class ConcreteImplementor1 implements MultiImplementorInterface {
+ }
+
+ static class ConcreteImplementor2 implements MultiImplementorInterface {
+ }
+
+ interface MultipleAbstractImplementorInterface {
+ }
+
+ abstract static class MultiAbstractImplementor1 implements MultipleAbstractImplementorInterface {
+ }
+
+ abstract static class MultiAbstractImplementor2 implements MultipleAbstractImplementorInterface {
+ }
+
+ interface SingleAbstractImplementorInterface2 {
+ }
+
+ interface ExtendedSingleImplementorInterface {
+ }
+
+ abstract static class SingleAbstractImplementor2 implements SingleAbstractImplementorInterface2 {
+ }
+
+ static class ConcreteTransitiveImplementor1 extends SingleAbstractImplementor2 implements ExtendedSingleImplementorInterface {
+ }
+
+ static class ConcreteTransitiveImplementor2 extends SingleAbstractImplementor2 implements ExtendedSingleImplementorInterface {
+ }
+
+ @Test
+ public void getSingleImplementorTest() {
+ ResolvedJavaType iNi = metaAccess.lookupJavaType(NoImplementor.class);
+ assertNull(iNi.getSingleImplementor());
+
+ ResolvedJavaType iSi = metaAccess.lookupJavaType(SingleImplementorInterface.class);
+ ResolvedJavaType cSi = metaAccess.lookupJavaType(SingleConcreteImplementor.class);
+ assertEquals(cSi, iSi.getSingleImplementor());
+
+ ResolvedJavaType iSai = metaAccess.lookupJavaType(SingleAbstractImplementorInterface.class);
+ ResolvedJavaType aSai = metaAccess.lookupJavaType(SingleAbstractImplementor.class);
+ assertEquals(aSai, iSai.getSingleImplementor());
+
+ ResolvedJavaType iMi = metaAccess.lookupJavaType(MultiImplementorInterface.class);
+ metaAccess.lookupJavaType(ConcreteImplementor1.class);
+ metaAccess.lookupJavaType(ConcreteImplementor2.class);
+ assertEquals(iMi, iMi.getSingleImplementor());
+
+ ResolvedJavaType iMai = metaAccess.lookupJavaType(MultipleAbstractImplementorInterface.class);
+ metaAccess.lookupJavaType(MultiAbstractImplementor1.class);
+ metaAccess.lookupJavaType(MultiAbstractImplementor2.class);
+ assertEquals(iMai, iMai.getSingleImplementor());
+
+ ResolvedJavaType iSai2 = metaAccess.lookupJavaType(SingleAbstractImplementorInterface2.class);
+ ResolvedJavaType aSai2 = metaAccess.lookupJavaType(SingleAbstractImplementor2.class);
+ metaAccess.lookupJavaType(ConcreteTransitiveImplementor1.class);
+ metaAccess.lookupJavaType(ConcreteTransitiveImplementor2.class);
+ assertEquals(aSai2, iSai2.getSingleImplementor());
+ }
+
+ @Test(expected = JVMCIError.class)
+ public void getSingleImplementorTestClassReceiver() {
+ ResolvedJavaType base = metaAccess.lookupJavaType(Base.class);
+ base.getSingleImplementor();
+ }
+
+ @Test(expected = JVMCIError.class)
+ public void getSingleImplementorTestPrimitiveReceiver() {
+ ResolvedJavaType primitive = metaAccess.lookupJavaType(int.class);
+ primitive.getSingleImplementor();
+ }
+
+ @Test
+ public void getComponentTypeTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Class<?> expected = c.getComponentType();
+ ResolvedJavaType actual = type.getComponentType();
+ if (expected == null) {
+ assertNull(actual);
+ } else {
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+ }
+
+ @Test
+ public void getArrayClassTest() {
+ for (Class<?> c : classes) {
+ if (c != void.class) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Class<?> expected = getArrayClass(c);
+ ResolvedJavaType actual = type.getArrayClass();
+ assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+ }
+ }
+ }
+
+ static class Declarations {
+
+ final Method implementation;
+ final Set<Method> declarations;
+
+ public Declarations(Method impl) {
+ this.implementation = impl;
+ declarations = new HashSet<>();
+ }
+ }
+
+ /**
+ * See <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4.5">Method
+ * overriding</a>.
+ */
+ static boolean isOverriderOf(Method impl, Method m) {
+ if (!isPrivate(m.getModifiers()) && !isFinal(m.getModifiers())) {
+ if (m.getName().equals(impl.getName())) {
+ if (m.getReturnType() == impl.getReturnType()) {
+ if (Arrays.equals(m.getParameterTypes(), impl.getParameterTypes())) {
+ if (isPublic(m.getModifiers()) || isProtected(m.getModifiers())) {
+ // m is public or protected
+ return isPublic(impl.getModifiers()) || isProtected(impl.getModifiers());
+ } else {
+ // m is package-private
+ return impl.getDeclaringClass().getPackage() == m.getDeclaringClass().getPackage();
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ static final Map<Class<?>, VTable> vtables = new HashMap<>();
+
+ static class VTable {
+
+ final Map<NameAndSignature, Method> methods = new HashMap<>();
+ }
+
+ static synchronized VTable getVTable(Class<?> c) {
+ VTable vtable = vtables.get(c);
+ if (vtable == null) {
+ vtable = new VTable();
+ if (c != Object.class) {
+ VTable superVtable = getVTable(c.getSuperclass());
+ vtable.methods.putAll(superVtable.methods);
+ }
+ for (Method m : c.getDeclaredMethods()) {
+ if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) {
+ if (isAbstract(m.getModifiers())) {
+ // A subclass makes a concrete method in a superclass abstract
+ vtable.methods.remove(new NameAndSignature(m));
+ } else {
+ vtable.methods.put(new NameAndSignature(m), m);
+ }
+ }
+ }
+ vtables.put(c, vtable);
+ }
+ return vtable;
+ }
+
+ static Set<Method> findDeclarations(Method impl, Class<?> c) {
+ Set<Method> declarations = new HashSet<>();
+ NameAndSignature implSig = new NameAndSignature(impl);
+ if (c != null) {
+ for (Method m : c.getDeclaredMethods()) {
+ if (new NameAndSignature(m).equals(implSig)) {
+ declarations.add(m);
+ break;
+ }
+ }
+ if (!c.isInterface()) {
+ declarations.addAll(findDeclarations(impl, c.getSuperclass()));
+ }
+ for (Class<?> i : c.getInterfaces()) {
+ declarations.addAll(findDeclarations(impl, i));
+ }
+ }
+ return declarations;
+ }
+
+ private static void checkResolveMethod(ResolvedJavaType type, ResolvedJavaType context, ResolvedJavaMethod decl, ResolvedJavaMethod expected) {
+ ResolvedJavaMethod impl = type.resolveConcreteMethod(decl, context);
+ assertEquals(expected, impl);
+ }
+
+ @Test
+ public void resolveMethodTest() {
+ ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class);
+ for (Class<?> c : classes) {
+ if (c.isInterface() || c.isPrimitive()) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ for (Method m : c.getDeclaredMethods()) {
+ if (JAVA_VERSION <= 1.7D || (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers()))) {
+ ResolvedJavaMethod resolved = metaAccess.lookupJavaMethod(m);
+ ResolvedJavaMethod impl = type.resolveMethod(resolved, context);
+ ResolvedJavaMethod expected = resolved.isDefault() || resolved.isAbstract() ? resolved : null;
+ assertEquals(m.toString(), expected, impl);
+ } else {
+ // As of JDK 8, interfaces can have static and private methods
+ }
+ }
+ } else {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ VTable vtable = getVTable(c);
+ for (Method impl : vtable.methods.values()) {
+ Set<Method> decls = findDeclarations(impl, c);
+ for (Method decl : decls) {
+ ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
+ if (m.isPublic()) {
+ ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
+ checkResolveMethod(type, context, m, i);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void resolveConcreteMethodTest() {
+ ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class);
+ for (Class<?> c : classes) {
+ if (c.isInterface() || c.isPrimitive()) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ for (Method m : c.getDeclaredMethods()) {
+ if (JAVA_VERSION <= 1.7D || (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers()))) {
+ ResolvedJavaMethod resolved = metaAccess.lookupJavaMethod(m);
+ ResolvedJavaMethod impl = type.resolveConcreteMethod(resolved, context);
+ ResolvedJavaMethod expected = resolved.isDefault() ? resolved : null;
+ assertEquals(m.toString(), expected, impl);
+ } else {
+ // As of JDK 8, interfaces can have static and private methods
+ }
+ }
+ } else {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ VTable vtable = getVTable(c);
+ for (Method impl : vtable.methods.values()) {
+ Set<Method> decls = findDeclarations(impl, c);
+ for (Method decl : decls) {
+ ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
+ if (m.isPublic()) {
+ ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
+ checkResolveMethod(type, context, m, i);
+ }
+ }
+ }
+ for (Method m : c.getDeclaredMethods()) {
+ ResolvedJavaMethod impl = type.resolveConcreteMethod(metaAccess.lookupJavaMethod(m), context);
+ ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl;
+ assertEquals(type + " " + m.toString(), expected, impl);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void findUniqueConcreteMethodTest() throws NoSuchMethodException {
+ ResolvedJavaMethod thisMethod = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("findUniqueConcreteMethodTest"));
+ ResolvedJavaMethod ucm = metaAccess.lookupJavaType(getClass()).findUniqueConcreteMethod(thisMethod).getResult();
+ assertEquals(thisMethod, ucm);
+ }
+
+ public static Set<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
+ if (c.isArray() || c.isPrimitive() || c.isInterface()) {
+ return Collections.emptySet();
+ }
+ Set<Field> result = new HashSet<>();
+ for (Field f : c.getDeclaredFields()) {
+ if (!Modifier.isStatic(f.getModifiers())) {
+ result.add(f);
+ }
+ }
+ if (includeSuperclasses && c != Object.class) {
+ result.addAll(getInstanceFields(c.getSuperclass(), true));
+ }
+ return result;
+ }
+
+ public static Set<Field> getStaticFields(Class<?> c) {
+ Set<Field> result = new HashSet<>();
+ for (Field f : c.getDeclaredFields()) {
+ if (Modifier.isStatic(f.getModifiers())) {
+ result.add(f);
+ }
+ }
+ return result;
+ }
+
+ public boolean fieldsEqual(Field f, ResolvedJavaField rjf) {
+ return rjf.getDeclaringClass().equals(metaAccess.lookupJavaType(f.getDeclaringClass())) && rjf.getName().equals(f.getName()) &&
+ rjf.getType().resolve(rjf.getDeclaringClass()).equals(metaAccess.lookupJavaType(f.getType()));
+ }
+
+ public ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) {
+ for (ResolvedJavaField rf : fields) {
+ if (fieldsEqual(key, rf)) {
+ return rf;
+ }
+ }
+ return null;
+ }
+
+ public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
+ for (Field f : fields) {
+ if (fieldsEqual(f, key)) {
+ return f;
+ }
+ }
+ return null;
+ }
+
+ private static boolean isHiddenFromReflection(ResolvedJavaField f) {
+ if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) {
+ return true;
+ }
+ if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(ConstantPool.class)) && f.getName().equals("constantPoolOop")) {
+ return true;
+ }
+ if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Class.class)) && f.getName().equals("classLoader")) {
+ return true;
+ }
+ return false;
+ }
+
+ @Test
+ public void getInstanceFieldsTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ for (boolean includeSuperclasses : new boolean[]{true, false}) {
+ Set<Field> expected = getInstanceFields(c, includeSuperclasses);
+ ResolvedJavaField[] actual = type.getInstanceFields(includeSuperclasses);
+ for (Field f : expected) {
+ assertNotNull(lookupField(actual, f));
+ }
+ for (ResolvedJavaField rf : actual) {
+ if (!isHiddenFromReflection(rf)) {
+ assertEquals(rf.toString(), lookupField(expected, rf) != null, !rf.isInternal());
+ }
+ }
+
+ // Test stability of getInstanceFields
+ ResolvedJavaField[] actual2 = type.getInstanceFields(includeSuperclasses);
+ assertArrayEquals(actual, actual2);
+ }
+ }
+ }
+
+ @Test
+ public void getStaticFieldsTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Set<Field> expected = getStaticFields(c);
+ ResolvedJavaField[] actual = type.getStaticFields();
+ for (Field f : expected) {
+ assertNotNull(lookupField(actual, f));
+ }
+ for (ResolvedJavaField rf : actual) {
+ if (!isHiddenFromReflection(rf)) {
+ assertEquals(lookupField(expected, rf) != null, !rf.isInternal());
+ }
+ }
+
+ // Test stability of getStaticFields
+ ResolvedJavaField[] actual2 = type.getStaticFields();
+ assertArrayEquals(actual, actual2);
+ }
+ }
+
+ @Test
+ public void getDeclaredMethodsTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ Method[] raw = c.getDeclaredMethods();
+ Set<ResolvedJavaMethod> expected = new HashSet<>();
+ for (Method m : raw) {
+ ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(m);
+ assertNotNull(resolvedMethod);
+ expected.add(resolvedMethod);
+ }
+ Set<ResolvedJavaMethod> actual = new HashSet<>(Arrays.asList(type.getDeclaredMethods()));
+ assertEquals(expected, actual);
+ }
+ }
+
+ static class A {
+ static String name = "foo";
+ }
+
+ static class B extends A {
+ }
+
+ static class C {
+ }
+
+ static class D {
+ void foo() {
+ // use of assertions causes the class to have a <clinit>
+ assert getClass() != null;
+ }
+ }
+
+ static class SubD extends D {
+
+ }
+
+ @Test
+ public void getClassInitializerTest() {
+ assertNotNull(metaAccess.lookupJavaType(A.class).getClassInitializer());
+ assertNotNull(metaAccess.lookupJavaType(D.class).getClassInitializer());
+ assertNull(metaAccess.lookupJavaType(B.class).getClassInitializer());
+ assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
+ assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
+ assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
+ }
+
+ @Test
+ public void getAnnotationsTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ assertArrayEquals(c.getAnnotations(), type.getAnnotations());
+ }
+ }
+
+ @Test
+ public void getAnnotationTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ for (Annotation a : c.getAnnotations()) {
+ assertEquals(a, type.getAnnotation(a.annotationType()));
+ }
+ }
+ }
+
+ @Test
+ public void memberClassesTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ assertEquals(c.isLocalClass(), type.isLocal());
+ assertEquals(c.isMemberClass(), type.isMember());
+ Class<?> enclc = c.getEnclosingClass();
+ ResolvedJavaType enclt = type.getEnclosingType();
+ assertFalse(enclc == null ^ enclt == null);
+ if (enclc != null) {
+ assertEquals(enclt, metaAccess.lookupJavaType(enclc));
+ }
+ }
+ }
+
+ @Test
+ public void classFilePathTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ URL path = type.getClassFilePath();
+ if (type.isPrimitive() || type.isArray()) {
+ assertEquals(null, path);
+ } else {
+ assertNotNull(path);
+ String pathString = path.getPath();
+ if (type.isLocal() || type.isMember()) {
+ assertTrue(pathString.indexOf('$') > 0);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void isTrustedInterfaceTypeTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ if (TrustedInterface.class.isAssignableFrom(c)) {
+ assertTrue(type.isTrustedInterfaceType());
+ }
+ }
+ }
+
+ @Test
+ public void isLeafTest() {
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ ResolvedJavaType arrayType = c != void.class ? metaAccess.lookupJavaType(getArrayClass(c)) : null;
+ if (c.isPrimitive()) {
+ assertTrue(type.isLeaf());
+ assertTrue(arrayType == null || arrayType.isLeaf());
+ } else {
+ assertTrue(c.toString(), type.isLeaf() == arrayType.isLeaf());
+ if (!c.isArray()) {
+ assertTrue(c.toString(), type.isLeaf() == Modifier.isFinal(c.getModifiers()));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void findMethodTest() {
+ try {
+ ResolvedJavaMethod findFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+ ResolvedJavaMethod expectedFoo = metaAccess.lookupJavaMethod(D.class.getDeclaredMethod("foo"));
+ assertEquals(expectedFoo, findFoo);
+
+ ResolvedJavaMethod wrongReturnTypeFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()I"));
+ assertNull(wrongReturnTypeFoo);
+
+ ResolvedJavaMethod wrongArgumentsFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("(I)V"));
+ assertNull(wrongArgumentsFoo);
+
+ ResolvedJavaMethod wrongNameFoo = metaAccess.lookupJavaType(D.class).findMethod("bar", metaAccess.parseMethodDescriptor("()V"));
+ assertNull(wrongNameFoo);
+
+ ResolvedJavaMethod wrongClassFoo = metaAccess.lookupJavaType(SubD.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+ assertNull(wrongClassFoo);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Method findTestMethod(Method apiMethod) {
+ String testName = apiMethod.getName() + "Test";
+ for (Method m : getClass().getDeclaredMethods()) {
+ if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ // @formatter:off
+ private static final String[] untestedApiMethods = {
+ "initialize",
+ "isPrimitive",
+ "newArray",
+ "getDeclaredConstructors",
+ "isInitialized",
+ "isLinked",
+ "getJavaClass",
+ "getObjectHub",
+ "hasFinalizableSubclass",
+ "hasFinalizer",
+ "getSourceFileName",
+ "getClassFilePath",
+ "isLocal",
+ "isJavaLangObject",
+ "isMember",
+ "getElementalType",
+ "getEnclosingType",
+ "$jacocoInit",
+ "isCpiSet",
+ "getCorrespondingCpi",
+ "setCorrespondingCpi"
+ };
+ // @formatter:on
+
+ /**
+ * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+ * for them or are added to {@link #untestedApiMethods}.
+ */
+ @Test
+ public void testCoverage() {
+ Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+ for (Method m : ResolvedJavaType.class.getDeclaredMethods()) {
+ if (findTestMethod(m) == null) {
+ assertTrue("test missing for " + m, known.contains(m.getName()));
+ } else {
+ assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package jdk.vm.ci.runtime.test;
+
+import static java.lang.reflect.Modifier.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Queue;
+import java.util.stream.*;
+
+import jdk.vm.ci.meta.*;
+import jdk.vm.ci.runtime.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+//JaCoCo Exclude
+
+/**
+ * Context for type related tests.
+ */
+public class TypeUniverse {
+
+ public static final Unsafe unsafe;
+ public static final double JAVA_VERSION = Double.valueOf(System.getProperty("java.specification.version"));
+
+ public static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ public static final ConstantReflectionProvider constantReflection = JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection();
+ public static final Collection<Class<?>> classes = new HashSet<>();
+ public static final Set<ResolvedJavaType> javaTypes;
+ public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
+
+ private static List<ConstantValue> constants;
+
+ public class InnerClass {
+
+ }
+
+ public static class InnerStaticClass {
+
+ }
+
+ public static final class InnerStaticFinalClass {
+
+ }
+
+ private class PrivateInnerClass {
+
+ }
+
+ protected class ProtectedInnerClass {
+
+ }
+
+ static {
+ Unsafe theUnsafe = null;
+ try {
+ theUnsafe = Unsafe.getUnsafe();
+ } catch (Exception e) {
+ try {
+ Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ theUnsafeField.setAccessible(true);
+ theUnsafe = (Unsafe) theUnsafeField.get(null);
+ } catch (Exception e1) {
+ throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1);
+ }
+ }
+ unsafe = theUnsafe;
+
+ Class<?>[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, boolean[].class,
+ byte[].class, short[].class, char[].class, int[].class, float[].class, long[].class, double[].class, Object[].class, Class[].class, List[].class, boolean[][].class,
+ byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].class,
+ ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class,
+ HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class, TrustedInterface.class, InnerClass.class,
+ InnerStaticClass.class, InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class};
+ for (Class<?> c : initialClasses) {
+ addClass(c);
+ }
+
+ javaTypes = Collections.unmodifiableSet(classes.stream().map(c -> metaAccess.lookupJavaType(c)).collect(Collectors.toSet()));
+ }
+
+ static class ConstantsUniverse {
+ static final Object[] ARRAYS = classes.stream().map(c -> c != void.class && !c.isArray() ? Array.newInstance(c, 42) : null).filter(o -> o != null).collect(Collectors.toList()).toArray();
+ static final Object CONST1 = new ArrayList<>();
+ static final Object CONST2 = new ArrayList<>();
+ static final Object CONST3 = new IdentityHashMap<>();
+ static final Object CONST4 = new LinkedHashMap<>();
+ static final Object CONST5 = new TreeMap<>();
+ static final Object CONST6 = new ArrayDeque<>();
+ static final Object CONST7 = new LinkedList<>();
+ static final Object CONST8 = "a string";
+ static final Object CONST9 = 42;
+ static final Object CONST10 = String.class;
+ static final Object CONST11 = String[].class;
+ }
+
+ public static List<ConstantValue> constants() {
+ if (constants == null) {
+ List<ConstantValue> res = readConstants(JavaConstant.class);
+ res.addAll(readConstants(ConstantsUniverse.class));
+ constants = res;
+ }
+ return constants;
+ }
+
+ public static class ConstantValue {
+ public final String name;
+ public final JavaConstant value;
+ public final Object boxed;
+
+ public ConstantValue(String name, JavaConstant value, Object boxed) {
+ this.name = name;
+ this.value = value;
+ this.boxed = boxed;
+ }
+
+ @Override
+ public String toString() {
+ return name + "=" + value;
+ }
+
+ public String getSimpleName() {
+ return name.substring(name.lastIndexOf('.') + 1);
+ }
+ }
+
+ /**
+ * Reads the value of all {@code static final} fields from a given class into an array of
+ * {@link ConstantValue}s.
+ */
+ public static List<ConstantValue> readConstants(Class<?> fromClass) {
+ try {
+ List<ConstantValue> res = new ArrayList<>();
+ for (Field field : fromClass.getDeclaredFields()) {
+ if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) {
+ JavaField javaField = metaAccess.lookupJavaField(field);
+ Object boxed = field.get(null);
+ if (boxed instanceof JavaConstant) {
+ res.add(new ConstantValue(javaField.format("%H.%n"), (JavaConstant) boxed, boxed));
+ } else {
+ JavaConstant value = constantReflection.readConstantFieldValue(javaField, null);
+ if (value != null) {
+ res.add(new ConstantValue(javaField.format("%H.%n"), value, boxed));
+ if (boxed instanceof Object[]) {
+ Object[] arr = (Object[]) boxed;
+ for (int i = 0; i < arr.length; i++) {
+ JavaConstant element = constantReflection.readArrayElement(value, i);
+ if (element != null) {
+ res.add(new ConstantValue(javaField.format("%H.%n[" + i + "]"), element, arr[i]));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return res;
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public synchronized Class<?> getArrayClass(Class<?> componentType) {
+ Class<?> arrayClass = arrayClasses.get(componentType);
+ if (arrayClass == null) {
+ arrayClass = Array.newInstance(componentType, 0).getClass();
+ arrayClasses.put(componentType, arrayClass);
+ }
+ return arrayClass;
+ }
+
+ public static int dimensions(Class<?> c) {
+ if (c.getComponentType() != null) {
+ return 1 + dimensions(c.getComponentType());
+ }
+ return 0;
+ }
+
+ private static void addClass(Class<?> c) {
+ if (classes.add(c)) {
+ if (c.getSuperclass() != null) {
+ addClass(c.getSuperclass());
+ }
+ for (Class<?> sc : c.getInterfaces()) {
+ addClass(sc);
+ }
+ for (Class<?> dc : c.getDeclaredClasses()) {
+ addClass(dc);
+ }
+ for (Method m : c.getDeclaredMethods()) {
+ addClass(m.getReturnType());
+ for (Class<?> p : m.getParameterTypes()) {
+ addClass(p);
+ }
+ }
+
+ if (c != void.class && dimensions(c) < 2) {
+ Class<?> arrayClass = Array.newInstance(c, 0).getClass();
+ arrayClasses.put(c, arrayClass);
+ addClass(arrayClass);
+ }
+ }
+ }
+}
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Oct 08 10:25:45 2015 +0000
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Oct 08 12:49:30 2015 -1000
@@ -459,6 +459,21 @@
}
/**
+ * Ensures a requested class is loaded
+ * @param aClass class to load
+ */
+ public static void ensureClassIsLoaded(Class<?> aClass) {
+ if (aClass == null) {
+ throw new Error("Requested null class");
+ }
+ try {
+ Class.forName(aClass.getName(), /* initialize = */ true,
+ ClassLoader.getSystemClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new Error("Class not found", e);
+ }
+ }
+ /**
* Runs runnable and checks that it throws expected exception. If exceptionException is null it means
* that we expect no exception to be thrown.
* @param runnable what we run