8171853: Remove Shark compiler
Reviewed-by: dholmes, kvn, erikj, ihse
This commit is contained in:
parent
50c759f20e
commit
7030019135
doc
make
autoconf
copy
hotspot
lib
src/hotspot
cpu
arm
sparc
x86
zero
share
ci
code
compiler
abstractCompiler.hppcompileBroker.cppcompilerDefinitions.cppcompilerDefinitions.hppcompilerDirectives.cppdisassembler.cpp
interpreter
oops
runtime
commandLineFlagConstraintsCompiler.cppdeoptimization.cppframe.cppframe.inline.hppglobals.cppglobals.hppthread.cppvm_version.cpp
shark
llvmHeaders.hppllvmValue.hppsharkBlock.cppsharkBlock.hppsharkBuilder.cppsharkBuilder.hppsharkCacheDecache.cppsharkCacheDecache.hppsharkCodeBuffer.hppsharkCompiler.cppsharkCompiler.hppsharkConstant.cppsharkConstant.hppsharkContext.cppsharkContext.hppsharkEntry.hppsharkFunction.cppsharkFunction.hppsharkInliner.cppsharkInliner.hppsharkIntrinsics.cppsharkIntrinsics.hppsharkInvariants.cppsharkInvariants.hppsharkMemoryManager.cppsharkMemoryManager.hppsharkNativeWrapper.cppsharkNativeWrapper.hppsharkRuntime.cppsharkRuntime.hppsharkStack.cppsharkStack.hppsharkState.cppsharkState.hppsharkStateScanner.cppsharkStateScanner.hppsharkTopLevelBlock.cppsharkTopLevelBlock.hppsharkType.hppsharkValue.cppsharkValue.hppshark_globals.cppshark_globals.hpp
utilities
test/hotspot/jtreg/compiler/whitebox
@ -463,7 +463,7 @@ tar -xzf freetype-2.5.3.tar.gz</code></pre>
|
||||
<li><code>--with-native-debug-symbols=<method></code> - Specify if and how native debug symbols should be built. Available methods are <code>none</code>, <code>internal</code>, <code>external</code>, <code>zipped</code>. Default behavior depends on platform. See <a href="#native-debug-symbols">Native Debug Symbols</a> for more details.</li>
|
||||
<li><code>--with-version-string=<string></code> - Specify the version string this build will be identified with.</li>
|
||||
<li><code>--with-version-<part>=<value></code> - A group of options, where <code><part></code> can be any of <code>pre</code>, <code>opt</code>, <code>build</code>, <code>major</code>, <code>minor</code>, <code>security</code> or <code>patch</code>. Use these options to modify just the corresponding part of the version string from the default, or the value provided by <code>--with-version-string</code>.</li>
|
||||
<li><code>--with-jvm-variants=<variant>[,<variant>...]</code> - Build the specified variant (or variants) of Hotspot. Valid variants are: <code>server</code>, <code>client</code>, <code>minimal</code>, <code>core</code>, <code>zero</code>, <code>zeroshark</code>, <code>custom</code>. Note that not all variants are possible to combine in a single build.</li>
|
||||
<li><code>--with-jvm-variants=<variant>[,<variant>...]</code> - Build the specified variant (or variants) of Hotspot. Valid variants are: <code>server</code>, <code>client</code>, <code>minimal</code>, <code>core</code>, <code>zero</code>, <code>custom</code>. Note that not all variants are possible to combine in a single build.</li>
|
||||
<li><code>--with-jvm-features=<feature>[,<feature>...]</code> - Use the specified JVM features when building Hotspot. The list of features will be enabled on top of the default list. For the <code>custom</code> JVM variant, this default list is empty. A complete list of available JVM features can be found using <code>bash configure --help</code>.</li>
|
||||
<li><code>--with-target-bits=<bits></code> - Create a target binary suitable for running on a <code><bits></code> platform. Use this to create 32-bit output on a 64-bit build platform, instead of doing a full cross-compile. (This is known as a <em>reduced</em> build.)</li>
|
||||
</ul>
|
||||
|
@ -668,7 +668,7 @@ features, use `bash configure --help=short` instead.)
|
||||
from the default, or the value provided by `--with-version-string`.
|
||||
* `--with-jvm-variants=<variant>[,<variant>...]` - Build the specified variant
|
||||
(or variants) of Hotspot. Valid variants are: `server`, `client`,
|
||||
`minimal`, `core`, `zero`, `zeroshark`, `custom`. Note that not all
|
||||
`minimal`, `core`, `zero`, `custom`. Note that not all
|
||||
variants are possible to combine in a single build.
|
||||
* `--with-jvm-features=<feature>[,<feature>...]` - Use the specified JVM
|
||||
features when building Hotspot. The list of features will be enabled on top
|
||||
|
@ -1097,7 +1097,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER],
|
||||
]
|
||||
)
|
||||
fi
|
||||
if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if ! HOTSPOT_CHECK_JVM_VARIANT(zero); then
|
||||
# Non-zero builds have stricter warnings
|
||||
$2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2"
|
||||
else
|
||||
|
@ -24,12 +24,12 @@
|
||||
#
|
||||
|
||||
# All valid JVM features, regardless of platform
|
||||
VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \
|
||||
VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \
|
||||
graal vm-structs jni-check services management all-gcs nmt cds \
|
||||
static-build link-time-opt aot"
|
||||
|
||||
# All valid JVM variants
|
||||
VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
|
||||
VALID_JVM_VARIANTS="server client minimal core zero custom"
|
||||
|
||||
###############################################################################
|
||||
# Check if the specified JVM variant should be built. To be used in shell if
|
||||
@ -62,13 +62,12 @@ AC_DEFUN([HOTSPOT_CHECK_JVM_FEATURE],
|
||||
# minimal: reduced form of client with optional features stripped out
|
||||
# core: normal interpreter only, no compiler
|
||||
# zero: C++ based interpreter only, no compiler
|
||||
# zeroshark: C++ based interpreter, and a llvm-based compiler
|
||||
# custom: baseline JVM with no default features
|
||||
#
|
||||
AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS],
|
||||
[
|
||||
AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants],
|
||||
[JVM variants (separated by commas) to build (server,client,minimal,core,zero,zeroshark,custom) @<:@server@:>@])])
|
||||
[JVM variants (separated by commas) to build (server,client,minimal,core,zero,custom) @<:@server@:>@])])
|
||||
|
||||
SETUP_HOTSPOT_TARGET_CPU_PORT
|
||||
|
||||
@ -132,7 +131,7 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS],
|
||||
AC_SUBST(VALID_JVM_VARIANTS)
|
||||
AC_SUBST(JVM_VARIANT_MAIN)
|
||||
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero); then
|
||||
# zero behaves as a platform and rewrites these values. This is really weird. :(
|
||||
# We are guaranteed that we do not build any other variants when building zero.
|
||||
HOTSPOT_TARGET_CPU=zero
|
||||
@ -325,15 +324,9 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if ! HOTSPOT_CHECK_JVM_VARIANT(zero); then
|
||||
if HOTSPOT_CHECK_JVM_FEATURE(zero); then
|
||||
AC_MSG_ERROR([To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark])
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if HOTSPOT_CHECK_JVM_FEATURE(shark); then
|
||||
AC_MSG_ERROR([To enable shark, you must use --with-jvm-variants=zeroshark])
|
||||
AC_MSG_ERROR([To enable zero, you must use --with-jvm-variants=zero])
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -408,7 +401,6 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
|
||||
JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES"
|
||||
JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES $JVM_FEATURES_link_time_opt"
|
||||
JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES"
|
||||
JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES"
|
||||
JVM_FEATURES_custom="$JVM_FEATURES"
|
||||
|
||||
AC_SUBST(JVM_FEATURES_server)
|
||||
@ -416,7 +408,6 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
|
||||
AC_SUBST(JVM_FEATURES_core)
|
||||
AC_SUBST(JVM_FEATURES_minimal)
|
||||
AC_SUBST(JVM_FEATURES_zero)
|
||||
AC_SUBST(JVM_FEATURES_zeroshark)
|
||||
AC_SUBST(JVM_FEATURES_custom)
|
||||
|
||||
# Used for verification of Makefiles by check-jvm-feature
|
||||
@ -437,7 +428,6 @@ AC_DEFUN_ONCE([HOTSPOT_VALIDATE_JVM_FEATURES],
|
||||
JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))"
|
||||
JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))"
|
||||
JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))"
|
||||
JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))"
|
||||
JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))"
|
||||
|
||||
# Validate features
|
||||
|
@ -232,7 +232,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
|
||||
|
||||
# Should we build the serviceability agent (SA)?
|
||||
INCLUDE_SA=true
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero); then
|
||||
INCLUDE_SA=false
|
||||
fi
|
||||
if test "x$OPENJDK_TARGET_OS" = xaix ; then
|
||||
|
@ -65,8 +65,7 @@ AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS],
|
||||
# If dynamic was requested, it's available since it would fail above otherwise.
|
||||
# If dynamic wasn't requested, go with static unless it isn't available.
|
||||
AC_MSG_CHECKING([how to link with libstdc++])
|
||||
if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno \
|
||||
|| HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno ; then
|
||||
AC_MSG_RESULT([dynamic])
|
||||
else
|
||||
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
|
||||
|
@ -68,7 +68,7 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
|
||||
fi
|
||||
|
||||
# Check if ffi is needed
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zero); then
|
||||
NEEDS_LIB_FFI=true
|
||||
else
|
||||
NEEDS_LIB_FFI=false
|
||||
@ -86,69 +86,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
LIB_SETUP_FREETYPE
|
||||
LIB_SETUP_ALSA
|
||||
LIB_SETUP_LIBFFI
|
||||
LIB_SETUP_LLVM
|
||||
LIB_SETUP_BUNDLED_LIBS
|
||||
LIB_SETUP_MISC_LIBS
|
||||
LIB_SETUP_SOLARIS_STLPORT
|
||||
])
|
||||
|
||||
################################################################################
|
||||
# Setup llvm (Low-Level VM)
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_SETUP_LLVM],
|
||||
[
|
||||
if HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then
|
||||
AC_CHECK_PROG([LLVM_CONFIG], [llvm-config], [llvm-config])
|
||||
|
||||
if test "x$LLVM_CONFIG" != xllvm-config; then
|
||||
AC_MSG_ERROR([llvm-config not found in $PATH.])
|
||||
fi
|
||||
|
||||
llvm_components="jit mcjit engine nativecodegen native"
|
||||
unset LLVM_CFLAGS
|
||||
for flag in $("$LLVM_CONFIG" --cxxflags); do
|
||||
if echo "${flag}" | grep -q '^-@<:@ID@:>@'; then
|
||||
if test "${flag}" != "-D_DEBUG" ; then
|
||||
if test "${LLVM_CFLAGS}" != "" ; then
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS} "
|
||||
fi
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS}${flag}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
llvm_version=$("${LLVM_CONFIG}" --version | $SED 's/\.//; s/svn.*//')
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS} -DSHARK_LLVM_VERSION=${llvm_version}"
|
||||
|
||||
unset LLVM_LDFLAGS
|
||||
for flag in $("${LLVM_CONFIG}" --ldflags); do
|
||||
if echo "${flag}" | grep -q '^-L'; then
|
||||
if test "${LLVM_LDFLAGS}" != ""; then
|
||||
LLVM_LDFLAGS="${LLVM_LDFLAGS} "
|
||||
fi
|
||||
LLVM_LDFLAGS="${LLVM_LDFLAGS}${flag}"
|
||||
fi
|
||||
done
|
||||
|
||||
unset LLVM_LIBS
|
||||
for flag in $("${LLVM_CONFIG}" --libs ${llvm_components}); do
|
||||
if echo "${flag}" | grep -q '^-l'; then
|
||||
if test "${LLVM_LIBS}" != ""; then
|
||||
LLVM_LIBS="${LLVM_LIBS} "
|
||||
fi
|
||||
LLVM_LIBS="${LLVM_LIBS}${flag}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Due to https://llvm.org/bugs/show_bug.cgi?id=16902, llvm does not
|
||||
# always properly detect -ltinfo
|
||||
LLVM_LIBS="${LLVM_LIBS} -ltinfo"
|
||||
|
||||
AC_SUBST(LLVM_CFLAGS)
|
||||
AC_SUBST(LLVM_LDFLAGS)
|
||||
AC_SUBST(LLVM_LIBS)
|
||||
fi
|
||||
])
|
||||
|
||||
################################################################################
|
||||
# Setup various libraries, typically small system libraries
|
||||
################################################################################
|
||||
|
@ -222,7 +222,6 @@ JVM_FEATURES_client := @JVM_FEATURES_client@
|
||||
JVM_FEATURES_core := @JVM_FEATURES_core@
|
||||
JVM_FEATURES_minimal := @JVM_FEATURES_minimal@
|
||||
JVM_FEATURES_zero := @JVM_FEATURES_zero@
|
||||
JVM_FEATURES_zeroshark := @JVM_FEATURES_zeroshark@
|
||||
JVM_FEATURES_custom := @JVM_FEATURES_custom@
|
||||
|
||||
# Used for make-time verifications
|
||||
@ -396,11 +395,6 @@ JVM_ASFLAGS := @JVM_ASFLAGS@
|
||||
JVM_LIBS := @JVM_LIBS@
|
||||
JVM_RCFLAGS := @JVM_RCFLAGS@
|
||||
|
||||
# Flags for zeroshark
|
||||
LLVM_CFLAGS := @LLVM_CFLAGS@
|
||||
LLVM_LIBS := @LLVM_LIBS@
|
||||
LLVM_LDFLAGS := @LLVM_LDFLAGS@
|
||||
|
||||
# These flags might contain variables set by a custom extension that is included later.
|
||||
EXTRA_CFLAGS = @EXTRA_CFLAGS@
|
||||
EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@
|
||||
|
@ -87,7 +87,7 @@ endif
|
||||
#
|
||||
# How to install jvm.cfg.
|
||||
#
|
||||
ifeq ($(call check-jvm-variant, zero zeroshark), true)
|
||||
ifeq ($(call check-jvm-variant, zero), true)
|
||||
JVMCFG_ARCH := zero
|
||||
else
|
||||
JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY)
|
||||
@ -102,8 +102,6 @@ else
|
||||
endif
|
||||
JVMCFG := $(LIB_DST_DIR)/jvm.cfg
|
||||
|
||||
# To do: should this also support -zeroshark?
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_CPU_BITS), 64)
|
||||
COPY_JVM_CFG_FILE := true
|
||||
else
|
||||
@ -120,7 +118,7 @@ else
|
||||
COPY_JVM_CFG_FILE := true
|
||||
else
|
||||
# For zero, the default jvm.cfg file is sufficient
|
||||
ifeq ($(call check-jvm-variant, zero zeroshark), true)
|
||||
ifeq ($(call check-jvm-variant, zero), true)
|
||||
COPY_JVM_CFG_FILE := true
|
||||
endif
|
||||
endif
|
||||
|
@ -75,7 +75,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
-ignorePath linux \
|
||||
-ignorePath posix \
|
||||
-ignorePath ppc \
|
||||
-ignorePath shark \
|
||||
-ignorePath solaris \
|
||||
-ignorePath sparc \
|
||||
-ignorePath x86_32 \
|
||||
|
@ -52,14 +52,6 @@ ifeq ($(call check-jvm-feature, zero), true)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(call check-jvm-feature, shark), true)
|
||||
JVM_CFLAGS_FEATURES += -DSHARK $(LLVM_CFLAGS)
|
||||
JVM_LDFLAGS_FEATURES += $(LLVM_LDFLAGS)
|
||||
JVM_LIBS_FEATURES += $(LLVM_LIBS)
|
||||
else
|
||||
JVM_EXCLUDES += shark
|
||||
endif
|
||||
|
||||
ifeq ($(call check-jvm-feature, minimal), true)
|
||||
JVM_CFLAGS_FEATURES += -DMINIMAL_JVM -DVMTYPE=\"Minimal\"
|
||||
ifeq ($(OPENJDK_TARGET_OS), linux)
|
||||
|
@ -300,7 +300,7 @@ LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli)
|
||||
|
||||
LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
|
||||
|
||||
ifeq ($(call check-jvm-variant, zero zeroshark), true)
|
||||
ifeq ($(call check-jvm-variant, zero), true)
|
||||
ERGO_FAMILY := zero
|
||||
else
|
||||
ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86)
|
||||
|
@ -42,10 +42,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "opto/runtime.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#endif
|
||||
|
||||
#define __ masm->
|
||||
|
||||
|
@ -43,7 +43,7 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
|
||||
#elif defined(COMPILER1)
|
||||
// pure C1, 32-bit, small machine
|
||||
#define DEFAULT_CACHE_LINE_SIZE 16
|
||||
#elif defined(COMPILER2) || defined(SHARK)
|
||||
#elif defined(COMPILER2)
|
||||
// pure C2, 64-bit, large machine
|
||||
#define DEFAULT_CACHE_LINE_SIZE 128
|
||||
#endif
|
||||
|
@ -41,10 +41,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "opto/runtime.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#endif
|
||||
#if INCLUDE_JVMCI
|
||||
#include "jvmci/jvmciJavaClasses.hpp"
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
|
||||
// pure C1, 32-bit, small machine
|
||||
// i486 was the last Intel chip with 16-byte cache line size
|
||||
#define DEFAULT_CACHE_LINE_SIZE 32
|
||||
#elif defined(COMPILER2) || defined(SHARK)
|
||||
#elif defined(COMPILER2)
|
||||
#ifdef _LP64
|
||||
// pure C2, 64-bit, large machine
|
||||
#define DEFAULT_CACHE_LINE_SIZE 128
|
||||
|
@ -50,9 +50,6 @@
|
||||
#include "stack_zero.inline.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#ifdef SHARK
|
||||
#include "shark/shark_globals.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef CC_INTERP
|
||||
|
||||
|
@ -71,7 +71,6 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
|
||||
|
||||
frame frame::sender_for_nonentry_frame(RegisterMap *map) const {
|
||||
assert(zeroframe()->is_interpreter_frame() ||
|
||||
zeroframe()->is_shark_frame() ||
|
||||
zeroframe()->is_fake_stub_frame(), "wrong type of frame");
|
||||
return frame(zeroframe()->next(), sender_sp());
|
||||
}
|
||||
@ -101,8 +100,6 @@ void frame::patch_pc(Thread* thread, address pc) {
|
||||
|
||||
if (pc != NULL) {
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
SharkFrame* sharkframe = zeroframe()->as_shark_frame();
|
||||
sharkframe->set_pc(pc);
|
||||
_pc = pc;
|
||||
_deopt_state = is_deoptimized;
|
||||
|
||||
@ -233,8 +230,6 @@ void ZeroFrame::identify_word(int frame_index,
|
||||
strncpy(valuebuf, "ENTRY_FRAME", buflen);
|
||||
else if (is_interpreter_frame())
|
||||
strncpy(valuebuf, "INTERPRETER_FRAME", buflen);
|
||||
else if (is_shark_frame())
|
||||
strncpy(valuebuf, "SHARK_FRAME", buflen);
|
||||
else if (is_fake_stub_frame())
|
||||
strncpy(valuebuf, "FAKE_STUB_FRAME", buflen);
|
||||
break;
|
||||
@ -248,10 +243,6 @@ void ZeroFrame::identify_word(int frame_index,
|
||||
as_interpreter_frame()->identify_word(
|
||||
frame_index, offset, fieldbuf, valuebuf, buflen);
|
||||
}
|
||||
else if (is_shark_frame()) {
|
||||
as_shark_frame()->identify_word(
|
||||
frame_index, offset, fieldbuf, valuebuf, buflen);
|
||||
}
|
||||
else if (is_fake_stub_frame()) {
|
||||
as_fake_stub_frame()->identify_word(
|
||||
frame_index, offset, fieldbuf, valuebuf, buflen);
|
||||
@ -350,50 +341,6 @@ void InterpreterFrame::identify_word(int frame_index,
|
||||
fieldbuf, buflen);
|
||||
}
|
||||
|
||||
void SharkFrame::identify_word(int frame_index,
|
||||
int offset,
|
||||
char* fieldbuf,
|
||||
char* valuebuf,
|
||||
int buflen) const {
|
||||
// Fixed part
|
||||
switch (offset) {
|
||||
case pc_off:
|
||||
strncpy(fieldbuf, "pc", buflen);
|
||||
if (method()->is_method()) {
|
||||
CompiledMethod *code = method()->code();
|
||||
if (code && code->pc_desc_at(pc())) {
|
||||
SimpleScopeDesc ssd(code, pc());
|
||||
snprintf(valuebuf, buflen, PTR_FORMAT " (bci %d)",
|
||||
(intptr_t) pc(), ssd.bci());
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case unextended_sp_off:
|
||||
strncpy(fieldbuf, "unextended_sp", buflen);
|
||||
return;
|
||||
|
||||
case method_off:
|
||||
strncpy(fieldbuf, "method", buflen);
|
||||
if (method()->is_method()) {
|
||||
method()->name_and_sig_as_C_string(valuebuf, buflen);
|
||||
}
|
||||
return;
|
||||
|
||||
case oop_tmp_off:
|
||||
strncpy(fieldbuf, "oop_tmp", buflen);
|
||||
return;
|
||||
}
|
||||
|
||||
// Variable part
|
||||
if (method()->is_method()) {
|
||||
identify_vp_word(frame_index, addr_of_word(offset),
|
||||
addr_of_word(header_words + 1),
|
||||
unextended_sp() + method()->max_stack(),
|
||||
fieldbuf, buflen);
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroFrame::identify_vp_word(int frame_index,
|
||||
intptr_t* addr,
|
||||
intptr_t* monitor_base,
|
||||
|
@ -62,9 +62,6 @@
|
||||
const InterpreterFrame *zero_interpreterframe() const {
|
||||
return zeroframe()->as_interpreter_frame();
|
||||
}
|
||||
const SharkFrame *zero_sharkframe() const {
|
||||
return zeroframe()->as_shark_frame();
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_fake_stub_frame() const;
|
||||
|
@ -56,18 +56,6 @@ inline frame::frame(ZeroFrame* zf, intptr_t* sp) {
|
||||
_deopt_state = not_deoptimized;
|
||||
break;
|
||||
|
||||
case ZeroFrame::SHARK_FRAME: {
|
||||
_pc = zero_sharkframe()->pc();
|
||||
_cb = CodeCache::find_blob_unsafe(pc());
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
_pc = original_pc;
|
||||
_deopt_state = is_deoptimized;
|
||||
} else {
|
||||
_deopt_state = not_deoptimized;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZeroFrame::FAKE_STUB_FRAME:
|
||||
_pc = NULL;
|
||||
_cb = NULL;
|
||||
@ -177,10 +165,7 @@ inline intptr_t* frame::entry_frame_argument_at(int offset) const {
|
||||
}
|
||||
|
||||
inline intptr_t* frame::unextended_sp() const {
|
||||
if (zeroframe()->is_shark_frame())
|
||||
return zero_sharkframe()->unextended_sp();
|
||||
else
|
||||
return (intptr_t *) -1;
|
||||
return (intptr_t *) -1;
|
||||
}
|
||||
|
||||
#endif // CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
|
||||
|
@ -29,7 +29,7 @@
|
||||
// Interface for updating the instruction cache. Whenever the VM
|
||||
// modifies code, part of the processor instruction cache potentially
|
||||
// has to be flushed. This implementation is empty: Zero never deals
|
||||
// with code, and LLVM handles cache flushing for Shark.
|
||||
// with code.
|
||||
|
||||
class ICache : public AbstractICache {
|
||||
public:
|
||||
|
@ -42,11 +42,6 @@
|
||||
// insert a jump to SharedRuntime::get_handle_wrong_method_stub()
|
||||
// (dest) at the start of a compiled method (verified_entry) to avoid
|
||||
// a race where a method is invoked while being made non-entrant.
|
||||
//
|
||||
// In Shark, verified_entry is a pointer to a SharkEntry. We can
|
||||
// handle this simply by changing it's entry point to point at the
|
||||
// interpreter. This only works because the interpreter and Shark
|
||||
// calling conventions are the same.
|
||||
|
||||
void NativeJump::patch_verified_entry(address entry,
|
||||
address verified_entry,
|
||||
|
@ -50,7 +50,7 @@ address Relocation::pd_get_address_from_code() {
|
||||
}
|
||||
|
||||
address* Relocation::pd_address_in_code() {
|
||||
// Relocations in Shark are just stored directly
|
||||
ShouldNotCallThis();
|
||||
return (address *) addr();
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "opto/runtime.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static address zero_null_code_stub() {
|
||||
@ -80,16 +75,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
BasicType *sig_bt,
|
||||
VMRegPair *regs,
|
||||
BasicType ret_type) {
|
||||
#ifdef SHARK
|
||||
return SharkCompiler::compiler()->generate_native_wrapper(masm,
|
||||
method,
|
||||
compile_id,
|
||||
sig_bt,
|
||||
ret_type);
|
||||
#else
|
||||
ShouldNotCallThis();
|
||||
return NULL;
|
||||
#endif // SHARK
|
||||
}
|
||||
|
||||
int Deoptimization::last_frame_adjust(int callee_parameters,
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 CPU_ZERO_VM_SHARKFRAME_ZERO_HPP
|
||||
#define CPU_ZERO_VM_SHARKFRAME_ZERO_HPP
|
||||
|
||||
#include "oops/method.hpp"
|
||||
#include "stack_zero.hpp"
|
||||
|
||||
// | ... |
|
||||
// +--------------------+ ------------------
|
||||
// | stack slot n-1 | low addresses
|
||||
// | ... |
|
||||
// | stack slot 0 |
|
||||
// | monitor m-1 |
|
||||
// | ... |
|
||||
// | monitor 0 |
|
||||
// | oop_tmp |
|
||||
// | method |
|
||||
// | unextended_sp |
|
||||
// | pc |
|
||||
// | frame_type |
|
||||
// | next_frame | high addresses
|
||||
// +--------------------+ ------------------
|
||||
// | ... |
|
||||
|
||||
class SharkFrame : public ZeroFrame {
|
||||
friend class SharkStack;
|
||||
|
||||
private:
|
||||
SharkFrame() : ZeroFrame() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
protected:
|
||||
enum Layout {
|
||||
pc_off = jf_header_words,
|
||||
unextended_sp_off,
|
||||
method_off,
|
||||
oop_tmp_off,
|
||||
header_words
|
||||
};
|
||||
|
||||
public:
|
||||
address pc() const {
|
||||
return (address) value_of_word(pc_off);
|
||||
}
|
||||
|
||||
void set_pc(address pc) const {
|
||||
*((address*) addr_of_word(pc_off)) = pc;
|
||||
}
|
||||
|
||||
intptr_t* unextended_sp() const {
|
||||
return (intptr_t *) value_of_word(unextended_sp_off);
|
||||
}
|
||||
|
||||
Method* method() const {
|
||||
return (Method*) value_of_word(method_off);
|
||||
}
|
||||
|
||||
public:
|
||||
void identify_word(int frame_index,
|
||||
int offset,
|
||||
char* fieldbuf,
|
||||
char* valuebuf,
|
||||
int buflen) const;
|
||||
};
|
||||
|
||||
#endif // CPU_ZERO_VM_SHARKFRAME_ZERO_HPP
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 CPU_ZERO_VM_SHARK_GLOBALS_ZERO_HPP
|
||||
#define CPU_ZERO_VM_SHARK_GLOBALS_ZERO_HPP
|
||||
|
||||
// Set the default values for platform dependent flags used by the
|
||||
// Shark compiler. See globals.hpp for details of what they do.
|
||||
|
||||
define_pd_global(bool, BackgroundCompilation, true );
|
||||
define_pd_global(bool, UseTLAB, true );
|
||||
define_pd_global(bool, ResizeTLAB, true );
|
||||
define_pd_global(bool, InlineIntrinsics, false);
|
||||
define_pd_global(bool, PreferInterpreterNativeStubs, false);
|
||||
define_pd_global(bool, ProfileTraps, false);
|
||||
define_pd_global(bool, UseOnStackReplacement, true );
|
||||
define_pd_global(bool, TieredCompilation, false);
|
||||
|
||||
define_pd_global(intx, CompileThreshold, 1500);
|
||||
define_pd_global(intx, Tier2CompileThreshold, 1500);
|
||||
define_pd_global(intx, Tier3CompileThreshold, 2500);
|
||||
define_pd_global(intx, Tier4CompileThreshold, 4500);
|
||||
|
||||
define_pd_global(intx, Tier2BackEdgeThreshold, 100000);
|
||||
define_pd_global(intx, Tier3BackEdgeThreshold, 100000);
|
||||
define_pd_global(intx, Tier4BackEdgeThreshold, 100000);
|
||||
|
||||
define_pd_global(intx, OnStackReplacePercentage, 933 );
|
||||
define_pd_global(intx, FreqInlineSize, 325 );
|
||||
define_pd_global(uintx, NewRatio, 12 );
|
||||
define_pd_global(size_t, NewSizeThreadIncrease, 4*K );
|
||||
define_pd_global(intx, InitialCodeCacheSize, 160*K);
|
||||
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
|
||||
define_pd_global(intx, NonProfiledCodeHeapSize, 13*M );
|
||||
define_pd_global(intx, ProfiledCodeHeapSize, 14*M );
|
||||
define_pd_global(intx, NonNMethodCodeHeapSize, 5*M );
|
||||
define_pd_global(bool, ProfileInterpreter, false);
|
||||
define_pd_global(intx, CodeCacheExpansionSize, 32*K );
|
||||
define_pd_global(uintx, CodeCacheMinBlockLength, 1 );
|
||||
define_pd_global(uintx, CodeCacheMinimumUseSpace, 200*K);
|
||||
|
||||
define_pd_global(size_t, MetaspaceSize, 12*M );
|
||||
define_pd_global(bool, NeverActAsServerClassMachine, true );
|
||||
define_pd_global(uint64_t, MaxRAM, 1ULL*G);
|
||||
define_pd_global(bool, CICompileOSR, true );
|
||||
|
||||
#endif // CPU_ZERO_VM_SHARK_GLOBALS_ZERO_HPP
|
@ -52,9 +52,6 @@ void ZeroStack::handle_overflow(TRAPS) {
|
||||
intptr_t *sp = thread->zero_stack()->sp();
|
||||
ZeroFrame *frame = thread->top_zero_frame();
|
||||
while (frame) {
|
||||
if (frame->is_shark_frame())
|
||||
break;
|
||||
|
||||
if (frame->is_interpreter_frame()) {
|
||||
interpreterState istate =
|
||||
frame->as_interpreter_frame()->interpreter_state();
|
||||
|
@ -121,7 +121,6 @@ class ZeroStack {
|
||||
|
||||
class EntryFrame;
|
||||
class InterpreterFrame;
|
||||
class SharkFrame;
|
||||
class FakeStubFrame;
|
||||
|
||||
//
|
||||
@ -151,7 +150,6 @@ class ZeroFrame {
|
||||
enum FrameType {
|
||||
ENTRY_FRAME = 1,
|
||||
INTERPRETER_FRAME,
|
||||
SHARK_FRAME,
|
||||
FAKE_STUB_FRAME
|
||||
};
|
||||
|
||||
@ -180,9 +178,6 @@ class ZeroFrame {
|
||||
bool is_interpreter_frame() const {
|
||||
return type() == INTERPRETER_FRAME;
|
||||
}
|
||||
bool is_shark_frame() const {
|
||||
return type() == SHARK_FRAME;
|
||||
}
|
||||
bool is_fake_stub_frame() const {
|
||||
return type() == FAKE_STUB_FRAME;
|
||||
}
|
||||
@ -196,10 +191,6 @@ class ZeroFrame {
|
||||
assert(is_interpreter_frame(), "should be");
|
||||
return (InterpreterFrame *) this;
|
||||
}
|
||||
SharkFrame *as_shark_frame() const {
|
||||
assert(is_shark_frame(), "should be");
|
||||
return (SharkFrame *) this;
|
||||
}
|
||||
FakeStubFrame *as_fake_stub_frame() const {
|
||||
assert(is_fake_stub_frame(), "should be");
|
||||
return (FakeStubFrame *) this;
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "runtime/thread.hpp"
|
||||
#include "stack_zero.hpp"
|
||||
|
||||
// This function should match SharkStack::CreateStackOverflowCheck
|
||||
inline void ZeroStack::overflow_check(int required_words, TRAPS) {
|
||||
// Check the Zero stack
|
||||
if (available_words() < required_words) {
|
||||
|
@ -1218,12 +1218,12 @@ void ciEnv::dump_compile_data(outputStream* out) {
|
||||
method->signature()->as_quoted_ascii(),
|
||||
entry_bci, comp_level);
|
||||
if (compiler_data() != NULL) {
|
||||
if (is_c2_compile(comp_level)) { // C2 or Shark
|
||||
if (is_c2_compile(comp_level)) {
|
||||
#ifdef COMPILER2
|
||||
// Dump C2 inlining data.
|
||||
((Compile*)compiler_data())->dump_inline_data(out);
|
||||
#endif
|
||||
} else if (is_c1_compile(comp_level)) { // C1
|
||||
} else if (is_c1_compile(comp_level)) {
|
||||
#ifdef COMPILER1
|
||||
// Dump C1 inlining data.
|
||||
((Compilation*)compiler_data())->dump_inline_data(out);
|
||||
|
@ -53,10 +53,6 @@
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#endif
|
||||
|
||||
// ciMethod
|
||||
//
|
||||
@ -97,10 +93,10 @@ ciMethod::ciMethod(const methodHandle& h_m, ciInstanceKlass* holder) :
|
||||
_exception_handlers = NULL;
|
||||
_liveness = NULL;
|
||||
_method_blocks = NULL;
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
_flow = NULL;
|
||||
_bcea = NULL;
|
||||
#endif // COMPILER2 || SHARK
|
||||
#endif // COMPILER2
|
||||
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
if (env->jvmti_can_hotswap_or_post_breakpoint() && can_be_compiled()) {
|
||||
@ -173,12 +169,12 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
|
||||
_can_be_statically_bound(false),
|
||||
_method_blocks( NULL),
|
||||
_method_data( NULL)
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
,
|
||||
_flow( NULL),
|
||||
_bcea( NULL),
|
||||
_instructions_size(-1)
|
||||
#endif // COMPILER2 || SHARK
|
||||
#endif // COMPILER2
|
||||
{
|
||||
// Usually holder and accessor are the same type but in some cases
|
||||
// the holder has the wrong class loader (e.g. invokedynamic call
|
||||
@ -287,23 +283,6 @@ int ciMethod::vtable_index() {
|
||||
}
|
||||
|
||||
|
||||
#ifdef SHARK
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::itable_index
|
||||
//
|
||||
// Get the position of this method's entry in the itable, if any.
|
||||
int ciMethod::itable_index() {
|
||||
check_is_loaded();
|
||||
assert(holder()->is_linked(), "must be linked");
|
||||
VM_ENTRY_MARK;
|
||||
Method* m = get_Method();
|
||||
if (!m->has_itable_index())
|
||||
return Method::nonvirtual_vtable_index;
|
||||
return m->itable_index();
|
||||
}
|
||||
#endif // SHARK
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::native_entry
|
||||
//
|
||||
@ -369,34 +348,34 @@ bool ciMethod::has_balanced_monitors() {
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::get_flow_analysis
|
||||
ciTypeFlow* ciMethod::get_flow_analysis() {
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
if (_flow == NULL) {
|
||||
ciEnv* env = CURRENT_ENV;
|
||||
_flow = new (env->arena()) ciTypeFlow(env, this);
|
||||
_flow->do_flow();
|
||||
}
|
||||
return _flow;
|
||||
#else // COMPILER2 || SHARK
|
||||
#else // COMPILER2
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
#endif // COMPILER2 || SHARK
|
||||
#endif // COMPILER2
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::get_osr_flow_analysis
|
||||
ciTypeFlow* ciMethod::get_osr_flow_analysis(int osr_bci) {
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
// OSR entry points are always place after a call bytecode of some sort
|
||||
assert(osr_bci >= 0, "must supply valid OSR entry point");
|
||||
ciEnv* env = CURRENT_ENV;
|
||||
ciTypeFlow* flow = new (env->arena()) ciTypeFlow(env, this, osr_bci);
|
||||
flow->do_flow();
|
||||
return flow;
|
||||
#else // COMPILER2 || SHARK
|
||||
#else // COMPILER2
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
#endif // COMPILER2 || SHARK
|
||||
#endif // COMPILER2
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -96,7 +96,7 @@ class ciMethod : public ciMetadata {
|
||||
|
||||
// Optional liveness analyzer.
|
||||
MethodLiveness* _liveness;
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
ciTypeFlow* _flow;
|
||||
BCEscapeAnalyzer* _bcea;
|
||||
#endif
|
||||
@ -216,9 +216,6 @@ class ciMethod : public ciMetadata {
|
||||
|
||||
// Runtime information.
|
||||
int vtable_index();
|
||||
#ifdef SHARK
|
||||
int itable_index();
|
||||
#endif // SHARK
|
||||
address native_entry();
|
||||
address interpreter_entry();
|
||||
|
||||
|
@ -30,12 +30,6 @@
|
||||
#include "ci/ciKlass.hpp"
|
||||
#include "ci/ciMethodBlocks.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "ci/ciEnv.hpp"
|
||||
#include "ci/ciKlass.hpp"
|
||||
#include "ci/ciMethodBlocks.hpp"
|
||||
#include "shark/shark_globals.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
class ciTypeFlow : public ResourceObj {
|
||||
|
@ -125,7 +125,6 @@ public:
|
||||
inline bool is_compiled_by_c1() const { return _type == compiler_c1; };
|
||||
inline bool is_compiled_by_c2() const { return _type == compiler_c2; };
|
||||
inline bool is_compiled_by_jvmci() const { return _type == compiler_jvmci; };
|
||||
inline bool is_compiled_by_shark() const { return _type == compiler_shark; };
|
||||
const char* compiler_name() const;
|
||||
|
||||
// Casting
|
||||
|
@ -294,7 +294,6 @@ int CompiledMethod::verify_icholder_relocations() {
|
||||
// Method that knows how to preserve outgoing arguments at call. This method must be
|
||||
// called with a frame corresponding to a Java invoke
|
||||
void CompiledMethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
|
||||
#ifndef SHARK
|
||||
if (method() != NULL && !method()->is_native()) {
|
||||
address pc = fr.pc();
|
||||
SimpleScopeDesc ssd(this, pc);
|
||||
@ -314,7 +313,6 @@ void CompiledMethod::preserve_callee_argument_oops(frame fr, const RegisterMap *
|
||||
|
||||
fr.oops_compiled_arguments_do(signature, has_receiver, has_appendix, reg_map, f);
|
||||
}
|
||||
#endif // !SHARK
|
||||
}
|
||||
|
||||
Method* CompiledMethod::attached_method(address call_instr) {
|
||||
|
@ -53,9 +53,6 @@
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
#include "utilities/xmlstream.hpp"
|
||||
#ifdef SHARK
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#endif
|
||||
#if INCLUDE_JVMCI
|
||||
#include "jvmci/jvmciJavaClasses.hpp"
|
||||
#endif
|
||||
@ -200,9 +197,6 @@ static java_nmethod_stats_struct c2_java_nmethod_stats;
|
||||
#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;
|
||||
@ -223,11 +217,6 @@ static void note_java_nmethod(nmethod* nm) {
|
||||
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);
|
||||
@ -1325,10 +1314,6 @@ void nmethod::flush() {
|
||||
CodeCache::drop_scavenge_root_nmethod(this);
|
||||
}
|
||||
|
||||
#ifdef SHARK
|
||||
((SharkCompiler *) compiler())->free_compiled_method(insts_begin());
|
||||
#endif // SHARK
|
||||
|
||||
CodeBlob::flush();
|
||||
CodeCache::free(this);
|
||||
}
|
||||
@ -2241,8 +2226,6 @@ void nmethod::print() const {
|
||||
tty->print("(c1) ");
|
||||
} else if (is_compiled_by_c2()) {
|
||||
tty->print("(c2) ");
|
||||
} else if (is_compiled_by_shark()) {
|
||||
tty->print("(shark) ");
|
||||
} else if (is_compiled_by_jvmci()) {
|
||||
tty->print("(JVMCI) ");
|
||||
} else {
|
||||
@ -2863,9 +2846,6 @@ void nmethod::print_statistics() {
|
||||
#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();
|
||||
|
@ -152,7 +152,6 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
const bool is_c1() { return _type == compiler_c1; }
|
||||
const bool is_c2() { return _type == compiler_c2; }
|
||||
const bool is_jvmci() { return _type == compiler_jvmci; }
|
||||
const bool is_shark() { return _type == compiler_shark; }
|
||||
const CompilerType type() { return _type; }
|
||||
|
||||
// Extra tests to identify trivial methods for the tiered compilation policy.
|
||||
|
@ -70,9 +70,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "opto/c2compiler.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef DTRACE_ENABLED
|
||||
|
||||
@ -531,7 +528,6 @@ void CompileBroker::compilation_init(TRAPS) {
|
||||
if (!UseCompiler) {
|
||||
return;
|
||||
}
|
||||
#ifndef SHARK
|
||||
// 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);
|
||||
@ -573,13 +569,6 @@ void CompileBroker::compilation_init(TRAPS) {
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
#else // SHARK
|
||||
int c1_count = 0;
|
||||
int c2_count = 1;
|
||||
|
||||
_compilers[1] = new SharkCompiler();
|
||||
#endif // SHARK
|
||||
|
||||
// Start the compiler thread(s) and the sweeper thread
|
||||
init_compiler_sweeper_threads(c1_count, c2_count);
|
||||
// totalTime performance counter is always created as it is required
|
||||
@ -774,9 +763,9 @@ JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, Co
|
||||
|
||||
void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count) {
|
||||
EXCEPTION_MARK;
|
||||
#if !defined(ZERO) && !defined(SHARK)
|
||||
#if !defined(ZERO)
|
||||
assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?");
|
||||
#endif // !ZERO && !SHARK
|
||||
#endif // !ZERO
|
||||
// Initialize the compilation queue
|
||||
if (c2_compiler_count > 0) {
|
||||
const char* name = JVMCI_ONLY(UseJVMCICompiler ? "JVMCI compile queue" :) "C2 compile queue";
|
||||
@ -796,7 +785,6 @@ void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_
|
||||
// Create a name for our thread.
|
||||
sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
|
||||
CompilerCounters* counters = new CompilerCounters();
|
||||
// Shark and C2
|
||||
make_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], compiler_thread, CHECK);
|
||||
}
|
||||
|
||||
@ -1100,7 +1088,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
|
||||
|
||||
assert(!HAS_PENDING_EXCEPTION, "No exception should be present");
|
||||
// some prerequisites that are compiler specific
|
||||
if (comp->is_c2() || comp->is_shark()) {
|
||||
if (comp->is_c2()) {
|
||||
method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NULL);
|
||||
// Resolve all classes seen in the signature of the method
|
||||
// we are compiling.
|
||||
@ -1490,10 +1478,8 @@ bool CompileBroker::init_compiler_runtime() {
|
||||
ThreadInVMfromNative tv(thread);
|
||||
ResetNoHandleMark rnhm;
|
||||
|
||||
if (!comp->is_shark()) {
|
||||
// Perform per-thread and global initializations
|
||||
comp->initialize();
|
||||
}
|
||||
// Perform per-thread and global initializations
|
||||
comp->initialize();
|
||||
}
|
||||
|
||||
if (comp->is_failed()) {
|
||||
|
@ -31,11 +31,10 @@ const char* compilertype2name_tab[compiler_number_of_types] = {
|
||||
"",
|
||||
"c1",
|
||||
"c2",
|
||||
"jvmci",
|
||||
"shark"
|
||||
"jvmci"
|
||||
};
|
||||
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
#if defined(COMPILER2)
|
||||
CompLevel CompLevel_highest_tier = CompLevel_full_optimization; // pure C2 and tiered or JVMCI and tiered
|
||||
#elif defined(COMPILER1)
|
||||
CompLevel CompLevel_highest_tier = CompLevel_simple; // pure C1 or JVMCI
|
||||
@ -47,7 +46,7 @@ CompLevel CompLevel_highest_tier = CompLevel_none;
|
||||
CompLevel CompLevel_initial_compile = CompLevel_full_profile; // tiered
|
||||
#elif defined(COMPILER1) || INCLUDE_JVMCI
|
||||
CompLevel CompLevel_initial_compile = CompLevel_simple; // pure C1 or JVMCI
|
||||
#elif defined(COMPILER2) || defined(SHARK)
|
||||
#elif defined(COMPILER2)
|
||||
CompLevel CompLevel_initial_compile = CompLevel_full_optimization; // pure C2
|
||||
#else
|
||||
CompLevel CompLevel_initial_compile = CompLevel_none;
|
||||
|
@ -33,7 +33,6 @@ enum CompilerType {
|
||||
compiler_c1,
|
||||
compiler_c2,
|
||||
compiler_jvmci,
|
||||
compiler_shark,
|
||||
compiler_number_of_types
|
||||
};
|
||||
|
||||
@ -54,7 +53,7 @@ enum CompLevel {
|
||||
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, Shark or JVMCI
|
||||
CompLevel_full_optimization = 4 // C2 or JVMCI
|
||||
};
|
||||
|
||||
extern CompLevel CompLevel_highest_tier;
|
||||
|
@ -171,7 +171,7 @@ DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
|
||||
return _c2_store;
|
||||
} else {
|
||||
// use c1_store as default
|
||||
assert(comp->is_c1() || comp->is_jvmci() || comp->is_shark(), "");
|
||||
assert(comp->is_c1() || comp->is_jvmci(), "");
|
||||
return _c1_store;
|
||||
}
|
||||
}
|
||||
|
@ -35,9 +35,6 @@
|
||||
#include "runtime/stubCodeGenerator.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include CPU_HEADER(depChecker)
|
||||
#ifdef SHARK
|
||||
#include "shark/sharkEntry.hpp"
|
||||
#endif
|
||||
|
||||
void* Disassembler::_library = NULL;
|
||||
bool Disassembler::_tried_to_load_library = false;
|
||||
@ -521,14 +518,8 @@ void Disassembler::decode(nmethod* nm, outputStream* st) {
|
||||
decode_env env(nm, st);
|
||||
env.output()->print_cr("----------------------------------------------------------------------");
|
||||
|
||||
#ifdef SHARK
|
||||
SharkEntry* entry = (SharkEntry *) nm->code_begin();
|
||||
unsigned char* p = entry->code_start();
|
||||
unsigned char* end = entry->code_limit();
|
||||
#else
|
||||
unsigned char* p = nm->code_begin();
|
||||
unsigned char* end = nm->code_end();
|
||||
#endif // SHARK
|
||||
|
||||
nm->method()->method_holder()->name()->print_symbol_on(env.output());
|
||||
env.output()->print(".");
|
||||
|
@ -478,9 +478,7 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
#ifdef ASSERT
|
||||
if (istate->_msg != initialize) {
|
||||
assert(labs(istate->_stack_base - istate->_stack_limit) == (istate->_method->max_stack() + 1), "bad stack limit");
|
||||
#ifndef SHARK
|
||||
IA32_ONLY(assert(istate->_stack_limit == istate->_thread->last_Java_sp() + 1, "wrong"));
|
||||
#endif // !SHARK
|
||||
}
|
||||
// Verify linkages.
|
||||
interpreterState l = istate;
|
||||
|
@ -1165,15 +1165,11 @@ void Method::set_code(const methodHandle& mh, CompiledMethod *code) {
|
||||
}
|
||||
|
||||
OrderAccess::storestore();
|
||||
#ifdef SHARK
|
||||
mh->_from_interpreted_entry = code->insts_begin();
|
||||
#else //!SHARK
|
||||
mh->_from_compiled_entry = code->verified_entry_point();
|
||||
OrderAccess::storestore();
|
||||
// Instantly compiled code can execute.
|
||||
if (!mh->is_method_handle_intrinsic())
|
||||
mh->_from_interpreted_entry = mh->get_i2c_entry();
|
||||
#endif //!SHARK
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ Flag::Error AliasLevelConstraintFunc(intx value, bool verbose) {
|
||||
*/
|
||||
Flag::Error CICompilerCountConstraintFunc(intx value, bool verbose) {
|
||||
int min_number_of_compiler_threads = 0;
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2) && !INCLUDE_JVMCI
|
||||
// case 1
|
||||
#else
|
||||
if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
|
||||
|
@ -339,7 +339,6 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
|
||||
}
|
||||
|
||||
#ifndef SHARK
|
||||
// Compute the caller frame based on the sender sp of stub_frame and stored frame sizes info.
|
||||
CodeBlob* cb = stub_frame.cb();
|
||||
// Verify we have the right vframeArray
|
||||
@ -359,9 +358,6 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
strcmp("Stub<UncommonTrapStub.uncommonTrapHandler>", cb->name()) == 0,
|
||||
"unexpected code blob: %s", cb->name());
|
||||
#endif
|
||||
#else
|
||||
intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp();
|
||||
#endif // !SHARK
|
||||
|
||||
// This is a guarantee instead of an assert because if vframe doesn't match
|
||||
// we will unpack the wrong deoptimized frame and wind up in strange places
|
||||
@ -488,9 +484,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
|
||||
frame_pcs[0] = deopt_sender.raw_pc();
|
||||
|
||||
#ifndef SHARK
|
||||
assert(CodeCache::find_blob_unsafe(frame_pcs[0]) != NULL, "bad pc");
|
||||
#endif // SHARK
|
||||
|
||||
#ifdef INCLUDE_JVMCI
|
||||
if (exceptionObject() != NULL) {
|
||||
@ -1449,7 +1443,7 @@ Deoptimization::get_method_data(JavaThread* thread, const methodHandle& m,
|
||||
return mdo;
|
||||
}
|
||||
|
||||
#if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
|
||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||
void Deoptimization::load_class_by_index(const 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()) {
|
||||
@ -2366,7 +2360,7 @@ void Deoptimization::print_statistics() {
|
||||
if (xtty != NULL) xtty->tail("statistics");
|
||||
}
|
||||
}
|
||||
#else // COMPILER2 || SHARK || INCLUDE_JVMCI
|
||||
#else // COMPILER2 || INCLUDE_JVMCI
|
||||
|
||||
|
||||
// Stubs for C1 only system.
|
||||
@ -2402,4 +2396,4 @@ const char* Deoptimization::format_trap_state(char* buf, size_t buflen,
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif // COMPILER2 || SHARK || INCLUDE_JVMCI
|
||||
#endif // COMPILER2 || INCLUDE_JVMCI
|
||||
|
@ -1115,10 +1115,6 @@ void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* ma
|
||||
oops_entry_do(f, map);
|
||||
} else if (CodeCache::contains(pc())) {
|
||||
oops_code_blob_do(f, cf, map);
|
||||
#ifdef SHARK
|
||||
} else if (is_fake_stub_frame()) {
|
||||
// nothing to do
|
||||
#endif // SHARK
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
# include "entryFrame_zero.hpp"
|
||||
# include "fakeStubFrame_zero.hpp"
|
||||
# include "interpreterFrame_zero.hpp"
|
||||
# include "sharkFrame_zero.hpp"
|
||||
#endif
|
||||
|
||||
#include CPU_HEADER_INLINE(frame)
|
||||
|
@ -50,9 +50,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "opto/c2_globals.hpp"
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#include "shark/shark_globals.hpp"
|
||||
#endif
|
||||
|
||||
RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
|
||||
MATERIALIZE_PD_DEVELOPER_FLAG, \
|
||||
@ -578,7 +575,6 @@ void Flag::print_kind_and_origin(outputStream* st) {
|
||||
{ KIND_C1, "C1" },
|
||||
{ KIND_C2, "C2" },
|
||||
{ KIND_ARCH, "ARCH" },
|
||||
{ KIND_SHARK, "SHARK" },
|
||||
{ KIND_PLATFORM_DEPENDENT, "pd" },
|
||||
{ KIND_PRODUCT, "product" },
|
||||
{ KIND_MANAGEABLE, "manageable" },
|
||||
@ -754,14 +750,6 @@ const char* Flag::flag_error_str(Flag::Error error) {
|
||||
#define ARCH_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DEVELOP) },
|
||||
#define ARCH_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_NOT_PRODUCT) },
|
||||
|
||||
#define SHARK_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT) },
|
||||
#define SHARK_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) },
|
||||
#define SHARK_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DIAGNOSTIC) },
|
||||
#define SHARK_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DIAGNOSTIC | Flag::KIND_PLATFORM_DEPENDENT) },
|
||||
#define SHARK_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP) },
|
||||
#define SHARK_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
|
||||
#define SHARK_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_NOT_PRODUCT) },
|
||||
|
||||
static Flag flagTable[] = {
|
||||
RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
|
||||
RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
|
||||
@ -840,18 +828,6 @@ static Flag flagTable[] = {
|
||||
IGNORE_CONSTRAINT, \
|
||||
IGNORE_WRITEABLE)
|
||||
#endif // COMPILER2
|
||||
#ifdef SHARK
|
||||
SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, \
|
||||
SHARK_PD_DEVELOP_FLAG_STRUCT, \
|
||||
SHARK_PRODUCT_FLAG_STRUCT, \
|
||||
SHARK_PD_PRODUCT_FLAG_STRUCT, \
|
||||
SHARK_DIAGNOSTIC_FLAG_STRUCT, \
|
||||
SHARK_PD_DIAGNOSTIC_FLAG_STRUCT, \
|
||||
SHARK_NOTPRODUCT_FLAG_STRUCT, \
|
||||
IGNORE_RANGE, \
|
||||
IGNORE_CONSTRAINT, \
|
||||
IGNORE_WRITEABLE)
|
||||
#endif // SHARK
|
||||
ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \
|
||||
ARCH_PRODUCT_FLAG_STRUCT, \
|
||||
ARCH_DIAGNOSTIC_FLAG_STRUCT, \
|
||||
|
@ -63,13 +63,8 @@
|
||||
#include CPU_HEADER(c2_globals)
|
||||
#include OS_HEADER(c2_globals)
|
||||
#endif
|
||||
#ifdef SHARK
|
||||
#ifdef ZERO
|
||||
# include "shark_globals_zero.hpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2) && !INCLUDE_JVMCI
|
||||
define_pd_global(bool, BackgroundCompilation, false);
|
||||
define_pd_global(bool, UseTLAB, false);
|
||||
define_pd_global(bool, CICompileOSR, false);
|
||||
@ -147,13 +142,12 @@ struct Flag {
|
||||
KIND_C1 = 1 << 12,
|
||||
KIND_C2 = 1 << 13,
|
||||
KIND_ARCH = 1 << 14,
|
||||
KIND_SHARK = 1 << 15,
|
||||
KIND_LP64_PRODUCT = 1 << 16,
|
||||
KIND_COMMERCIAL = 1 << 17,
|
||||
KIND_JVMCI = 1 << 18,
|
||||
KIND_LP64_PRODUCT = 1 << 15,
|
||||
KIND_COMMERCIAL = 1 << 16,
|
||||
KIND_JVMCI = 1 << 17,
|
||||
|
||||
// set this bit if the flag was set on the command line
|
||||
ORIG_COMMAND_LINE = 1 << 19,
|
||||
ORIG_COMMAND_LINE = 1 << 18,
|
||||
|
||||
KIND_MASK = ~(VALUE_ORIGIN_MASK | ORIG_COMMAND_LINE)
|
||||
};
|
||||
|
@ -3724,7 +3724,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
}
|
||||
|
||||
// initialize compiler(s)
|
||||
#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
|
||||
#if defined(COMPILER1) || defined(COMPILER2) || INCLUDE_JVMCI
|
||||
CompileBroker::compilation_init(CHECK_JNI_ERR);
|
||||
#endif
|
||||
|
||||
|
@ -95,11 +95,7 @@ bool Abstract_VM_Version::_parallel_worker_threads_initialized = false;
|
||||
#define VMTYPE "Server"
|
||||
#else // TIERED
|
||||
#ifdef ZERO
|
||||
#ifdef SHARK
|
||||
#define VMTYPE "Shark"
|
||||
#else // SHARK
|
||||
#define VMTYPE "Zero"
|
||||
#endif // SHARK
|
||||
#else // ZERO
|
||||
#define VMTYPE COMPILER1_PRESENT("Client") \
|
||||
COMPILER2_PRESENT("Server")
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_LLVMHEADERS_HPP
|
||||
#define SHARE_VM_SHARK_LLVMHEADERS_HPP
|
||||
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define SHARK_DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#include <llvm/Analysis/Verifier.h>
|
||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
|
||||
// includes specific to each version
|
||||
#if SHARK_LLVM_VERSION <= 31
|
||||
#include <llvm/Support/IRBuilder.h>
|
||||
#include <llvm/Type.h>
|
||||
#include <llvm/Argument.h>
|
||||
#include <llvm/Constants.h>
|
||||
#include <llvm/DerivedTypes.h>
|
||||
#include <llvm/Instructions.h>
|
||||
#include <llvm/LLVMContext.h>
|
||||
#include <llvm/Module.h>
|
||||
#elif SHARK_LLVM_VERSION <= 32
|
||||
#include <llvm/IRBuilder.h>
|
||||
#include <llvm/Type.h>
|
||||
#include <llvm/Argument.h>
|
||||
#include <llvm/Constants.h>
|
||||
#include <llvm/DerivedTypes.h>
|
||||
#include <llvm/Instructions.h>
|
||||
#include <llvm/LLVMContext.h>
|
||||
#include <llvm/Module.h>
|
||||
#else // SHARK_LLVM_VERSION <= 34
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/Argument.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/IR/Type.h>
|
||||
#endif
|
||||
|
||||
// common includes
|
||||
#include <llvm/Support/Threading.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
#include <llvm/ExecutionEngine/JITMemoryManager.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/ExecutionEngine/MCJIT.h>
|
||||
#include <llvm/ExecutionEngine/JIT.h>
|
||||
#include <llvm/ADT/StringMap.h>
|
||||
#include <llvm/Support/Debug.h>
|
||||
#include <llvm/Support/Host.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
#define assert(p, msg) vmassert(p, msg)
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#ifdef SHARK_DEBUG
|
||||
#define DEBUG
|
||||
#undef SHARK_DEBUG
|
||||
#endif
|
||||
|
||||
#endif // SHARE_VM_SHARK_LLVMHEADERS_HPP
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_LLVMVALUE_HPP
|
||||
#define SHARE_VM_SHARK_LLVMVALUE_HPP
|
||||
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
|
||||
class LLVMValue : public AllStatic {
|
||||
public:
|
||||
static llvm::ConstantInt* jbyte_constant(jbyte value)
|
||||
{
|
||||
return llvm::ConstantInt::get(SharkType::jbyte_type(), value, true);
|
||||
}
|
||||
static llvm::ConstantInt* jint_constant(jint value)
|
||||
{
|
||||
return llvm::ConstantInt::get(SharkType::jint_type(), value, true);
|
||||
}
|
||||
static llvm::ConstantInt* jlong_constant(jlong value)
|
||||
{
|
||||
return llvm::ConstantInt::get(SharkType::jlong_type(), value, true);
|
||||
}
|
||||
static llvm::ConstantFP* jfloat_constant(jfloat value)
|
||||
{
|
||||
return llvm::ConstantFP::get(SharkContext::current(), llvm::APFloat(value));
|
||||
}
|
||||
static llvm::ConstantFP* jdouble_constant(jdouble value)
|
||||
{
|
||||
return llvm::ConstantFP::get(SharkContext::current(), llvm::APFloat(value));
|
||||
}
|
||||
static llvm::ConstantPointerNull* null()
|
||||
{
|
||||
return llvm::ConstantPointerNull::get(SharkType::oop_type());
|
||||
}
|
||||
static llvm::ConstantPointerNull* nullKlass()
|
||||
{
|
||||
return llvm::ConstantPointerNull::get(SharkType::klass_type());
|
||||
}
|
||||
|
||||
public:
|
||||
static llvm::ConstantInt* bit_constant(int value)
|
||||
{
|
||||
return llvm::ConstantInt::get(SharkType::bit_type(), value, false);
|
||||
}
|
||||
static llvm::ConstantInt* intptr_constant(intptr_t value)
|
||||
{
|
||||
return llvm::ConstantInt::get(SharkType::intptr_type(), value, false);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_LLVMVALUE_HPP
|
File diff suppressed because it is too large
Load Diff
@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKBLOCK_HPP
|
||||
#define SHARE_VM_SHARK_SHARKBLOCK_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkConstant.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
class SharkState;
|
||||
|
||||
class SharkBlock : public SharkTargetInvariants {
|
||||
protected:
|
||||
SharkBlock(const SharkTargetInvariants* parent)
|
||||
: SharkTargetInvariants(parent),
|
||||
_iter(target()),
|
||||
_current_state(NULL) {}
|
||||
|
||||
SharkBlock(const SharkCompileInvariants* parent, ciMethod* target)
|
||||
: SharkTargetInvariants(parent, target),
|
||||
_iter(target),
|
||||
_current_state(NULL) {}
|
||||
|
||||
private:
|
||||
ciBytecodeStream _iter;
|
||||
SharkState* _current_state;
|
||||
|
||||
public:
|
||||
ciBytecodeStream* iter() {
|
||||
return &_iter;
|
||||
}
|
||||
Bytecodes::Code bc() {
|
||||
return iter()->cur_bc();
|
||||
}
|
||||
int bci() {
|
||||
return iter()->cur_bci();
|
||||
}
|
||||
|
||||
// Entry state
|
||||
protected:
|
||||
virtual SharkState* entry_state();
|
||||
|
||||
// Current state
|
||||
private:
|
||||
SharkState* initial_current_state();
|
||||
|
||||
public:
|
||||
SharkState* current_state() {
|
||||
if (_current_state == NULL)
|
||||
set_current_state(initial_current_state());
|
||||
return _current_state;
|
||||
}
|
||||
|
||||
protected:
|
||||
void set_current_state(SharkState* current_state) {
|
||||
_current_state = current_state;
|
||||
}
|
||||
|
||||
// Local variables
|
||||
protected:
|
||||
SharkValue* local(int index) {
|
||||
SharkValue *value = current_state()->local(index);
|
||||
assert(value != NULL, "shouldn't be");
|
||||
assert(value->is_one_word() ||
|
||||
(index + 1 < max_locals() &&
|
||||
current_state()->local(index + 1) == NULL), "should be");
|
||||
return value;
|
||||
}
|
||||
void set_local(int index, SharkValue* value) {
|
||||
assert(value != NULL, "shouldn't be");
|
||||
current_state()->set_local(index, value);
|
||||
if (value->is_two_word())
|
||||
current_state()->set_local(index + 1, NULL);
|
||||
}
|
||||
|
||||
// Expression stack (raw)
|
||||
protected:
|
||||
void xpush(SharkValue* value) {
|
||||
current_state()->push(value);
|
||||
}
|
||||
SharkValue* xpop() {
|
||||
return current_state()->pop();
|
||||
}
|
||||
SharkValue* xstack(int slot) {
|
||||
SharkValue *value = current_state()->stack(slot);
|
||||
assert(value != NULL, "shouldn't be");
|
||||
assert(value->is_one_word() ||
|
||||
(slot > 0 &&
|
||||
current_state()->stack(slot - 1) == NULL), "should be");
|
||||
return value;
|
||||
}
|
||||
int xstack_depth() {
|
||||
return current_state()->stack_depth();
|
||||
}
|
||||
|
||||
// Expression stack (cooked)
|
||||
protected:
|
||||
void push(SharkValue* value) {
|
||||
assert(value != NULL, "shouldn't be");
|
||||
xpush(value);
|
||||
if (value->is_two_word())
|
||||
xpush(NULL);
|
||||
}
|
||||
SharkValue* pop() {
|
||||
int size = current_state()->stack(0) == NULL ? 2 : 1;
|
||||
if (size == 2)
|
||||
xpop();
|
||||
SharkValue *value = xpop();
|
||||
assert(value && value->size() == size, "should be");
|
||||
return value;
|
||||
}
|
||||
SharkValue* pop_result(BasicType type) {
|
||||
SharkValue *result = pop();
|
||||
|
||||
#ifdef ASSERT
|
||||
switch (result->basic_type()) {
|
||||
case T_BOOLEAN:
|
||||
case T_BYTE:
|
||||
case T_CHAR:
|
||||
case T_SHORT:
|
||||
assert(type == T_INT, "type mismatch");
|
||||
break;
|
||||
|
||||
case T_ARRAY:
|
||||
assert(type == T_OBJECT, "type mismatch");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(result->basic_type() == type, "type mismatch");
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Code generation
|
||||
public:
|
||||
virtual void emit_IR();
|
||||
|
||||
protected:
|
||||
void parse_bytecode(int start, int limit);
|
||||
|
||||
// Helpers
|
||||
protected:
|
||||
virtual void do_zero_check(SharkValue* value);
|
||||
|
||||
// Zero checking
|
||||
protected:
|
||||
void check_null(SharkValue* object) {
|
||||
zero_check(object);
|
||||
}
|
||||
void check_divide_by_zero(SharkValue* value) {
|
||||
zero_check(value);
|
||||
}
|
||||
private:
|
||||
void zero_check(SharkValue* value) {
|
||||
if (!value->zero_checked())
|
||||
do_zero_check(value);
|
||||
}
|
||||
|
||||
// Safepoints
|
||||
protected:
|
||||
virtual void maybe_add_backedge_safepoint();
|
||||
|
||||
// Traps
|
||||
protected:
|
||||
virtual bool has_trap();
|
||||
virtual int trap_request();
|
||||
virtual int trap_bci();
|
||||
virtual void do_trap(int trap_request);
|
||||
|
||||
// arraylength
|
||||
protected:
|
||||
virtual void do_arraylength();
|
||||
|
||||
// *aload and *astore
|
||||
protected:
|
||||
virtual void do_aload(BasicType basic_type);
|
||||
virtual void do_astore(BasicType basic_type);
|
||||
|
||||
// *div and *rem
|
||||
private:
|
||||
void do_idiv() {
|
||||
do_div_or_rem(false, false);
|
||||
}
|
||||
void do_irem() {
|
||||
do_div_or_rem(false, true);
|
||||
}
|
||||
void do_ldiv() {
|
||||
do_div_or_rem(true, false);
|
||||
}
|
||||
void do_lrem() {
|
||||
do_div_or_rem(true, true);
|
||||
}
|
||||
void do_div_or_rem(bool is_long, bool is_rem);
|
||||
|
||||
// get* and put*
|
||||
private:
|
||||
void do_getstatic() {
|
||||
do_field_access(true, false);
|
||||
}
|
||||
void do_getfield() {
|
||||
do_field_access(true, true);
|
||||
}
|
||||
void do_putstatic() {
|
||||
do_field_access(false, false);
|
||||
}
|
||||
void do_putfield() {
|
||||
do_field_access(false, true);
|
||||
}
|
||||
void do_field_access(bool is_get, bool is_field);
|
||||
|
||||
// lcmp and [fd]cmp[lg]
|
||||
private:
|
||||
void do_lcmp();
|
||||
void do_fcmp(bool is_double, bool unordered_is_greater);
|
||||
|
||||
// *return and athrow
|
||||
protected:
|
||||
virtual void do_return(BasicType type);
|
||||
virtual void do_athrow();
|
||||
|
||||
// goto*
|
||||
protected:
|
||||
virtual void do_goto();
|
||||
|
||||
// jsr* and ret
|
||||
protected:
|
||||
virtual void do_jsr();
|
||||
virtual void do_ret();
|
||||
|
||||
// if*
|
||||
protected:
|
||||
virtual void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
|
||||
|
||||
// *switch
|
||||
protected:
|
||||
int switch_default_dest();
|
||||
int switch_table_length();
|
||||
int switch_key(int i);
|
||||
int switch_dest(int i);
|
||||
|
||||
virtual void do_switch();
|
||||
|
||||
// invoke*
|
||||
protected:
|
||||
virtual void do_call();
|
||||
|
||||
// checkcast and instanceof
|
||||
protected:
|
||||
virtual void do_instance_check();
|
||||
virtual bool maybe_do_instanceof_if();
|
||||
|
||||
// new and *newarray
|
||||
protected:
|
||||
virtual void do_new();
|
||||
virtual void do_newarray();
|
||||
virtual void do_anewarray();
|
||||
virtual void do_multianewarray();
|
||||
|
||||
// monitorenter and monitorexit
|
||||
protected:
|
||||
virtual void do_monitorenter();
|
||||
virtual void do_monitorexit();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKBLOCK_HPP
|
@ -1,530 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciMethod.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/cardTableModRefBS.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "prims/unsafe.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "shark/sharkRuntime.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer)
|
||||
: IRBuilder<>(SharkContext::current()),
|
||||
_code_buffer(code_buffer) {
|
||||
}
|
||||
|
||||
// Helpers for accessing structures
|
||||
Value* SharkBuilder::CreateAddressOfStructEntry(Value* base,
|
||||
ByteSize offset,
|
||||
Type* type,
|
||||
const char* name) {
|
||||
return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name);
|
||||
}
|
||||
|
||||
LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base,
|
||||
ByteSize offset,
|
||||
Type* type,
|
||||
const char* name) {
|
||||
return CreateLoad(
|
||||
CreateAddressOfStructEntry(
|
||||
base, offset, PointerType::getUnqual(type)),
|
||||
name);
|
||||
}
|
||||
|
||||
// Helpers for accessing arrays
|
||||
|
||||
LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) {
|
||||
return CreateValueOfStructEntry(
|
||||
arrayoop, in_ByteSize(arrayOopDesc::length_offset_in_bytes()),
|
||||
SharkType::jint_type(), "length");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,
|
||||
Type* element_type,
|
||||
int element_bytes,
|
||||
ByteSize base_offset,
|
||||
Value* index,
|
||||
const char* name) {
|
||||
Value* offset = CreateIntCast(index, SharkType::intptr_type(), false);
|
||||
if (element_bytes != 1)
|
||||
offset = CreateShl(
|
||||
offset,
|
||||
LLVMValue::intptr_constant(exact_log2(element_bytes)));
|
||||
offset = CreateAdd(
|
||||
LLVMValue::intptr_constant(in_bytes(base_offset)), offset);
|
||||
|
||||
return CreateIntToPtr(
|
||||
CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset),
|
||||
PointerType::getUnqual(element_type),
|
||||
name);
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,
|
||||
BasicType basic_type,
|
||||
ByteSize base_offset,
|
||||
Value* index,
|
||||
const char* name) {
|
||||
return CreateArrayAddress(
|
||||
arrayoop,
|
||||
SharkType::to_arrayType(basic_type),
|
||||
type2aelembytes(basic_type),
|
||||
base_offset, index, name);
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,
|
||||
BasicType basic_type,
|
||||
Value* index,
|
||||
const char* name) {
|
||||
return CreateArrayAddress(
|
||||
arrayoop, basic_type,
|
||||
in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)),
|
||||
index, name);
|
||||
}
|
||||
|
||||
// Helpers for creating intrinsics and external functions.
|
||||
|
||||
Type* SharkBuilder::make_type(char type, bool void_ok) {
|
||||
switch (type) {
|
||||
// Primitive types
|
||||
case 'c':
|
||||
return SharkType::jbyte_type();
|
||||
case 'i':
|
||||
return SharkType::jint_type();
|
||||
case 'l':
|
||||
return SharkType::jlong_type();
|
||||
case 'x':
|
||||
return SharkType::intptr_type();
|
||||
case 'f':
|
||||
return SharkType::jfloat_type();
|
||||
case 'd':
|
||||
return SharkType::jdouble_type();
|
||||
|
||||
// Pointers to primitive types
|
||||
case 'C':
|
||||
case 'I':
|
||||
case 'L':
|
||||
case 'X':
|
||||
case 'F':
|
||||
case 'D':
|
||||
return PointerType::getUnqual(make_type(tolower(type), false));
|
||||
|
||||
// VM objects
|
||||
case 'T':
|
||||
return SharkType::thread_type();
|
||||
case 'M':
|
||||
return PointerType::getUnqual(SharkType::monitor_type());
|
||||
case 'O':
|
||||
return SharkType::oop_type();
|
||||
case 'K':
|
||||
return SharkType::klass_type();
|
||||
|
||||
// Miscellaneous
|
||||
case 'v':
|
||||
assert(void_ok, "should be");
|
||||
return SharkType::void_type();
|
||||
case '1':
|
||||
return SharkType::bit_type();
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
FunctionType* SharkBuilder::make_ftype(const char* params,
|
||||
const char* ret) {
|
||||
std::vector<Type*> param_types;
|
||||
for (const char* c = params; *c; c++)
|
||||
param_types.push_back(make_type(*c, false));
|
||||
|
||||
assert(strlen(ret) == 1, "should be");
|
||||
Type *return_type = make_type(*ret, true);
|
||||
|
||||
return FunctionType::get(return_type, param_types, false);
|
||||
}
|
||||
|
||||
// Create an object representing an intrinsic or external function by
|
||||
// referencing the symbol by name. This is the LLVM-style approach,
|
||||
// but it cannot be used on functions within libjvm.so its symbols
|
||||
// are not exported. Note that you cannot make this work simply by
|
||||
// exporting the symbols, as some symbols have the same names as
|
||||
// symbols in the standard libraries (eg, atan2, fabs) and would
|
||||
// obscure them were they visible.
|
||||
Value* SharkBuilder::make_function(const char* name,
|
||||
const char* params,
|
||||
const char* ret) {
|
||||
return SharkContext::current().get_external(name, make_ftype(params, ret));
|
||||
}
|
||||
|
||||
// Create an object representing an external function by inlining a
|
||||
// function pointer in the code. This is not the LLVM way, but it's
|
||||
// the only way to access functions in libjvm.so and functions like
|
||||
// __kernel_dmb on ARM which is accessed via an absolute address.
|
||||
Value* SharkBuilder::make_function(address func,
|
||||
const char* params,
|
||||
const char* ret) {
|
||||
return CreateIntToPtr(
|
||||
LLVMValue::intptr_constant((intptr_t) func),
|
||||
PointerType::getUnqual(make_ftype(params, ret)));
|
||||
}
|
||||
|
||||
// VM calls
|
||||
|
||||
Value* SharkBuilder::find_exception_handler() {
|
||||
return make_function(
|
||||
(address) SharkRuntime::find_exception_handler, "TIi", "i");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::monitorenter() {
|
||||
return make_function((address) SharkRuntime::monitorenter, "TM", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::monitorexit() {
|
||||
return make_function((address) SharkRuntime::monitorexit, "TM", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::new_instance() {
|
||||
return make_function((address) SharkRuntime::new_instance, "Ti", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::newarray() {
|
||||
return make_function((address) SharkRuntime::newarray, "Tii", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::anewarray() {
|
||||
return make_function((address) SharkRuntime::anewarray, "Tii", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::multianewarray() {
|
||||
return make_function((address) SharkRuntime::multianewarray, "TiiI", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::register_finalizer() {
|
||||
return make_function((address) SharkRuntime::register_finalizer, "TO", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::safepoint() {
|
||||
return make_function((address) SafepointSynchronize::block, "T", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::throw_ArithmeticException() {
|
||||
return make_function(
|
||||
(address) SharkRuntime::throw_ArithmeticException, "TCi", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::throw_ArrayIndexOutOfBoundsException() {
|
||||
return make_function(
|
||||
(address) SharkRuntime::throw_ArrayIndexOutOfBoundsException, "TCii", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::throw_ClassCastException() {
|
||||
return make_function(
|
||||
(address) SharkRuntime::throw_ClassCastException, "TCi", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::throw_NullPointerException() {
|
||||
return make_function(
|
||||
(address) SharkRuntime::throw_NullPointerException, "TCi", "v");
|
||||
}
|
||||
|
||||
// High-level non-VM calls
|
||||
|
||||
Value* SharkBuilder::f2i() {
|
||||
return make_function((address) SharedRuntime::f2i, "f", "i");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::f2l() {
|
||||
return make_function((address) SharedRuntime::f2l, "f", "l");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::d2i() {
|
||||
return make_function((address) SharedRuntime::d2i, "d", "i");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::d2l() {
|
||||
return make_function((address) SharedRuntime::d2l, "d", "l");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::is_subtype_of() {
|
||||
return make_function((address) SharkRuntime::is_subtype_of, "KK", "c");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::current_time_millis() {
|
||||
return make_function((address) os::javaTimeMillis, "", "l");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::sin() {
|
||||
return make_function("llvm.sin.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::cos() {
|
||||
return make_function("llvm.cos.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::tan() {
|
||||
return make_function((address) ::tan, "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::atan2() {
|
||||
return make_function((address) ::atan2, "dd", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::sqrt() {
|
||||
return make_function("llvm.sqrt.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::log() {
|
||||
return make_function("llvm.log.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::log10() {
|
||||
return make_function("llvm.log10.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::pow() {
|
||||
return make_function("llvm.pow.f64", "dd", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::exp() {
|
||||
return make_function("llvm.exp.f64", "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::fabs() {
|
||||
return make_function((address) ::fabs, "d", "d");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::unsafe_field_offset_to_byte_offset() {
|
||||
return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::osr_migration_end() {
|
||||
return make_function((address) SharedRuntime::OSR_migration_end, "C", "v");
|
||||
}
|
||||
|
||||
// Semi-VM calls
|
||||
|
||||
Value* SharkBuilder::throw_StackOverflowError() {
|
||||
return make_function((address) ZeroStack::handle_overflow, "T", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::uncommon_trap() {
|
||||
return make_function((address) SharkRuntime::uncommon_trap, "Ti", "i");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::deoptimized_entry_point() {
|
||||
return make_function((address) CppInterpreter::main_loop, "iT", "v");
|
||||
}
|
||||
|
||||
// Native-Java transition
|
||||
|
||||
Value* SharkBuilder::check_special_condition_for_native_trans() {
|
||||
return make_function(
|
||||
(address) JavaThread::check_special_condition_for_native_trans,
|
||||
"T", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::frame_address() {
|
||||
return make_function("llvm.frameaddress", "i", "C");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::memset() {
|
||||
// LLVM 2.8 added a fifth isVolatile field for memset
|
||||
// introduced with LLVM r100304
|
||||
return make_function("llvm.memset.p0i8.i32", "Cciii", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::unimplemented() {
|
||||
return make_function((address) report_unimplemented, "Ci", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::should_not_reach_here() {
|
||||
return make_function((address) report_should_not_reach_here, "Ci", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::dump() {
|
||||
return make_function((address) SharkRuntime::dump, "Cx", "v");
|
||||
}
|
||||
|
||||
// Public interface to low-level non-VM calls
|
||||
|
||||
CallInst* SharkBuilder::CreateGetFrameAddress() {
|
||||
return CreateCall(frame_address(), LLVMValue::jint_constant(0));
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateMemset(Value* dst,
|
||||
Value* value,
|
||||
Value* len,
|
||||
Value* align) {
|
||||
return CreateCall5(memset(), dst, value, len, align,
|
||||
LLVMValue::jint_constant(0));
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) {
|
||||
return CreateCall2(
|
||||
unimplemented(),
|
||||
CreateIntToPtr(
|
||||
LLVMValue::intptr_constant((intptr_t) file),
|
||||
PointerType::getUnqual(SharkType::jbyte_type())),
|
||||
LLVMValue::jint_constant(line));
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) {
|
||||
return CreateCall2(
|
||||
should_not_reach_here(),
|
||||
CreateIntToPtr(
|
||||
LLVMValue::intptr_constant((intptr_t) file),
|
||||
PointerType::getUnqual(SharkType::jbyte_type())),
|
||||
LLVMValue::jint_constant(line));
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
CallInst* SharkBuilder::CreateDump(Value* value) {
|
||||
const char *name;
|
||||
if (value->hasName())
|
||||
// XXX this leaks, but it's only debug code
|
||||
name = os::strdup(value->getName().str().c_str());
|
||||
else
|
||||
name = "unnamed_value";
|
||||
|
||||
if (isa<PointerType>(value->getType()))
|
||||
value = CreatePtrToInt(value, SharkType::intptr_type());
|
||||
else if (value->getType()->
|
||||
isIntegerTy()
|
||||
)
|
||||
value = CreateIntCast(value, SharkType::intptr_type(), false);
|
||||
else
|
||||
Unimplemented();
|
||||
|
||||
return CreateCall2(
|
||||
dump(),
|
||||
CreateIntToPtr(
|
||||
LLVMValue::intptr_constant((intptr_t) name),
|
||||
PointerType::getUnqual(SharkType::jbyte_type())),
|
||||
value);
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
// HotSpot memory barriers
|
||||
|
||||
void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {
|
||||
if (bs->kind() != BarrierSet::CardTableForRS &&
|
||||
bs->kind() != BarrierSet::CardTableExtension) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
CreateStore(
|
||||
LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
|
||||
CreateIntToPtr(
|
||||
CreateAdd(
|
||||
LLVMValue::intptr_constant(
|
||||
(intptr_t) (barrier_set_cast<CardTableModRefBS>(bs)->byte_map_base)),
|
||||
CreateLShr(
|
||||
CreatePtrToInt(field, SharkType::intptr_type()),
|
||||
LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),
|
||||
PointerType::getUnqual(SharkType::jbyte_type())));
|
||||
}
|
||||
|
||||
// Helpers for accessing the code buffer
|
||||
|
||||
Value* SharkBuilder::code_buffer_address(int offset) {
|
||||
return CreateAdd(
|
||||
code_buffer()->base_pc(),
|
||||
LLVMValue::intptr_constant(offset));
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) {
|
||||
return CreateLoad(
|
||||
CreateIntToPtr(
|
||||
code_buffer_address(code_buffer()->inline_oop(object)),
|
||||
PointerType::getUnqual(SharkType::oop_type())),
|
||||
name);
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) {
|
||||
assert(metadata != NULL, "inlined metadata must not be NULL");
|
||||
assert(metadata->is_metaspace_object(), "sanity check");
|
||||
return CreateLoad(
|
||||
CreateIntToPtr(
|
||||
code_buffer_address(code_buffer()->inline_Metadata(metadata)),
|
||||
PointerType::getUnqual(type)),
|
||||
name);
|
||||
}
|
||||
|
||||
Value* SharkBuilder::CreateInlineData(void* data,
|
||||
size_t size,
|
||||
Type* type,
|
||||
const char* name) {
|
||||
return CreateIntToPtr(
|
||||
code_buffer_address(code_buffer()->inline_data(data, size)),
|
||||
type,
|
||||
name);
|
||||
}
|
||||
|
||||
// Helpers for creating basic blocks.
|
||||
|
||||
BasicBlock* SharkBuilder::GetBlockInsertionPoint() const {
|
||||
BasicBlock *cur = GetInsertBlock();
|
||||
|
||||
// BasicBlock::Create takes an insertBefore argument, so
|
||||
// we need to find the block _after_ the current block
|
||||
Function::iterator iter = cur->getParent()->begin();
|
||||
Function::iterator end = cur->getParent()->end();
|
||||
while (iter != end) {
|
||||
iter++;
|
||||
if (&*iter == cur) {
|
||||
iter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter == end)
|
||||
return NULL;
|
||||
else
|
||||
return iter;
|
||||
}
|
||||
|
||||
BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const {
|
||||
return BasicBlock::Create(
|
||||
SharkContext::current(), name, GetInsertBlock()->getParent(), ip);
|
||||
}
|
||||
|
||||
LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
|
||||
return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name);
|
||||
}
|
||||
|
||||
StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
|
||||
return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name);
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKBUILDER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKBUILDER_HPP
|
||||
|
||||
#include "ci/ciType.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkCodeBuffer.hpp"
|
||||
#include "shark/sharkEntry.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/sizes.hpp"
|
||||
|
||||
class BarrierSet;
|
||||
|
||||
class SharkBuilder : public llvm::IRBuilder<> {
|
||||
friend class SharkCompileInvariants;
|
||||
|
||||
public:
|
||||
SharkBuilder(SharkCodeBuffer* code_buffer);
|
||||
|
||||
// The code buffer we are building into.
|
||||
private:
|
||||
SharkCodeBuffer* _code_buffer;
|
||||
|
||||
protected:
|
||||
SharkCodeBuffer* code_buffer() const {
|
||||
return _code_buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::LoadInst* CreateAtomicLoad(llvm::Value* ptr,
|
||||
unsigned align = HeapWordSize,
|
||||
llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent,
|
||||
llvm::SynchronizationScope synchScope = llvm::CrossThread,
|
||||
bool isVolatile = true,
|
||||
const char *name = "");
|
||||
llvm::StoreInst* CreateAtomicStore(llvm::Value *val,
|
||||
llvm::Value *ptr,
|
||||
unsigned align = HeapWordSize,
|
||||
llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent,
|
||||
llvm::SynchronizationScope SynchScope = llvm::CrossThread,
|
||||
bool isVolatile = true,
|
||||
const char *name = "");
|
||||
|
||||
// Helpers for accessing structures.
|
||||
public:
|
||||
llvm::Value* CreateAddressOfStructEntry(llvm::Value* base,
|
||||
ByteSize offset,
|
||||
llvm::Type* type,
|
||||
const char *name = "");
|
||||
llvm::LoadInst* CreateValueOfStructEntry(llvm::Value* base,
|
||||
ByteSize offset,
|
||||
llvm::Type* type,
|
||||
const char *name = "");
|
||||
|
||||
// Helpers for accessing arrays.
|
||||
public:
|
||||
llvm::LoadInst* CreateArrayLength(llvm::Value* arrayoop);
|
||||
llvm::Value* CreateArrayAddress(llvm::Value* arrayoop,
|
||||
llvm::Type* element_type,
|
||||
int element_bytes,
|
||||
ByteSize base_offset,
|
||||
llvm::Value* index,
|
||||
const char* name = "");
|
||||
llvm::Value* CreateArrayAddress(llvm::Value* arrayoop,
|
||||
BasicType basic_type,
|
||||
ByteSize base_offset,
|
||||
llvm::Value* index,
|
||||
const char* name = "");
|
||||
llvm::Value* CreateArrayAddress(llvm::Value* arrayoop,
|
||||
BasicType basic_type,
|
||||
llvm::Value* index,
|
||||
const char* name = "");
|
||||
|
||||
// Helpers for creating intrinsics and external functions.
|
||||
private:
|
||||
static llvm::Type* make_type(char type, bool void_ok);
|
||||
static llvm::FunctionType* make_ftype(const char* params,
|
||||
const char* ret);
|
||||
llvm::Value* make_function(const char* name,
|
||||
const char* params,
|
||||
const char* ret);
|
||||
llvm::Value* make_function(address func,
|
||||
const char* params,
|
||||
const char* ret);
|
||||
|
||||
// Intrinsics and external functions, part 1: VM calls.
|
||||
// These are functions declared with JRT_ENTRY and JRT_EXIT,
|
||||
// macros which flip the thread from _thread_in_Java to
|
||||
// _thread_in_vm and back. VM calls always safepoint, and can
|
||||
// therefore throw exceptions. VM calls require of setup and
|
||||
// teardown, and must be called with SharkTopLevelBlock::call_vm.
|
||||
public:
|
||||
llvm::Value* find_exception_handler();
|
||||
llvm::Value* monitorenter();
|
||||
llvm::Value* monitorexit();
|
||||
llvm::Value* new_instance();
|
||||
llvm::Value* newarray();
|
||||
llvm::Value* anewarray();
|
||||
llvm::Value* multianewarray();
|
||||
llvm::Value* register_finalizer();
|
||||
llvm::Value* safepoint();
|
||||
llvm::Value* throw_ArithmeticException();
|
||||
llvm::Value* throw_ArrayIndexOutOfBoundsException();
|
||||
llvm::Value* throw_ClassCastException();
|
||||
llvm::Value* throw_NullPointerException();
|
||||
|
||||
// Intrinsics and external functions, part 2: High-level non-VM calls.
|
||||
// These are called like normal functions. The stack is not set
|
||||
// up for walking so they must not safepoint or throw exceptions,
|
||||
// or call anything that might.
|
||||
public:
|
||||
llvm::Value* f2i();
|
||||
llvm::Value* f2l();
|
||||
llvm::Value* d2i();
|
||||
llvm::Value* d2l();
|
||||
llvm::Value* is_subtype_of();
|
||||
llvm::Value* current_time_millis();
|
||||
llvm::Value* sin();
|
||||
llvm::Value* cos();
|
||||
llvm::Value* tan();
|
||||
llvm::Value* atan2();
|
||||
llvm::Value* sqrt();
|
||||
llvm::Value* log();
|
||||
llvm::Value* log10();
|
||||
llvm::Value* pow();
|
||||
llvm::Value* exp();
|
||||
llvm::Value* fabs();
|
||||
llvm::Value* unsafe_field_offset_to_byte_offset();
|
||||
llvm::Value* osr_migration_end();
|
||||
|
||||
// Intrinsics and external functions, part 3: semi-VM calls.
|
||||
// These are special cases that do VM call stuff but are invoked
|
||||
// as though they were normal calls. This is acceptable so long
|
||||
// as the method that calls them returns to its immediately that
|
||||
// the semi VM call returns.
|
||||
public:
|
||||
llvm::Value* throw_StackOverflowError();
|
||||
llvm::Value* uncommon_trap();
|
||||
llvm::Value* deoptimized_entry_point();
|
||||
|
||||
// Intrinsics and external functions, part 4: Native-Java transition.
|
||||
// This is a special case in that it is invoked during a thread
|
||||
// state transition. The stack must be set up for walking, and it
|
||||
// may throw exceptions, but the state is _thread_in_native_trans.
|
||||
public:
|
||||
llvm::Value* check_special_condition_for_native_trans();
|
||||
|
||||
// Intrinsics and external functions, part 5: Low-level non-VM calls.
|
||||
// These have the same caveats as the high-level non-VM calls
|
||||
// above. They are not accessed directly; rather, you should
|
||||
// access them via the various Create* methods below.
|
||||
private:
|
||||
llvm::Value* cmpxchg_int();
|
||||
llvm::Value* cmpxchg_ptr();
|
||||
llvm::Value* frame_address();
|
||||
llvm::Value* memset();
|
||||
llvm::Value* unimplemented();
|
||||
llvm::Value* should_not_reach_here();
|
||||
llvm::Value* dump();
|
||||
|
||||
// Public interface to low-level non-VM calls.
|
||||
public:
|
||||
llvm::CallInst* CreateGetFrameAddress();
|
||||
llvm::CallInst* CreateMemset(llvm::Value* dst,
|
||||
llvm::Value* value,
|
||||
llvm::Value* len,
|
||||
llvm::Value* align);
|
||||
llvm::CallInst* CreateUnimplemented(const char* file, int line);
|
||||
llvm::CallInst* CreateShouldNotReachHere(const char* file, int line);
|
||||
NOT_PRODUCT(llvm::CallInst* CreateDump(llvm::Value* value));
|
||||
|
||||
// HotSpot memory barriers
|
||||
public:
|
||||
void CreateUpdateBarrierSet(BarrierSet* bs, llvm::Value* field);
|
||||
|
||||
// Helpers for accessing the code buffer.
|
||||
public:
|
||||
llvm::Value* code_buffer_address(int offset);
|
||||
llvm::Value* CreateInlineOop(jobject object, const char* name = "");
|
||||
llvm::Value* CreateInlineOop(ciObject* object, const char* name = "") {
|
||||
return CreateInlineOop(object->constant_encoding(), name);
|
||||
}
|
||||
|
||||
llvm::Value* CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name = "");
|
||||
llvm::Value* CreateInlineMetadata(ciMetadata* metadata, llvm::PointerType* type, const char* name = "") {
|
||||
return CreateInlineMetadata(metadata->constant_encoding(), type, name);
|
||||
}
|
||||
llvm::Value* CreateInlineData(void* data,
|
||||
size_t size,
|
||||
llvm::Type* type,
|
||||
const char* name = "");
|
||||
|
||||
// Helpers for creating basic blocks.
|
||||
// NB don't use unless SharkFunction::CreateBlock is unavailable.
|
||||
// XXX these are hacky and should be removed.
|
||||
public:
|
||||
llvm::BasicBlock* GetBlockInsertionPoint() const;
|
||||
llvm::BasicBlock* CreateBlock(llvm::BasicBlock* ip,
|
||||
const char* name="") const;
|
||||
};
|
||||
#endif // SHARE_VM_SHARK_SHARKBUILDER_HPP
|
@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciMethod.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkCacheDecache.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkDecacher::start_frame() {
|
||||
// Start recording the debug information
|
||||
_pc_offset = code_buffer()->create_unique_offset();
|
||||
_oopmap = new OopMap(
|
||||
oopmap_slot_munge(stack()->oopmap_frame_size()),
|
||||
oopmap_slot_munge(arg_size()));
|
||||
debug_info()->add_safepoint(pc_offset(), oopmap());
|
||||
}
|
||||
|
||||
void SharkDecacher::start_stack(int stack_depth) {
|
||||
// Create the array we'll record our stack slots in
|
||||
_exparray = new GrowableArray<ScopeValue*>(stack_depth);
|
||||
|
||||
// Set the stack pointer
|
||||
stack()->CreateStoreStackPointer(
|
||||
builder()->CreatePtrToInt(
|
||||
stack()->slot_addr(
|
||||
stack()->stack_slots_offset() + max_stack() - stack_depth),
|
||||
SharkType::intptr_type()));
|
||||
}
|
||||
|
||||
void SharkDecacher::process_stack_slot(int index,
|
||||
SharkValue** addr,
|
||||
int offset) {
|
||||
SharkValue *value = *addr;
|
||||
|
||||
// Write the value to the frame if necessary
|
||||
if (stack_slot_needs_write(index, value)) {
|
||||
write_value_to_frame(
|
||||
SharkType::to_stackType(value->basic_type()),
|
||||
value->generic_value(),
|
||||
adjusted_offset(value, offset));
|
||||
}
|
||||
|
||||
// Record the value in the oopmap if necessary
|
||||
if (stack_slot_needs_oopmap(index, value)) {
|
||||
oopmap()->set_oop(slot2reg(offset));
|
||||
}
|
||||
|
||||
// Record the value in the debuginfo if necessary
|
||||
if (stack_slot_needs_debuginfo(index, value)) {
|
||||
exparray()->append(slot2lv(offset, stack_location_type(index, addr)));
|
||||
}
|
||||
}
|
||||
|
||||
void SharkDecacher::start_monitors(int num_monitors) {
|
||||
// Create the array we'll record our monitors in
|
||||
_monarray = new GrowableArray<MonitorValue*>(num_monitors);
|
||||
}
|
||||
|
||||
void SharkDecacher::process_monitor(int index, int box_offset, int obj_offset) {
|
||||
oopmap()->set_oop(slot2reg(obj_offset));
|
||||
|
||||
monarray()->append(new MonitorValue(
|
||||
slot2lv (obj_offset, Location::oop),
|
||||
slot2loc(box_offset, Location::normal)));
|
||||
}
|
||||
|
||||
void SharkDecacher::process_oop_tmp_slot(Value** value, int offset) {
|
||||
// Decache the temporary oop slot
|
||||
if (*value) {
|
||||
write_value_to_frame(
|
||||
SharkType::oop_type(),
|
||||
*value,
|
||||
offset);
|
||||
|
||||
oopmap()->set_oop(slot2reg(offset));
|
||||
}
|
||||
}
|
||||
|
||||
void SharkDecacher::process_method_slot(Value** value, int offset) {
|
||||
// Decache the method pointer
|
||||
write_value_to_frame(
|
||||
SharkType::Method_type(),
|
||||
*value,
|
||||
offset);
|
||||
|
||||
}
|
||||
|
||||
void SharkDecacher::process_pc_slot(int offset) {
|
||||
// Record the PC
|
||||
builder()->CreateStore(
|
||||
builder()->code_buffer_address(pc_offset()),
|
||||
stack()->slot_addr(offset));
|
||||
}
|
||||
|
||||
void SharkDecacher::start_locals() {
|
||||
// Create the array we'll record our local variables in
|
||||
_locarray = new GrowableArray<ScopeValue*>(max_locals());}
|
||||
|
||||
void SharkDecacher::process_local_slot(int index,
|
||||
SharkValue** addr,
|
||||
int offset) {
|
||||
SharkValue *value = *addr;
|
||||
|
||||
// Write the value to the frame if necessary
|
||||
if (local_slot_needs_write(index, value)) {
|
||||
write_value_to_frame(
|
||||
SharkType::to_stackType(value->basic_type()),
|
||||
value->generic_value(),
|
||||
adjusted_offset(value, offset));
|
||||
}
|
||||
|
||||
// Record the value in the oopmap if necessary
|
||||
if (local_slot_needs_oopmap(index, value)) {
|
||||
oopmap()->set_oop(slot2reg(offset));
|
||||
}
|
||||
|
||||
// Record the value in the debuginfo if necessary
|
||||
if (local_slot_needs_debuginfo(index, value)) {
|
||||
locarray()->append(slot2lv(offset, local_location_type(index, addr)));
|
||||
}
|
||||
}
|
||||
|
||||
void SharkDecacher::end_frame() {
|
||||
// Record the scope
|
||||
methodHandle null_mh;
|
||||
debug_info()->describe_scope(
|
||||
pc_offset(),
|
||||
null_mh,
|
||||
target(),
|
||||
bci(),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
debug_info()->create_scope_values(locarray()),
|
||||
debug_info()->create_scope_values(exparray()),
|
||||
debug_info()->create_monitor_values(monarray()));
|
||||
|
||||
// Finish recording the debug information
|
||||
debug_info()->end_safepoint(pc_offset());
|
||||
}
|
||||
|
||||
void SharkCacher::process_stack_slot(int index,
|
||||
SharkValue** addr,
|
||||
int offset) {
|
||||
SharkValue *value = *addr;
|
||||
|
||||
// Read the value from the frame if necessary
|
||||
if (stack_slot_needs_read(index, value)) {
|
||||
*addr = SharkValue::create_generic(
|
||||
value->type(),
|
||||
read_value_from_frame(
|
||||
SharkType::to_stackType(value->basic_type()),
|
||||
adjusted_offset(value, offset)),
|
||||
value->zero_checked());
|
||||
}
|
||||
}
|
||||
|
||||
void SharkOSREntryCacher::process_monitor(int index,
|
||||
int box_offset,
|
||||
int obj_offset) {
|
||||
// Copy the monitor from the OSR buffer to the frame
|
||||
int src_offset = max_locals() + index * 2;
|
||||
builder()->CreateStore(
|
||||
builder()->CreateLoad(
|
||||
CreateAddressOfOSRBufEntry(src_offset, SharkType::intptr_type())),
|
||||
stack()->slot_addr(box_offset, SharkType::intptr_type()));
|
||||
builder()->CreateStore(
|
||||
builder()->CreateLoad(
|
||||
CreateAddressOfOSRBufEntry(src_offset + 1, SharkType::oop_type())),
|
||||
stack()->slot_addr(obj_offset, SharkType::oop_type()));
|
||||
}
|
||||
|
||||
void SharkCacher::process_oop_tmp_slot(Value** value, int offset) {
|
||||
// Cache the temporary oop
|
||||
if (*value)
|
||||
*value = read_value_from_frame(SharkType::oop_type(), offset);
|
||||
}
|
||||
|
||||
void SharkCacher::process_method_slot(Value** value, int offset) {
|
||||
// Cache the method pointer
|
||||
*value = read_value_from_frame(SharkType::Method_type(), offset);
|
||||
}
|
||||
|
||||
void SharkFunctionEntryCacher::process_method_slot(Value** value, int offset) {
|
||||
// "Cache" the method pointer
|
||||
*value = method();
|
||||
}
|
||||
|
||||
void SharkCacher::process_local_slot(int index,
|
||||
SharkValue** addr,
|
||||
int offset) {
|
||||
SharkValue *value = *addr;
|
||||
|
||||
// Read the value from the frame if necessary
|
||||
if (local_slot_needs_read(index, value)) {
|
||||
*addr = SharkValue::create_generic(
|
||||
value->type(),
|
||||
read_value_from_frame(
|
||||
SharkType::to_stackType(value->basic_type()),
|
||||
adjusted_offset(value, offset)),
|
||||
value->zero_checked());
|
||||
}
|
||||
}
|
||||
|
||||
Value* SharkOSREntryCacher::CreateAddressOfOSRBufEntry(int offset,
|
||||
Type* type) {
|
||||
Value *result = builder()->CreateStructGEP(osr_buf(), offset);
|
||||
if (type != SharkType::intptr_type())
|
||||
result = builder()->CreateBitCast(result, PointerType::getUnqual(type));
|
||||
return result;
|
||||
}
|
||||
|
||||
void SharkOSREntryCacher::process_local_slot(int index,
|
||||
SharkValue** addr,
|
||||
int offset) {
|
||||
SharkValue *value = *addr;
|
||||
|
||||
// Read the value from the OSR buffer if necessary
|
||||
if (local_slot_needs_read(index, value)) {
|
||||
*addr = SharkValue::create_generic(
|
||||
value->type(),
|
||||
builder()->CreateLoad(
|
||||
CreateAddressOfOSRBufEntry(
|
||||
adjusted_offset(value, max_locals() - 1 - index),
|
||||
SharkType::to_stackType(value->basic_type()))),
|
||||
value->zero_checked());
|
||||
}
|
||||
}
|
||||
|
||||
void SharkDecacher::write_value_to_frame(Type* type,
|
||||
Value* value,
|
||||
int offset) {
|
||||
builder()->CreateStore(value, stack()->slot_addr(offset, type));
|
||||
}
|
||||
|
||||
Value* SharkCacher::read_value_from_frame(Type* type, int offset) {
|
||||
return builder()->CreateLoad(stack()->slot_addr(offset, type));
|
||||
}
|
@ -1,428 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKCACHEDECACHE_HPP
|
||||
#define SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkStateScanner.hpp"
|
||||
|
||||
// Class hierarchy:
|
||||
// - SharkStateScanner
|
||||
// - SharkCacherDecacher
|
||||
// - SharkDecacher
|
||||
// - SharkJavaCallDecacher
|
||||
// - SharkVMCallDecacher
|
||||
// - SharkTrapDecacher
|
||||
// - SharkCacher
|
||||
// - SharkJavaCallCacher
|
||||
// - SharkVMCallCacher
|
||||
// - SharkFunctionEntryCacher
|
||||
// - SharkNormalEntryCacher
|
||||
// - SharkOSREntryCacher
|
||||
|
||||
class SharkCacherDecacher : public SharkStateScanner {
|
||||
protected:
|
||||
SharkCacherDecacher(SharkFunction* function)
|
||||
: SharkStateScanner(function) {}
|
||||
|
||||
// Helper
|
||||
protected:
|
||||
static int adjusted_offset(SharkValue* value, int offset) {
|
||||
if (value->is_two_word())
|
||||
offset--;
|
||||
return offset;
|
||||
}
|
||||
};
|
||||
|
||||
class SharkDecacher : public SharkCacherDecacher {
|
||||
protected:
|
||||
SharkDecacher(SharkFunction* function, int bci)
|
||||
: SharkCacherDecacher(function), _bci(bci) {}
|
||||
|
||||
private:
|
||||
int _bci;
|
||||
|
||||
protected:
|
||||
int bci() const {
|
||||
return _bci;
|
||||
}
|
||||
|
||||
private:
|
||||
int _pc_offset;
|
||||
OopMap* _oopmap;
|
||||
GrowableArray<ScopeValue*>* _exparray;
|
||||
GrowableArray<MonitorValue*>* _monarray;
|
||||
GrowableArray<ScopeValue*>* _locarray;
|
||||
|
||||
private:
|
||||
int pc_offset() const {
|
||||
return _pc_offset;
|
||||
}
|
||||
OopMap* oopmap() const {
|
||||
return _oopmap;
|
||||
}
|
||||
GrowableArray<ScopeValue*>* exparray() const {
|
||||
return _exparray;
|
||||
}
|
||||
GrowableArray<MonitorValue*>* monarray() const {
|
||||
return _monarray;
|
||||
}
|
||||
GrowableArray<ScopeValue*>* locarray() const {
|
||||
return _locarray;
|
||||
}
|
||||
|
||||
// Callbacks
|
||||
protected:
|
||||
void start_frame();
|
||||
|
||||
void start_stack(int stack_depth);
|
||||
void process_stack_slot(int index, SharkValue** value, int offset);
|
||||
|
||||
void start_monitors(int num_monitors);
|
||||
void process_monitor(int index, int box_offset, int obj_offset);
|
||||
|
||||
void process_oop_tmp_slot(llvm::Value** value, int offset);
|
||||
void process_method_slot(llvm::Value** value, int offset);
|
||||
void process_pc_slot(int offset);
|
||||
|
||||
void start_locals();
|
||||
void process_local_slot(int index, SharkValue** value, int offset);
|
||||
|
||||
void end_frame();
|
||||
|
||||
// oopmap and debuginfo helpers
|
||||
private:
|
||||
static int oopmap_slot_munge(int offset) {
|
||||
return SharkStack::oopmap_slot_munge(offset);
|
||||
}
|
||||
static VMReg slot2reg(int offset) {
|
||||
return SharkStack::slot2reg(offset);
|
||||
}
|
||||
static Location slot2loc(int offset, Location::Type type) {
|
||||
return Location::new_stk_loc(type, offset * wordSize);
|
||||
}
|
||||
static LocationValue* slot2lv(int offset, Location::Type type) {
|
||||
return new LocationValue(slot2loc(offset, type));
|
||||
}
|
||||
static Location::Type location_type(SharkValue** addr, bool maybe_two_word) {
|
||||
// low addresses this end
|
||||
// Type 32-bit 64-bit
|
||||
// ----------------------------------------------------
|
||||
// stack[0] local[3] jobject oop oop
|
||||
// stack[1] local[2] NULL normal lng
|
||||
// stack[2] local[1] jlong normal invalid
|
||||
// stack[3] local[0] jint normal normal
|
||||
//
|
||||
// high addresses this end
|
||||
|
||||
SharkValue *value = *addr;
|
||||
if (value) {
|
||||
if (value->is_jobject())
|
||||
return Location::oop;
|
||||
#ifdef _LP64
|
||||
if (value->is_two_word())
|
||||
return Location::invalid;
|
||||
#endif // _LP64
|
||||
return Location::normal;
|
||||
}
|
||||
else {
|
||||
if (maybe_two_word) {
|
||||
value = *(addr - 1);
|
||||
if (value && value->is_two_word()) {
|
||||
#ifdef _LP64
|
||||
if (value->is_jlong())
|
||||
return Location::lng;
|
||||
if (value->is_jdouble())
|
||||
return Location::dbl;
|
||||
ShouldNotReachHere();
|
||||
#else
|
||||
return Location::normal;
|
||||
#endif // _LP64
|
||||
}
|
||||
}
|
||||
return Location::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Stack slot helpers
|
||||
protected:
|
||||
virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0;
|
||||
virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
||||
virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
||||
|
||||
static Location::Type stack_location_type(int index, SharkValue** addr) {
|
||||
return location_type(addr, *addr == NULL);
|
||||
}
|
||||
|
||||
// Local slot helpers
|
||||
protected:
|
||||
virtual bool local_slot_needs_write(int index, SharkValue* value) = 0;
|
||||
virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
||||
virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
||||
|
||||
static Location::Type local_location_type(int index, SharkValue** addr) {
|
||||
return location_type(addr, index > 0);
|
||||
}
|
||||
|
||||
// Writer helper
|
||||
protected:
|
||||
void write_value_to_frame(llvm::Type* type,
|
||||
llvm::Value* value,
|
||||
int offset);
|
||||
};
|
||||
|
||||
class SharkJavaCallDecacher : public SharkDecacher {
|
||||
public:
|
||||
SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee)
|
||||
: SharkDecacher(function, bci), _callee(callee) {}
|
||||
|
||||
private:
|
||||
ciMethod* _callee;
|
||||
|
||||
protected:
|
||||
ciMethod* callee() const {
|
||||
return _callee;
|
||||
}
|
||||
|
||||
// Stack slot helpers
|
||||
protected:
|
||||
bool stack_slot_needs_write(int index, SharkValue* value) {
|
||||
return value && (index < callee()->arg_size() || value->is_jobject());
|
||||
}
|
||||
bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject() && index >= callee()->arg_size();
|
||||
}
|
||||
bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return index >= callee()->arg_size();
|
||||
}
|
||||
|
||||
// Local slot helpers
|
||||
protected:
|
||||
bool local_slot_needs_write(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SharkVMCallDecacher : public SharkDecacher {
|
||||
public:
|
||||
SharkVMCallDecacher(SharkFunction* function, int bci)
|
||||
: SharkDecacher(function, bci) {}
|
||||
|
||||
// Stack slot helpers
|
||||
protected:
|
||||
bool stack_slot_needs_write(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Local slot helpers
|
||||
protected:
|
||||
bool local_slot_needs_write(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SharkTrapDecacher : public SharkDecacher {
|
||||
public:
|
||||
SharkTrapDecacher(SharkFunction* function, int bci)
|
||||
: SharkDecacher(function, bci) {}
|
||||
|
||||
// Stack slot helpers
|
||||
protected:
|
||||
bool stack_slot_needs_write(int index, SharkValue* value) {
|
||||
return value != NULL;
|
||||
}
|
||||
bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Local slot helpers
|
||||
protected:
|
||||
bool local_slot_needs_write(int index, SharkValue* value) {
|
||||
return value != NULL;
|
||||
}
|
||||
bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SharkCacher : public SharkCacherDecacher {
|
||||
protected:
|
||||
SharkCacher(SharkFunction* function)
|
||||
: SharkCacherDecacher(function) {}
|
||||
|
||||
// Callbacks
|
||||
protected:
|
||||
void process_stack_slot(int index, SharkValue** value, int offset);
|
||||
|
||||
void process_oop_tmp_slot(llvm::Value** value, int offset);
|
||||
virtual void process_method_slot(llvm::Value** value, int offset);
|
||||
|
||||
virtual void process_local_slot(int index, SharkValue** value, int offset);
|
||||
|
||||
// Stack slot helper
|
||||
protected:
|
||||
virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0;
|
||||
|
||||
// Local slot helper
|
||||
protected:
|
||||
virtual bool local_slot_needs_read(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
|
||||
// Writer helper
|
||||
protected:
|
||||
llvm::Value* read_value_from_frame(llvm::Type* type, int offset);
|
||||
};
|
||||
|
||||
class SharkJavaCallCacher : public SharkCacher {
|
||||
public:
|
||||
SharkJavaCallCacher(SharkFunction* function, ciMethod* callee)
|
||||
: SharkCacher(function), _callee(callee) {}
|
||||
|
||||
private:
|
||||
ciMethod* _callee;
|
||||
|
||||
protected:
|
||||
ciMethod* callee() const {
|
||||
return _callee;
|
||||
}
|
||||
|
||||
// Stack slot helper
|
||||
protected:
|
||||
bool stack_slot_needs_read(int index, SharkValue* value) {
|
||||
return value && (index < callee()->return_type()->size() ||
|
||||
value->is_jobject());
|
||||
}
|
||||
};
|
||||
|
||||
class SharkVMCallCacher : public SharkCacher {
|
||||
public:
|
||||
SharkVMCallCacher(SharkFunction* function)
|
||||
: SharkCacher(function) {}
|
||||
|
||||
// Stack slot helper
|
||||
protected:
|
||||
bool stack_slot_needs_read(int index, SharkValue* value) {
|
||||
return value && value->is_jobject();
|
||||
}
|
||||
};
|
||||
|
||||
class SharkFunctionEntryCacher : public SharkCacher {
|
||||
public:
|
||||
SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method)
|
||||
: SharkCacher(function), _method(method) {}
|
||||
|
||||
private:
|
||||
llvm::Value* _method;
|
||||
|
||||
private:
|
||||
llvm::Value* method() const {
|
||||
return _method;
|
||||
}
|
||||
|
||||
// Method slot callback
|
||||
protected:
|
||||
void process_method_slot(llvm::Value** value, int offset);
|
||||
|
||||
// Stack slot helper
|
||||
protected:
|
||||
bool stack_slot_needs_read(int index, SharkValue* value) {
|
||||
ShouldNotReachHere(); // entry block shouldn't have stack
|
||||
}
|
||||
|
||||
// Local slot helper
|
||||
protected:
|
||||
bool local_slot_needs_read(int index, SharkValue* value) {
|
||||
return value != NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class SharkNormalEntryCacher : public SharkFunctionEntryCacher {
|
||||
public:
|
||||
SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method)
|
||||
: SharkFunctionEntryCacher(function, method) {}
|
||||
};
|
||||
|
||||
class SharkOSREntryCacher : public SharkFunctionEntryCacher {
|
||||
public:
|
||||
SharkOSREntryCacher(SharkFunction* function,
|
||||
llvm::Value* method,
|
||||
llvm::Value* osr_buf)
|
||||
: SharkFunctionEntryCacher(function, method),
|
||||
_osr_buf(
|
||||
builder()->CreateBitCast(
|
||||
osr_buf,
|
||||
llvm::PointerType::getUnqual(
|
||||
llvm::ArrayType::get(
|
||||
SharkType::intptr_type(),
|
||||
max_locals() + max_monitors() * 2)))) {}
|
||||
|
||||
private:
|
||||
llvm::Value* _osr_buf;
|
||||
|
||||
private:
|
||||
llvm::Value* osr_buf() const {
|
||||
return _osr_buf;
|
||||
}
|
||||
|
||||
// Callbacks
|
||||
protected:
|
||||
void process_monitor(int index, int box_offset, int obj_offset);
|
||||
void process_local_slot(int index, SharkValue** value, int offset);
|
||||
|
||||
// Helper
|
||||
private:
|
||||
llvm::Value* CreateAddressOfOSRBufEntry(int offset, llvm::Type* type);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKCODEBUFFER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKCODEBUFFER_HPP
|
||||
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
|
||||
class SharkCodeBuffer : public StackObj {
|
||||
public:
|
||||
SharkCodeBuffer(MacroAssembler* masm)
|
||||
: _masm(masm), _base_pc(NULL) {}
|
||||
|
||||
private:
|
||||
MacroAssembler* _masm;
|
||||
llvm::Value* _base_pc;
|
||||
|
||||
private:
|
||||
MacroAssembler* masm() const {
|
||||
return _masm;
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::Value* base_pc() const {
|
||||
return _base_pc;
|
||||
}
|
||||
void set_base_pc(llvm::Value* base_pc) {
|
||||
assert(_base_pc == NULL, "only do this once");
|
||||
_base_pc = base_pc;
|
||||
}
|
||||
|
||||
// Allocate some space in the buffer and return its address.
|
||||
// This buffer will have been relocated by the time the method
|
||||
// is installed, so you can't inline the result in code.
|
||||
public:
|
||||
void* malloc(size_t size) const {
|
||||
masm()->align(BytesPerWord);
|
||||
void *result = masm()->pc();
|
||||
masm()->advance(size);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Create a unique offset in the buffer.
|
||||
public:
|
||||
int create_unique_offset() const {
|
||||
int offset = masm()->offset();
|
||||
masm()->advance(1);
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Inline an oop into the buffer and return its offset.
|
||||
public:
|
||||
int inline_oop(jobject object) const {
|
||||
masm()->align(BytesPerWord);
|
||||
int offset = masm()->offset();
|
||||
masm()->store_oop(object);
|
||||
return offset;
|
||||
}
|
||||
|
||||
int inline_Metadata(Metadata* metadata) const {
|
||||
masm()->align(BytesPerWord);
|
||||
int offset = masm()->offset();
|
||||
masm()->store_Metadata(metadata);
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Inline a block of non-oop data into the buffer and return its offset.
|
||||
public:
|
||||
int inline_data(void *src, size_t size) const {
|
||||
masm()->align(BytesPerWord);
|
||||
int offset = masm()->offset();
|
||||
void *dst = masm()->pc();
|
||||
masm()->advance(size);
|
||||
memcpy(dst, src, size);
|
||||
return offset;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKCODEBUFFER_HPP
|
@ -1,372 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciEnv.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "code/dependencies.hpp"
|
||||
#include "code/exceptionHandlerTable.hpp"
|
||||
#include "code/oopRecorder.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkCodeBuffer.hpp"
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "shark/sharkEntry.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkMemoryManager.hpp"
|
||||
#include "shark/sharkNativeWrapper.hpp"
|
||||
#include "shark/shark_globals.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
cl::opt<std::string>
|
||||
MCPU("mcpu");
|
||||
|
||||
cl::list<std::string>
|
||||
MAttrs("mattr",
|
||||
cl::CommaSeparated);
|
||||
}
|
||||
|
||||
SharkCompiler::SharkCompiler()
|
||||
: AbstractCompiler(shark) {
|
||||
// Create the lock to protect the memory manager and execution engine
|
||||
_execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock");
|
||||
MutexLocker locker(execution_engine_lock());
|
||||
|
||||
// Make LLVM safe for multithreading
|
||||
if (!llvm_start_multithreaded())
|
||||
fatal("llvm_start_multithreaded() failed");
|
||||
|
||||
// Initialize the native target
|
||||
InitializeNativeTarget();
|
||||
|
||||
// MCJIT require a native AsmPrinter
|
||||
InitializeNativeTargetAsmPrinter();
|
||||
|
||||
// Create the two contexts which we'll use
|
||||
_normal_context = new SharkContext("normal");
|
||||
_native_context = new SharkContext("native");
|
||||
|
||||
// Create the memory manager
|
||||
_memory_manager = new SharkMemoryManager();
|
||||
|
||||
// Finetune LLVM for the current host CPU.
|
||||
StringMap<bool> Features;
|
||||
bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features);
|
||||
std::string cpu("-mcpu=" + llvm::sys::getHostCPUName());
|
||||
|
||||
std::vector<const char*> args;
|
||||
args.push_back(""); // program name
|
||||
args.push_back(cpu.c_str());
|
||||
|
||||
std::string mattr("-mattr=");
|
||||
if(gotCpuFeatures){
|
||||
for(StringMap<bool>::iterator I = Features.begin(),
|
||||
E = Features.end(); I != E; ++I){
|
||||
if(I->second){
|
||||
std::string attr(I->first());
|
||||
mattr+="+"+attr+",";
|
||||
}
|
||||
}
|
||||
args.push_back(mattr.c_str());
|
||||
}
|
||||
|
||||
args.push_back(0); // terminator
|
||||
cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
|
||||
|
||||
// Create the JIT
|
||||
std::string ErrorMsg;
|
||||
|
||||
EngineBuilder builder(_normal_context->module());
|
||||
builder.setMCPU(MCPU);
|
||||
builder.setMAttrs(MAttrs);
|
||||
builder.setJITMemoryManager(memory_manager());
|
||||
builder.setEngineKind(EngineKind::JIT);
|
||||
builder.setErrorStr(&ErrorMsg);
|
||||
if (! fnmatch(SharkOptimizationLevel, "None", 0)) {
|
||||
tty->print_cr("Shark optimization level set to: None");
|
||||
builder.setOptLevel(llvm::CodeGenOpt::None);
|
||||
} else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) {
|
||||
tty->print_cr("Shark optimization level set to: Less");
|
||||
builder.setOptLevel(llvm::CodeGenOpt::Less);
|
||||
} else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) {
|
||||
tty->print_cr("Shark optimization level set to: Aggressive");
|
||||
builder.setOptLevel(llvm::CodeGenOpt::Aggressive);
|
||||
} // else Default is selected by, well, default :-)
|
||||
_execution_engine = builder.create();
|
||||
|
||||
if (!execution_engine()) {
|
||||
if (!ErrorMsg.empty())
|
||||
printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str());
|
||||
else
|
||||
printf("Unknown error while creating Shark JIT\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
execution_engine()->addModule(_native_context->module());
|
||||
|
||||
// All done
|
||||
set_state(initialized);
|
||||
}
|
||||
|
||||
void SharkCompiler::initialize() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void SharkCompiler::compile_method(ciEnv* env,
|
||||
ciMethod* target,
|
||||
int entry_bci,
|
||||
DirectiveSet* directive) {
|
||||
assert(is_initialized(), "should be");
|
||||
ResourceMark rm;
|
||||
const char *name = methodname(
|
||||
target->holder()->name()->as_utf8(), target->name()->as_utf8());
|
||||
|
||||
// Do the typeflow analysis
|
||||
ciTypeFlow *flow;
|
||||
if (entry_bci == InvocationEntryBci)
|
||||
flow = target->get_flow_analysis();
|
||||
else
|
||||
flow = target->get_osr_flow_analysis(entry_bci);
|
||||
if (flow->failing())
|
||||
return;
|
||||
if (SharkPrintTypeflowOf != NULL) {
|
||||
if (!fnmatch(SharkPrintTypeflowOf, name, 0))
|
||||
flow->print_on(tty);
|
||||
}
|
||||
|
||||
// Create the recorders
|
||||
Arena arena;
|
||||
env->set_oop_recorder(new OopRecorder(&arena));
|
||||
OopMapSet oopmaps;
|
||||
env->set_debug_info(new DebugInformationRecorder(env->oop_recorder()));
|
||||
env->debug_info()->set_oopmaps(&oopmaps);
|
||||
env->set_dependencies(new Dependencies(env));
|
||||
|
||||
// Create the code buffer and builder
|
||||
CodeBuffer hscb("Shark", 256 * K, 64 * K);
|
||||
hscb.initialize_oop_recorder(env->oop_recorder());
|
||||
MacroAssembler *masm = new MacroAssembler(&hscb);
|
||||
SharkCodeBuffer cb(masm);
|
||||
SharkBuilder builder(&cb);
|
||||
|
||||
// Emit the entry point
|
||||
SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
|
||||
|
||||
// Build the LLVM IR for the method
|
||||
Function *function = SharkFunction::build(env, &builder, flow, name);
|
||||
if (env->failing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate native code. It's unpleasant that we have to drop into
|
||||
// the VM to do this -- it blocks safepoints -- but I can't see any
|
||||
// other way to handle the locking.
|
||||
{
|
||||
ThreadInVMfromNative tiv(JavaThread::current());
|
||||
generate_native_code(entry, function, name);
|
||||
}
|
||||
|
||||
// Install the method into the VM
|
||||
CodeOffsets offsets;
|
||||
offsets.set_value(CodeOffsets::Deopt, 0);
|
||||
offsets.set_value(CodeOffsets::Exceptions, 0);
|
||||
offsets.set_value(CodeOffsets::Verified_Entry,
|
||||
target->is_static() ? 0 : wordSize);
|
||||
|
||||
ExceptionHandlerTable handler_table;
|
||||
ImplicitExceptionTable inc_table;
|
||||
|
||||
env->register_method(target,
|
||||
entry_bci,
|
||||
&offsets,
|
||||
0,
|
||||
&hscb,
|
||||
0,
|
||||
&oopmaps,
|
||||
&handler_table,
|
||||
&inc_table,
|
||||
this,
|
||||
false,
|
||||
directive(),
|
||||
false);
|
||||
}
|
||||
|
||||
nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,
|
||||
const methodHandle& target,
|
||||
int compile_id,
|
||||
BasicType* arg_types,
|
||||
BasicType return_type) {
|
||||
assert(is_initialized(), "should be");
|
||||
ResourceMark rm;
|
||||
const char *name = methodname(
|
||||
target->klass_name()->as_utf8(), target->name()->as_utf8());
|
||||
|
||||
// Create the code buffer and builder
|
||||
SharkCodeBuffer cb(masm);
|
||||
SharkBuilder builder(&cb);
|
||||
|
||||
// Emit the entry point
|
||||
SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
|
||||
|
||||
// Build the LLVM IR for the method
|
||||
SharkNativeWrapper *wrapper = SharkNativeWrapper::build(
|
||||
&builder, target, name, arg_types, return_type);
|
||||
|
||||
// Generate native code
|
||||
generate_native_code(entry, wrapper->function(), name);
|
||||
|
||||
// Return the nmethod for installation in the VM
|
||||
return nmethod::new_native_nmethod(target,
|
||||
compile_id,
|
||||
masm->code(),
|
||||
0,
|
||||
0,
|
||||
wrapper->frame_size(),
|
||||
wrapper->receiver_offset(),
|
||||
wrapper->lock_offset(),
|
||||
wrapper->oop_maps());
|
||||
}
|
||||
|
||||
void SharkCompiler::generate_native_code(SharkEntry* entry,
|
||||
Function* function,
|
||||
const char* name) {
|
||||
// Print the LLVM bitcode, if requested
|
||||
if (SharkPrintBitcodeOf != NULL) {
|
||||
if (!fnmatch(SharkPrintBitcodeOf, name, 0))
|
||||
function->dump();
|
||||
}
|
||||
|
||||
if (SharkVerifyFunction != NULL) {
|
||||
if (!fnmatch(SharkVerifyFunction, name, 0)) {
|
||||
verifyFunction(*function);
|
||||
}
|
||||
}
|
||||
|
||||
// Compile to native code
|
||||
address code = NULL;
|
||||
context()->add_function(function);
|
||||
{
|
||||
MutexLocker locker(execution_engine_lock());
|
||||
free_queued_methods();
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if SHARK_LLVM_VERSION <= 31
|
||||
#define setCurrentDebugType SetCurrentDebugType
|
||||
#endif
|
||||
if (SharkPrintAsmOf != NULL) {
|
||||
if (!fnmatch(SharkPrintAsmOf, name, 0)) {
|
||||
llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
|
||||
llvm::DebugFlag = true;
|
||||
}
|
||||
else {
|
||||
llvm::setCurrentDebugType("");
|
||||
llvm::DebugFlag = false;
|
||||
}
|
||||
}
|
||||
#ifdef setCurrentDebugType
|
||||
#undef setCurrentDebugType
|
||||
#endif
|
||||
#endif // !NDEBUG
|
||||
memory_manager()->set_entry_for_function(function, entry);
|
||||
code = (address) execution_engine()->getPointerToFunction(function);
|
||||
}
|
||||
assert(code != NULL, "code must be != NULL");
|
||||
entry->set_entry_point(code);
|
||||
entry->set_function(function);
|
||||
entry->set_context(context());
|
||||
address code_start = entry->code_start();
|
||||
address code_limit = entry->code_limit();
|
||||
|
||||
// Register generated code for profiling, etc
|
||||
if (JvmtiExport::should_post_dynamic_code_generated())
|
||||
JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit);
|
||||
|
||||
// Print debug information, if requested
|
||||
if (SharkTraceInstalls) {
|
||||
tty->print_cr(
|
||||
" [%p-%p): %s (%d bytes code)",
|
||||
code_start, code_limit, name, code_limit - code_start);
|
||||
}
|
||||
}
|
||||
|
||||
void SharkCompiler::free_compiled_method(address code) {
|
||||
// This method may only be called when the VM is at a safepoint.
|
||||
// All _thread_in_vm threads will be waiting for the safepoint to
|
||||
// finish with the exception of the VM thread, so we can consider
|
||||
// ourself the owner of the execution engine lock even though we
|
||||
// can't actually acquire it at this time.
|
||||
assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
SharkEntry *entry = (SharkEntry *) code;
|
||||
entry->context()->push_to_free_queue(entry->function());
|
||||
}
|
||||
|
||||
void SharkCompiler::free_queued_methods() {
|
||||
// The free queue is protected by the execution engine lock
|
||||
assert(execution_engine_lock()->owned_by_self(), "should be");
|
||||
|
||||
while (true) {
|
||||
Function *function = context()->pop_from_free_queue();
|
||||
if (function == NULL)
|
||||
break;
|
||||
|
||||
execution_engine()->freeMachineCodeForFunction(function);
|
||||
function->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
const char* SharkCompiler::methodname(const char* klass, const char* method) {
|
||||
char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1);
|
||||
|
||||
char *dst = buf;
|
||||
for (const char *c = klass; *c; c++) {
|
||||
if (*c == '/')
|
||||
*(dst++) = '.';
|
||||
else
|
||||
*(dst++) = *c;
|
||||
}
|
||||
*(dst++) = ':';
|
||||
*(dst++) = ':';
|
||||
for (const char *c = method; *c; c++) {
|
||||
*(dst++) = *c;
|
||||
}
|
||||
*(dst++) = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
void SharkCompiler::print_timers() {
|
||||
// do nothing
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKCOMPILER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKCOMPILER_HPP
|
||||
|
||||
#include "ci/ciEnv.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkMemoryManager.hpp"
|
||||
|
||||
class SharkContext;
|
||||
|
||||
class SharkCompiler : public AbstractCompiler {
|
||||
public:
|
||||
// Creation
|
||||
SharkCompiler();
|
||||
|
||||
// Name of this compiler
|
||||
const char *name() { return "shark"; }
|
||||
|
||||
// Missing feature tests
|
||||
bool supports_native() { return true; }
|
||||
bool supports_osr() { return true; }
|
||||
bool can_compile_method(const methodHandle& method) {
|
||||
return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form());
|
||||
}
|
||||
|
||||
// Initialization
|
||||
void initialize();
|
||||
|
||||
// Compile a normal (bytecode) method and install it in the VM
|
||||
void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* dirset);
|
||||
|
||||
// Print compilation timers and statistics
|
||||
void print_timers();
|
||||
|
||||
// Generate a wrapper for a native (JNI) method
|
||||
nmethod* generate_native_wrapper(MacroAssembler* masm,
|
||||
const methodHandle& target,
|
||||
int compile_id,
|
||||
BasicType* arg_types,
|
||||
BasicType return_type);
|
||||
|
||||
// Free compiled methods (and native wrappers)
|
||||
void free_compiled_method(address code);
|
||||
|
||||
// Each thread generating IR needs its own context. The normal
|
||||
// context is used for bytecode methods, and is protected from
|
||||
// multiple simultaneous accesses by being restricted to the
|
||||
// compiler thread. The native context is used for JNI methods,
|
||||
// and is protected from multiple simultaneous accesses by the
|
||||
// adapter handler library lock.
|
||||
private:
|
||||
SharkContext* _normal_context;
|
||||
SharkContext* _native_context;
|
||||
|
||||
public:
|
||||
SharkContext* context() const {
|
||||
if (JavaThread::current()->is_Compiler_thread()) {
|
||||
return _normal_context;
|
||||
}
|
||||
else {
|
||||
assert(AdapterHandlerLibrary_lock->owned_by_self(), "should be");
|
||||
return _native_context;
|
||||
}
|
||||
}
|
||||
|
||||
// The LLVM execution engine is the JIT we use to generate native
|
||||
// code. It is thread safe, but we need to protect it with a lock
|
||||
// of our own because otherwise LLVM's lock and HotSpot's locks
|
||||
// interleave and deadlock. The SharkMemoryManager is not thread
|
||||
// safe, and is protected by the same lock as the execution engine.
|
||||
private:
|
||||
Monitor* _execution_engine_lock;
|
||||
SharkMemoryManager* _memory_manager;
|
||||
llvm::ExecutionEngine* _execution_engine;
|
||||
|
||||
private:
|
||||
Monitor* execution_engine_lock() const {
|
||||
return _execution_engine_lock;
|
||||
}
|
||||
SharkMemoryManager* memory_manager() const {
|
||||
assert(execution_engine_lock()->owned_by_self(), "should be");
|
||||
return _memory_manager;
|
||||
}
|
||||
llvm::ExecutionEngine* execution_engine() const {
|
||||
assert(execution_engine_lock()->owned_by_self(), "should be");
|
||||
return _execution_engine;
|
||||
}
|
||||
|
||||
// Global access
|
||||
public:
|
||||
static SharkCompiler* compiler() {
|
||||
AbstractCompiler *compiler =
|
||||
CompileBroker::compiler(CompLevel_full_optimization);
|
||||
assert(compiler->is_shark() && compiler->is_initialized(), "should be");
|
||||
return (SharkCompiler *) compiler;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
private:
|
||||
static const char* methodname(const char* klass, const char* method);
|
||||
void generate_native_code(SharkEntry* entry,
|
||||
llvm::Function* function,
|
||||
const char* name);
|
||||
void free_queued_methods();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKCOMPILER_HPP
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciInstance.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkConstant.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
SharkConstant* SharkConstant::for_ldc(ciBytecodeStream *iter) {
|
||||
ciConstant constant = iter->get_constant();
|
||||
ciType *type = NULL;
|
||||
if (constant.basic_type() == T_OBJECT) {
|
||||
ciEnv *env = ciEnv::current();
|
||||
|
||||
assert(constant.as_object()->klass() == env->String_klass()
|
||||
|| constant.as_object()->klass() == env->Class_klass()
|
||||
|| constant.as_object()->klass()->is_subtype_of(env->MethodType_klass())
|
||||
|| constant.as_object()->klass()->is_subtype_of(env->MethodHandle_klass()), "should be");
|
||||
|
||||
type = constant.as_object()->klass();
|
||||
}
|
||||
return new SharkConstant(constant, type);
|
||||
}
|
||||
|
||||
SharkConstant* SharkConstant::for_field(ciBytecodeStream *iter) {
|
||||
bool will_link;
|
||||
ciField *field = iter->get_field(will_link);
|
||||
assert(will_link, "typeflow responsibility");
|
||||
|
||||
return new SharkConstant(field->constant_value(), field->type());
|
||||
}
|
||||
|
||||
SharkConstant::SharkConstant(ciConstant constant, ciType *type) {
|
||||
SharkValue *value = NULL;
|
||||
|
||||
switch (constant.basic_type()) {
|
||||
case T_BOOLEAN:
|
||||
case T_BYTE:
|
||||
case T_CHAR:
|
||||
case T_SHORT:
|
||||
case T_INT:
|
||||
value = SharkValue::jint_constant(constant.as_int());
|
||||
break;
|
||||
|
||||
case T_LONG:
|
||||
value = SharkValue::jlong_constant(constant.as_long());
|
||||
break;
|
||||
|
||||
case T_FLOAT:
|
||||
value = SharkValue::jfloat_constant(constant.as_float());
|
||||
break;
|
||||
|
||||
case T_DOUBLE:
|
||||
value = SharkValue::jdouble_constant(constant.as_double());
|
||||
break;
|
||||
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
break;
|
||||
|
||||
case T_ILLEGAL:
|
||||
// out of memory
|
||||
_is_loaded = false;
|
||||
return;
|
||||
|
||||
default:
|
||||
tty->print_cr("Unhandled type %s", type2name(constant.basic_type()));
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
// Handle primitive types. We create SharkValues for these
|
||||
// now; doing so doesn't emit any code, and it allows us to
|
||||
// delegate a bunch of stuff to the SharkValue code.
|
||||
if (value) {
|
||||
_value = value;
|
||||
_is_loaded = true;
|
||||
_is_nonzero = value->zero_checked();
|
||||
_is_two_word = value->is_two_word();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle reference types. This is tricky because some
|
||||
// ciObjects are psuedo-objects that refer to oops which
|
||||
// have yet to be created. We need to spot the unloaded
|
||||
// objects (which differ between ldc* and get*, thanks!)
|
||||
ciObject *object = constant.as_object();
|
||||
assert(type != NULL, "shouldn't be");
|
||||
|
||||
if ((! object->is_null_object()) && object->klass() == ciEnv::current()->Class_klass()) {
|
||||
ciKlass *klass = object->klass();
|
||||
if (! klass->is_loaded()) {
|
||||
_is_loaded = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (object->is_null_object() || ! object->can_be_constant() || ! object->is_loaded()) {
|
||||
_is_loaded = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_value = NULL;
|
||||
_object = object;
|
||||
_type = type;
|
||||
_is_loaded = true;
|
||||
_is_nonzero = true;
|
||||
_is_two_word = false;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKCONSTANT_HPP
|
||||
#define SHARE_VM_SHARK_SHARKCONSTANT_HPP
|
||||
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
class SharkConstant : public ResourceObj {
|
||||
public:
|
||||
static SharkConstant* for_ldc(ciBytecodeStream* iter);
|
||||
static SharkConstant* for_field(ciBytecodeStream* iter);
|
||||
|
||||
private:
|
||||
SharkConstant(ciConstant constant, ciType* type);
|
||||
|
||||
private:
|
||||
SharkValue* _value;
|
||||
ciObject* _object;
|
||||
ciType* _type;
|
||||
bool _is_loaded;
|
||||
bool _is_nonzero;
|
||||
bool _is_two_word;
|
||||
|
||||
public:
|
||||
bool is_loaded() const {
|
||||
return _is_loaded;
|
||||
}
|
||||
bool is_nonzero() const {
|
||||
assert(is_loaded(), "should be");
|
||||
return _is_nonzero;
|
||||
}
|
||||
bool is_two_word() const {
|
||||
assert(is_loaded(), "should be");
|
||||
return _is_two_word;
|
||||
}
|
||||
|
||||
public:
|
||||
SharkValue* value(SharkBuilder* builder) {
|
||||
assert(is_loaded(), "should be");
|
||||
if (_value == NULL) {
|
||||
_value = SharkValue::create_generic(
|
||||
_type, builder->CreateInlineOop(_object), _is_nonzero);
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKCONSTANT_HPP
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "oops/arrayOop.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
SharkContext::SharkContext(const char* name)
|
||||
: LLVMContext(),
|
||||
_free_queue(NULL) {
|
||||
// Create a module to build our functions into
|
||||
_module = new Module(name, *this);
|
||||
|
||||
// Create basic types
|
||||
_void_type = Type::getVoidTy(*this);
|
||||
_bit_type = Type::getInt1Ty(*this);
|
||||
_jbyte_type = Type::getInt8Ty(*this);
|
||||
_jshort_type = Type::getInt16Ty(*this);
|
||||
_jint_type = Type::getInt32Ty(*this);
|
||||
_jlong_type = Type::getInt64Ty(*this);
|
||||
_jfloat_type = Type::getFloatTy(*this);
|
||||
_jdouble_type = Type::getDoubleTy(*this);
|
||||
|
||||
// Create compound types
|
||||
_itableOffsetEntry_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), itableOffsetEntry::size() * wordSize));
|
||||
|
||||
_Metadata_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(Metadata)));
|
||||
|
||||
_klass_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(Klass)));
|
||||
|
||||
_jniEnv_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(JNIEnv)));
|
||||
|
||||
_jniHandleBlock_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(JNIHandleBlock)));
|
||||
|
||||
_Method_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(Method)));
|
||||
|
||||
_monitor_type = ArrayType::get(
|
||||
jbyte_type(), frame::interpreter_frame_monitor_size() * wordSize);
|
||||
|
||||
_oop_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(oopDesc)));
|
||||
|
||||
_thread_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(JavaThread)));
|
||||
|
||||
_zeroStack_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(ZeroStack)));
|
||||
|
||||
std::vector<Type*> params;
|
||||
params.push_back(Method_type());
|
||||
params.push_back(intptr_type());
|
||||
params.push_back(thread_type());
|
||||
_entry_point_type = FunctionType::get(jint_type(), params, false);
|
||||
|
||||
params.clear();
|
||||
params.push_back(Method_type());
|
||||
params.push_back(PointerType::getUnqual(jbyte_type()));
|
||||
params.push_back(intptr_type());
|
||||
params.push_back(thread_type());
|
||||
_osr_entry_point_type = FunctionType::get(jint_type(), params, false);
|
||||
|
||||
// Create mappings
|
||||
for (int i = 0; i < T_CONFLICT; i++) {
|
||||
switch (i) {
|
||||
case T_BOOLEAN:
|
||||
_to_stackType[i] = jint_type();
|
||||
_to_arrayType[i] = jbyte_type();
|
||||
break;
|
||||
|
||||
case T_BYTE:
|
||||
_to_stackType[i] = jint_type();
|
||||
_to_arrayType[i] = jbyte_type();
|
||||
break;
|
||||
|
||||
case T_CHAR:
|
||||
_to_stackType[i] = jint_type();
|
||||
_to_arrayType[i] = jshort_type();
|
||||
break;
|
||||
|
||||
case T_SHORT:
|
||||
_to_stackType[i] = jint_type();
|
||||
_to_arrayType[i] = jshort_type();
|
||||
break;
|
||||
|
||||
case T_INT:
|
||||
_to_stackType[i] = jint_type();
|
||||
_to_arrayType[i] = jint_type();
|
||||
break;
|
||||
|
||||
case T_LONG:
|
||||
_to_stackType[i] = jlong_type();
|
||||
_to_arrayType[i] = jlong_type();
|
||||
break;
|
||||
|
||||
case T_FLOAT:
|
||||
_to_stackType[i] = jfloat_type();
|
||||
_to_arrayType[i] = jfloat_type();
|
||||
break;
|
||||
|
||||
case T_DOUBLE:
|
||||
_to_stackType[i] = jdouble_type();
|
||||
_to_arrayType[i] = jdouble_type();
|
||||
break;
|
||||
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
_to_stackType[i] = oop_type();
|
||||
_to_arrayType[i] = oop_type();
|
||||
break;
|
||||
|
||||
case T_ADDRESS:
|
||||
_to_stackType[i] = intptr_type();
|
||||
_to_arrayType[i] = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
_to_stackType[i] = NULL;
|
||||
_to_arrayType[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SharkFreeQueueItem : public CHeapObj<mtNone> {
|
||||
public:
|
||||
SharkFreeQueueItem(llvm::Function* function, SharkFreeQueueItem *next)
|
||||
: _function(function), _next(next) {}
|
||||
|
||||
private:
|
||||
llvm::Function* _function;
|
||||
SharkFreeQueueItem* _next;
|
||||
|
||||
public:
|
||||
llvm::Function* function() const {
|
||||
return _function;
|
||||
}
|
||||
SharkFreeQueueItem* next() const {
|
||||
return _next;
|
||||
}
|
||||
};
|
||||
|
||||
void SharkContext::push_to_free_queue(Function* function) {
|
||||
_free_queue = new SharkFreeQueueItem(function, _free_queue);
|
||||
}
|
||||
|
||||
Function* SharkContext::pop_from_free_queue() {
|
||||
if (_free_queue == NULL)
|
||||
return NULL;
|
||||
|
||||
SharkFreeQueueItem *item = _free_queue;
|
||||
Function *function = item->function();
|
||||
_free_queue = item->next();
|
||||
delete item;
|
||||
return function;
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKCONTEXT_HPP
|
||||
#define SHARE_VM_SHARK_SHARKCONTEXT_HPP
|
||||
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkCompiler.hpp"
|
||||
|
||||
// The LLVMContext class allows multiple instances of LLVM to operate
|
||||
// independently of each other in a multithreaded context. We extend
|
||||
// this here to store things in Shark that are LLVMContext-specific.
|
||||
|
||||
class SharkFreeQueueItem;
|
||||
|
||||
class SharkContext : public llvm::LLVMContext {
|
||||
public:
|
||||
SharkContext(const char* name);
|
||||
|
||||
private:
|
||||
llvm::Module* _module;
|
||||
|
||||
public:
|
||||
llvm::Module* module() const {
|
||||
return _module;
|
||||
}
|
||||
|
||||
// Get this thread's SharkContext
|
||||
public:
|
||||
static SharkContext& current() {
|
||||
return *SharkCompiler::compiler()->context();
|
||||
}
|
||||
|
||||
// Module accessors
|
||||
public:
|
||||
void add_function(llvm::Function* function) const {
|
||||
module()->getFunctionList().push_back(function);
|
||||
}
|
||||
llvm::Constant* get_external(const char* name,
|
||||
llvm::FunctionType* sig) {
|
||||
return module()->getOrInsertFunction(name, sig);
|
||||
}
|
||||
|
||||
// Basic types
|
||||
private:
|
||||
llvm::Type* _void_type;
|
||||
llvm::IntegerType* _bit_type;
|
||||
llvm::IntegerType* _jbyte_type;
|
||||
llvm::IntegerType* _jshort_type;
|
||||
llvm::IntegerType* _jint_type;
|
||||
llvm::IntegerType* _jlong_type;
|
||||
llvm::Type* _jfloat_type;
|
||||
llvm::Type* _jdouble_type;
|
||||
|
||||
public:
|
||||
llvm::Type* void_type() const {
|
||||
return _void_type;
|
||||
}
|
||||
llvm::IntegerType* bit_type() const {
|
||||
return _bit_type;
|
||||
}
|
||||
llvm::IntegerType* jbyte_type() const {
|
||||
return _jbyte_type;
|
||||
}
|
||||
llvm::IntegerType* jshort_type() const {
|
||||
return _jshort_type;
|
||||
}
|
||||
llvm::IntegerType* jint_type() const {
|
||||
return _jint_type;
|
||||
}
|
||||
llvm::IntegerType* jlong_type() const {
|
||||
return _jlong_type;
|
||||
}
|
||||
llvm::Type* jfloat_type() const {
|
||||
return _jfloat_type;
|
||||
}
|
||||
llvm::Type* jdouble_type() const {
|
||||
return _jdouble_type;
|
||||
}
|
||||
llvm::IntegerType* intptr_type() const {
|
||||
return LP64_ONLY(jlong_type()) NOT_LP64(jint_type());
|
||||
}
|
||||
|
||||
// Compound types
|
||||
private:
|
||||
llvm::PointerType* _itableOffsetEntry_type;
|
||||
llvm::PointerType* _jniEnv_type;
|
||||
llvm::PointerType* _jniHandleBlock_type;
|
||||
llvm::PointerType* _Metadata_type;
|
||||
llvm::PointerType* _klass_type;
|
||||
llvm::PointerType* _Method_type;
|
||||
llvm::ArrayType* _monitor_type;
|
||||
llvm::PointerType* _oop_type;
|
||||
llvm::PointerType* _thread_type;
|
||||
llvm::PointerType* _zeroStack_type;
|
||||
llvm::FunctionType* _entry_point_type;
|
||||
llvm::FunctionType* _osr_entry_point_type;
|
||||
|
||||
public:
|
||||
llvm::PointerType* itableOffsetEntry_type() const {
|
||||
return _itableOffsetEntry_type;
|
||||
}
|
||||
llvm::PointerType* jniEnv_type() const {
|
||||
return _jniEnv_type;
|
||||
}
|
||||
llvm::PointerType* jniHandleBlock_type() const {
|
||||
return _jniHandleBlock_type;
|
||||
}
|
||||
llvm::PointerType* Metadata_type() const {
|
||||
return _Metadata_type;
|
||||
}
|
||||
llvm::PointerType* klass_type() const {
|
||||
return _klass_type;
|
||||
}
|
||||
llvm::PointerType* Method_type() const {
|
||||
return _Method_type;
|
||||
}
|
||||
llvm::ArrayType* monitor_type() const {
|
||||
return _monitor_type;
|
||||
}
|
||||
llvm::PointerType* oop_type() const {
|
||||
return _oop_type;
|
||||
}
|
||||
llvm::PointerType* thread_type() const {
|
||||
return _thread_type;
|
||||
}
|
||||
llvm::PointerType* zeroStack_type() const {
|
||||
return _zeroStack_type;
|
||||
}
|
||||
llvm::FunctionType* entry_point_type() const {
|
||||
return _entry_point_type;
|
||||
}
|
||||
llvm::FunctionType* osr_entry_point_type() const {
|
||||
return _osr_entry_point_type;
|
||||
}
|
||||
|
||||
// Mappings
|
||||
private:
|
||||
llvm::Type* _to_stackType[T_CONFLICT];
|
||||
llvm::Type* _to_arrayType[T_CONFLICT];
|
||||
|
||||
private:
|
||||
llvm::Type* map_type(llvm::Type* const* table,
|
||||
BasicType type) const {
|
||||
assert(type >= 0 && type < T_CONFLICT, "unhandled type");
|
||||
llvm::Type* result = table[type];
|
||||
assert(result != NULL, "unhandled type");
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::Type* to_stackType(BasicType type) const {
|
||||
return map_type(_to_stackType, type);
|
||||
}
|
||||
llvm::Type* to_arrayType(BasicType type) const {
|
||||
return map_type(_to_arrayType, type);
|
||||
}
|
||||
|
||||
// Functions queued for freeing
|
||||
private:
|
||||
SharkFreeQueueItem* _free_queue;
|
||||
|
||||
public:
|
||||
void push_to_free_queue(llvm::Function* function);
|
||||
llvm::Function* pop_from_free_queue();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKCONTEXT_HPP
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKENTRY_HPP
|
||||
#define SHARE_VM_SHARK_SHARKENTRY_HPP
|
||||
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
|
||||
class SharkContext;
|
||||
|
||||
class SharkEntry : public ZeroEntry {
|
||||
private:
|
||||
address _code_limit;
|
||||
SharkContext* _context;
|
||||
llvm::Function* _function;
|
||||
|
||||
public:
|
||||
address code_start() const {
|
||||
return entry_point();
|
||||
}
|
||||
address code_limit() const {
|
||||
return _code_limit;
|
||||
}
|
||||
SharkContext* context() const {
|
||||
return _context;
|
||||
}
|
||||
llvm::Function* function() const {
|
||||
return _function;
|
||||
}
|
||||
|
||||
public:
|
||||
void set_code_limit(address code_limit) {
|
||||
_code_limit = code_limit;
|
||||
}
|
||||
void set_context(SharkContext* context) {
|
||||
_context = context;
|
||||
}
|
||||
void set_function(llvm::Function* function) {
|
||||
_function = function;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKENTRY_HPP
|
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciTypeFlow.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkEntry.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkTopLevelBlock.hpp"
|
||||
#include "shark/shark_globals.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkFunction::initialize(const char *name) {
|
||||
// Create the function
|
||||
_function = Function::Create(
|
||||
entry_point_type(),
|
||||
GlobalVariable::InternalLinkage,
|
||||
name);
|
||||
|
||||
// Get our arguments
|
||||
Function::arg_iterator ai = function()->arg_begin();
|
||||
Argument *method = ai++;
|
||||
method->setName("method");
|
||||
Argument *osr_buf = NULL;
|
||||
if (is_osr()) {
|
||||
osr_buf = ai++;
|
||||
osr_buf->setName("osr_buf");
|
||||
}
|
||||
Argument *base_pc = ai++;
|
||||
base_pc->setName("base_pc");
|
||||
code_buffer()->set_base_pc(base_pc);
|
||||
Argument *thread = ai++;
|
||||
thread->setName("thread");
|
||||
set_thread(thread);
|
||||
|
||||
// Create the list of blocks
|
||||
set_block_insertion_point(NULL);
|
||||
_blocks = NEW_RESOURCE_ARRAY(SharkTopLevelBlock*, block_count());
|
||||
for (int i = 0; i < block_count(); i++) {
|
||||
ciTypeFlow::Block *b = flow()->pre_order_at(i);
|
||||
|
||||
// Work around a bug in pre_order_at() that does not return
|
||||
// the correct pre-ordering. If pre_order_at() were correct
|
||||
// this line could simply be:
|
||||
// _blocks[i] = new SharkTopLevelBlock(this, b);
|
||||
_blocks[b->pre_order()] = new SharkTopLevelBlock(this, b);
|
||||
}
|
||||
|
||||
// Walk the tree from the start block to determine which
|
||||
// blocks are entered and which blocks require phis
|
||||
SharkTopLevelBlock *start_block = block(flow()->start_block_num());
|
||||
if (is_osr() && start_block->stack_depth_at_entry() != 0) {
|
||||
env()->record_method_not_compilable("can't compile OSR block with incoming stack-depth > 0");
|
||||
return;
|
||||
}
|
||||
assert(start_block->start() == flow()->start_bci(), "blocks out of order");
|
||||
start_block->enter();
|
||||
|
||||
// Initialize all entered blocks
|
||||
for (int i = 0; i < block_count(); i++) {
|
||||
if (block(i)->entered())
|
||||
block(i)->initialize();
|
||||
}
|
||||
|
||||
// Create and push our stack frame
|
||||
set_block_insertion_point(&function()->front());
|
||||
builder()->SetInsertPoint(CreateBlock());
|
||||
_stack = SharkStack::CreateBuildAndPushFrame(this, method);
|
||||
|
||||
// Create the entry state
|
||||
SharkState *entry_state;
|
||||
if (is_osr()) {
|
||||
entry_state = new SharkOSREntryState(start_block, method, osr_buf);
|
||||
|
||||
// Free the OSR buffer
|
||||
builder()->CreateCall(builder()->osr_migration_end(), osr_buf);
|
||||
}
|
||||
else {
|
||||
entry_state = new SharkNormalEntryState(start_block, method);
|
||||
|
||||
// Lock if necessary
|
||||
if (is_synchronized()) {
|
||||
SharkTopLevelBlock *locker =
|
||||
new SharkTopLevelBlock(this, start_block->ciblock());
|
||||
locker->add_incoming(entry_state);
|
||||
|
||||
set_block_insertion_point(start_block->entry_block());
|
||||
locker->acquire_method_lock();
|
||||
|
||||
entry_state = locker->current_state();
|
||||
}
|
||||
}
|
||||
|
||||
// Transition into the method proper
|
||||
start_block->add_incoming(entry_state);
|
||||
builder()->CreateBr(start_block->entry_block());
|
||||
|
||||
// Parse the blocks
|
||||
for (int i = 0; i < block_count(); i++) {
|
||||
if (!block(i)->entered())
|
||||
continue;
|
||||
|
||||
if (i + 1 < block_count())
|
||||
set_block_insertion_point(block(i + 1)->entry_block());
|
||||
else
|
||||
set_block_insertion_point(NULL);
|
||||
|
||||
block(i)->emit_IR();
|
||||
}
|
||||
do_deferred_zero_checks();
|
||||
}
|
||||
|
||||
class DeferredZeroCheck : public SharkTargetInvariants {
|
||||
public:
|
||||
DeferredZeroCheck(SharkTopLevelBlock* block, SharkValue* value)
|
||||
: SharkTargetInvariants(block),
|
||||
_block(block),
|
||||
_value(value),
|
||||
_bci(block->bci()),
|
||||
_state(block->current_state()->copy()),
|
||||
_check_block(builder()->GetInsertBlock()),
|
||||
_continue_block(function()->CreateBlock("not_zero")) {
|
||||
builder()->SetInsertPoint(continue_block());
|
||||
}
|
||||
|
||||
private:
|
||||
SharkTopLevelBlock* _block;
|
||||
SharkValue* _value;
|
||||
int _bci;
|
||||
SharkState* _state;
|
||||
BasicBlock* _check_block;
|
||||
BasicBlock* _continue_block;
|
||||
|
||||
public:
|
||||
SharkTopLevelBlock* block() const {
|
||||
return _block;
|
||||
}
|
||||
SharkValue* value() const {
|
||||
return _value;
|
||||
}
|
||||
int bci() const {
|
||||
return _bci;
|
||||
}
|
||||
SharkState* state() const {
|
||||
return _state;
|
||||
}
|
||||
BasicBlock* check_block() const {
|
||||
return _check_block;
|
||||
}
|
||||
BasicBlock* continue_block() const {
|
||||
return _continue_block;
|
||||
}
|
||||
|
||||
public:
|
||||
SharkFunction* function() const {
|
||||
return block()->function();
|
||||
}
|
||||
|
||||
public:
|
||||
void process() const {
|
||||
builder()->SetInsertPoint(check_block());
|
||||
block()->do_deferred_zero_check(value(), bci(), state(), continue_block());
|
||||
}
|
||||
};
|
||||
|
||||
void SharkFunction::add_deferred_zero_check(SharkTopLevelBlock* block,
|
||||
SharkValue* value) {
|
||||
deferred_zero_checks()->append(new DeferredZeroCheck(block, value));
|
||||
}
|
||||
|
||||
void SharkFunction::do_deferred_zero_checks() {
|
||||
for (int i = 0; i < deferred_zero_checks()->length(); i++)
|
||||
deferred_zero_checks()->at(i)->process();
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKFUNCTION_HPP
|
||||
#define SHARE_VM_SHARK_SHARKFUNCTION_HPP
|
||||
|
||||
#include "ci/ciEnv.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
#include "shark/sharkStack.hpp"
|
||||
|
||||
class SharkTopLevelBlock;
|
||||
class DeferredZeroCheck;
|
||||
|
||||
class SharkFunction : public SharkTargetInvariants {
|
||||
friend class SharkStackWithNormalFrame;
|
||||
|
||||
public:
|
||||
static llvm::Function* build(ciEnv* env,
|
||||
SharkBuilder* builder,
|
||||
ciTypeFlow* flow,
|
||||
const char* name) {
|
||||
SharkFunction function(env, builder, flow, name);
|
||||
return function.function();
|
||||
}
|
||||
|
||||
private:
|
||||
SharkFunction(ciEnv* env,
|
||||
SharkBuilder* builder,
|
||||
ciTypeFlow* flow,
|
||||
const char* name)
|
||||
: SharkTargetInvariants(env, builder, flow) { initialize(name); }
|
||||
|
||||
private:
|
||||
void initialize(const char* name);
|
||||
|
||||
private:
|
||||
llvm::Function* _function;
|
||||
SharkTopLevelBlock** _blocks;
|
||||
GrowableArray<DeferredZeroCheck*> _deferred_zero_checks;
|
||||
SharkStack* _stack;
|
||||
|
||||
public:
|
||||
llvm::Function* function() const {
|
||||
return _function;
|
||||
}
|
||||
int block_count() const {
|
||||
return flow()->block_count();
|
||||
}
|
||||
SharkTopLevelBlock* block(int i) const {
|
||||
assert(i < block_count(), "should be");
|
||||
return _blocks[i];
|
||||
}
|
||||
GrowableArray<DeferredZeroCheck*>* deferred_zero_checks() {
|
||||
return &_deferred_zero_checks;
|
||||
}
|
||||
SharkStack* stack() const {
|
||||
return _stack;
|
||||
}
|
||||
|
||||
// On-stack replacement
|
||||
private:
|
||||
bool is_osr() const {
|
||||
return flow()->is_osr_flow();
|
||||
}
|
||||
llvm::FunctionType* entry_point_type() const {
|
||||
if (is_osr())
|
||||
return SharkType::osr_entry_point_type();
|
||||
else
|
||||
return SharkType::entry_point_type();
|
||||
}
|
||||
|
||||
// Block management
|
||||
private:
|
||||
llvm::BasicBlock* _block_insertion_point;
|
||||
|
||||
void set_block_insertion_point(llvm::BasicBlock* block_insertion_point) {
|
||||
_block_insertion_point = block_insertion_point;
|
||||
}
|
||||
llvm::BasicBlock* block_insertion_point() const {
|
||||
return _block_insertion_point;
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::BasicBlock* CreateBlock(const char* name = "") const {
|
||||
return llvm::BasicBlock::Create(
|
||||
SharkContext::current(), name, function(), block_insertion_point());
|
||||
}
|
||||
|
||||
// Deferred zero checks
|
||||
public:
|
||||
void add_deferred_zero_check(SharkTopLevelBlock* block,
|
||||
SharkValue* value);
|
||||
|
||||
private:
|
||||
void do_deferred_zero_checks();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKFUNCTION_HPP
|
@ -1,765 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciField.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "shark/sharkBlock.hpp"
|
||||
#include "shark/sharkConstant.hpp"
|
||||
#include "shark/sharkInliner.hpp"
|
||||
#include "shark/sharkIntrinsics.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
#include "shark/shark_globals.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
class SharkInlineBlock : public SharkBlock {
|
||||
public:
|
||||
SharkInlineBlock(ciMethod* target, SharkState* state)
|
||||
: SharkBlock(state, target),
|
||||
_outer_state(state),
|
||||
_entry_state(new SharkState(this)) {
|
||||
for (int i = target->max_locals() - 1; i >= 0; i--) {
|
||||
SharkValue *value = NULL;
|
||||
if (i < target->arg_size())
|
||||
value = outer_state()->pop();
|
||||
entry_state()->set_local(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SharkState* _outer_state;
|
||||
SharkState* _entry_state;
|
||||
|
||||
private:
|
||||
SharkState* outer_state() {
|
||||
return _outer_state;
|
||||
}
|
||||
SharkState* entry_state() {
|
||||
return _entry_state;
|
||||
}
|
||||
|
||||
public:
|
||||
void emit_IR() {
|
||||
parse_bytecode(0, target()->code_size());
|
||||
}
|
||||
|
||||
private:
|
||||
void do_return(BasicType type) {
|
||||
if (type != T_VOID) {
|
||||
SharkValue *result = pop_result(type);
|
||||
outer_state()->push(result);
|
||||
if (result->is_two_word())
|
||||
outer_state()->push(NULL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SharkInlinerHelper : public StackObj {
|
||||
public:
|
||||
SharkInlinerHelper(ciMethod* target, SharkState* entry_state)
|
||||
: _target(target),
|
||||
_entry_state(entry_state),
|
||||
_iter(target) {}
|
||||
|
||||
private:
|
||||
ciBytecodeStream _iter;
|
||||
SharkState* _entry_state;
|
||||
ciMethod* _target;
|
||||
|
||||
public:
|
||||
ciBytecodeStream* iter() {
|
||||
return &_iter;
|
||||
}
|
||||
SharkState* entry_state() const {
|
||||
return _entry_state;
|
||||
}
|
||||
ciMethod* target() const {
|
||||
return _target;
|
||||
}
|
||||
|
||||
public:
|
||||
Bytecodes::Code bc() {
|
||||
return iter()->cur_bc();
|
||||
}
|
||||
int max_locals() const {
|
||||
return target()->max_locals();
|
||||
}
|
||||
int max_stack() const {
|
||||
return target()->max_stack();
|
||||
}
|
||||
|
||||
// Inlinability check
|
||||
public:
|
||||
bool is_inlinable();
|
||||
|
||||
private:
|
||||
void initialize_for_check();
|
||||
|
||||
bool do_getstatic() {
|
||||
return do_field_access(true, false);
|
||||
}
|
||||
bool do_getfield() {
|
||||
return do_field_access(true, true);
|
||||
}
|
||||
bool do_putfield() {
|
||||
return do_field_access(false, true);
|
||||
}
|
||||
bool do_field_access(bool is_get, bool is_field);
|
||||
|
||||
// Local variables for inlinability check
|
||||
private:
|
||||
bool* _locals;
|
||||
|
||||
public:
|
||||
bool* local_addr(int index) const {
|
||||
assert(index >= 0 && index < max_locals(), "bad local variable index");
|
||||
return &_locals[index];
|
||||
}
|
||||
bool local(int index) const {
|
||||
return *local_addr(index);
|
||||
}
|
||||
void set_local(int index, bool value) {
|
||||
*local_addr(index) = value;
|
||||
}
|
||||
|
||||
// Expression stack for inlinability check
|
||||
private:
|
||||
bool* _stack;
|
||||
bool* _sp;
|
||||
|
||||
public:
|
||||
int stack_depth() const {
|
||||
return _sp - _stack;
|
||||
}
|
||||
bool* stack_addr(int slot) const {
|
||||
assert(slot >= 0 && slot < stack_depth(), "bad stack slot");
|
||||
return &_sp[-(slot + 1)];
|
||||
}
|
||||
void push(bool value) {
|
||||
assert(stack_depth() < max_stack(), "stack overrun");
|
||||
*(_sp++) = value;
|
||||
}
|
||||
bool pop() {
|
||||
assert(stack_depth() > 0, "stack underrun");
|
||||
return *(--_sp);
|
||||
}
|
||||
|
||||
// Methods for two-word locals
|
||||
public:
|
||||
void push_pair_local(int index) {
|
||||
push(local(index));
|
||||
push(local(index + 1));
|
||||
}
|
||||
void pop_pair_local(int index) {
|
||||
set_local(index + 1, pop());
|
||||
set_local(index, pop());
|
||||
}
|
||||
|
||||
// Code generation
|
||||
public:
|
||||
void do_inline() {
|
||||
(new SharkInlineBlock(target(), entry_state()))->emit_IR();
|
||||
}
|
||||
};
|
||||
|
||||
// Quick checks so we can bail out before doing too much
|
||||
bool SharkInliner::may_be_inlinable(ciMethod *target) {
|
||||
// We can't inline native methods
|
||||
if (target->is_native())
|
||||
return false;
|
||||
|
||||
// Not much point inlining abstract ones, and in any
|
||||
// case we'd need a stack frame to throw the exception
|
||||
if (target->is_abstract())
|
||||
return false;
|
||||
|
||||
// Don't inline anything huge
|
||||
if (target->code_size() > SharkMaxInlineSize)
|
||||
return false;
|
||||
|
||||
// Monitors aren't allowed without a frame to put them in
|
||||
if (target->is_synchronized() || target->has_monitor_bytecodes())
|
||||
return false;
|
||||
|
||||
// We don't do control flow
|
||||
if (target->has_exception_handlers() || target->has_jsrs())
|
||||
return false;
|
||||
|
||||
// Don't try to inline constructors, as they must
|
||||
// eventually call Object.<init> which we can't inline.
|
||||
// Note that this catches <clinit> too, but why would
|
||||
// we be compiling that?
|
||||
if (target->is_initializer())
|
||||
return false;
|
||||
|
||||
// Mustn't inline Object.<init>
|
||||
// Should be caught by the above, but just in case...
|
||||
if (target->intrinsic_id() == vmIntrinsics::_Object_init)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Full-on detailed check, for methods that pass the quick checks
|
||||
// Inlined methods have no stack frame, so we can't do anything
|
||||
// that would require one. This means no safepoints (and hence
|
||||
// no loops) and no VM calls. No VM calls means, amongst other
|
||||
// things, that no exceptions can be created, which means no null
|
||||
// checks or divide-by-zero checks are allowed. The lack of null
|
||||
// checks in particular would eliminate practically everything,
|
||||
// but we can get around that restriction by relying on the zero-
|
||||
// check eliminator to strip the checks. To do that, we need to
|
||||
// walk through the method, tracking which values are and are not
|
||||
// zero-checked.
|
||||
bool SharkInlinerHelper::is_inlinable() {
|
||||
ResourceMark rm;
|
||||
initialize_for_check();
|
||||
|
||||
SharkConstant *sc;
|
||||
bool a, b, c, d;
|
||||
|
||||
iter()->reset_to_bci(0);
|
||||
while (iter()->next() != ciBytecodeStream::EOBC()) {
|
||||
switch (bc()) {
|
||||
case Bytecodes::_nop:
|
||||
break;
|
||||
|
||||
case Bytecodes::_aconst_null:
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iconst_0:
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_iconst_m1:
|
||||
case Bytecodes::_iconst_1:
|
||||
case Bytecodes::_iconst_2:
|
||||
case Bytecodes::_iconst_3:
|
||||
case Bytecodes::_iconst_4:
|
||||
case Bytecodes::_iconst_5:
|
||||
push(true);
|
||||
break;
|
||||
|
||||
case Bytecodes::_lconst_0:
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_lconst_1:
|
||||
push(true);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_fconst_0:
|
||||
case Bytecodes::_fconst_1:
|
||||
case Bytecodes::_fconst_2:
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_dconst_0:
|
||||
case Bytecodes::_dconst_1:
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_bipush:
|
||||
push(iter()->get_constant_u1() != 0);
|
||||
break;
|
||||
case Bytecodes::_sipush:
|
||||
push(iter()->get_constant_u2() != 0);
|
||||
break;
|
||||
|
||||
case Bytecodes::_ldc:
|
||||
case Bytecodes::_ldc_w:
|
||||
case Bytecodes::_ldc2_w:
|
||||
sc = SharkConstant::for_ldc(iter());
|
||||
if (!sc->is_loaded())
|
||||
return false;
|
||||
push(sc->is_nonzero());
|
||||
if (sc->is_two_word())
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iload_0:
|
||||
case Bytecodes::_fload_0:
|
||||
case Bytecodes::_aload_0:
|
||||
push(local(0));
|
||||
break;
|
||||
case Bytecodes::_lload_0:
|
||||
case Bytecodes::_dload_0:
|
||||
push_pair_local(0);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iload_1:
|
||||
case Bytecodes::_fload_1:
|
||||
case Bytecodes::_aload_1:
|
||||
push(local(1));
|
||||
break;
|
||||
case Bytecodes::_lload_1:
|
||||
case Bytecodes::_dload_1:
|
||||
push_pair_local(1);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iload_2:
|
||||
case Bytecodes::_fload_2:
|
||||
case Bytecodes::_aload_2:
|
||||
push(local(2));
|
||||
break;
|
||||
case Bytecodes::_lload_2:
|
||||
case Bytecodes::_dload_2:
|
||||
push_pair_local(2);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iload_3:
|
||||
case Bytecodes::_fload_3:
|
||||
case Bytecodes::_aload_3:
|
||||
push(local(3));
|
||||
break;
|
||||
case Bytecodes::_lload_3:
|
||||
case Bytecodes::_dload_3:
|
||||
push_pair_local(3);
|
||||
break;
|
||||
|
||||
case Bytecodes::_iload:
|
||||
case Bytecodes::_fload:
|
||||
case Bytecodes::_aload:
|
||||
push(local(iter()->get_index()));
|
||||
break;
|
||||
case Bytecodes::_lload:
|
||||
case Bytecodes::_dload:
|
||||
push_pair_local(iter()->get_index());
|
||||
break;
|
||||
|
||||
case Bytecodes::_istore_0:
|
||||
case Bytecodes::_fstore_0:
|
||||
case Bytecodes::_astore_0:
|
||||
set_local(0, pop());
|
||||
break;
|
||||
case Bytecodes::_lstore_0:
|
||||
case Bytecodes::_dstore_0:
|
||||
pop_pair_local(0);
|
||||
break;
|
||||
|
||||
case Bytecodes::_istore_1:
|
||||
case Bytecodes::_fstore_1:
|
||||
case Bytecodes::_astore_1:
|
||||
set_local(1, pop());
|
||||
break;
|
||||
case Bytecodes::_lstore_1:
|
||||
case Bytecodes::_dstore_1:
|
||||
pop_pair_local(1);
|
||||
break;
|
||||
|
||||
case Bytecodes::_istore_2:
|
||||
case Bytecodes::_fstore_2:
|
||||
case Bytecodes::_astore_2:
|
||||
set_local(2, pop());
|
||||
break;
|
||||
case Bytecodes::_lstore_2:
|
||||
case Bytecodes::_dstore_2:
|
||||
pop_pair_local(2);
|
||||
break;
|
||||
|
||||
case Bytecodes::_istore_3:
|
||||
case Bytecodes::_fstore_3:
|
||||
case Bytecodes::_astore_3:
|
||||
set_local(3, pop());
|
||||
break;
|
||||
case Bytecodes::_lstore_3:
|
||||
case Bytecodes::_dstore_3:
|
||||
pop_pair_local(3);
|
||||
break;
|
||||
|
||||
case Bytecodes::_istore:
|
||||
case Bytecodes::_fstore:
|
||||
case Bytecodes::_astore:
|
||||
set_local(iter()->get_index(), pop());
|
||||
break;
|
||||
case Bytecodes::_lstore:
|
||||
case Bytecodes::_dstore:
|
||||
pop_pair_local(iter()->get_index());
|
||||
break;
|
||||
|
||||
case Bytecodes::_pop:
|
||||
pop();
|
||||
break;
|
||||
case Bytecodes::_pop2:
|
||||
pop();
|
||||
pop();
|
||||
break;
|
||||
case Bytecodes::_swap:
|
||||
a = pop();
|
||||
b = pop();
|
||||
push(a);
|
||||
push(b);
|
||||
break;
|
||||
case Bytecodes::_dup:
|
||||
a = pop();
|
||||
push(a);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_dup_x1:
|
||||
a = pop();
|
||||
b = pop();
|
||||
push(a);
|
||||
push(b);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_dup_x2:
|
||||
a = pop();
|
||||
b = pop();
|
||||
c = pop();
|
||||
push(a);
|
||||
push(c);
|
||||
push(b);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_dup2:
|
||||
a = pop();
|
||||
b = pop();
|
||||
push(b);
|
||||
push(a);
|
||||
push(b);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_dup2_x1:
|
||||
a = pop();
|
||||
b = pop();
|
||||
c = pop();
|
||||
push(b);
|
||||
push(a);
|
||||
push(c);
|
||||
push(b);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_dup2_x2:
|
||||
a = pop();
|
||||
b = pop();
|
||||
c = pop();
|
||||
d = pop();
|
||||
push(b);
|
||||
push(a);
|
||||
push(d);
|
||||
push(c);
|
||||
push(b);
|
||||
push(a);
|
||||
break;
|
||||
|
||||
case Bytecodes::_getfield:
|
||||
if (!do_getfield())
|
||||
return false;
|
||||
break;
|
||||
case Bytecodes::_getstatic:
|
||||
if (!do_getstatic())
|
||||
return false;
|
||||
break;
|
||||
case Bytecodes::_putfield:
|
||||
if (!do_putfield())
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Bytecodes::_iadd:
|
||||
case Bytecodes::_isub:
|
||||
case Bytecodes::_imul:
|
||||
case Bytecodes::_iand:
|
||||
case Bytecodes::_ixor:
|
||||
case Bytecodes::_ishl:
|
||||
case Bytecodes::_ishr:
|
||||
case Bytecodes::_iushr:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_ior:
|
||||
a = pop();
|
||||
b = pop();
|
||||
push(a && b);
|
||||
break;
|
||||
case Bytecodes::_idiv:
|
||||
case Bytecodes::_irem:
|
||||
if (!pop())
|
||||
return false;
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_ineg:
|
||||
break;
|
||||
|
||||
case Bytecodes::_ladd:
|
||||
case Bytecodes::_lsub:
|
||||
case Bytecodes::_lmul:
|
||||
case Bytecodes::_land:
|
||||
case Bytecodes::_lxor:
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_lor:
|
||||
a = pop();
|
||||
b = pop();
|
||||
push(a && b);
|
||||
break;
|
||||
case Bytecodes::_ldiv:
|
||||
case Bytecodes::_lrem:
|
||||
pop();
|
||||
if (!pop())
|
||||
return false;
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_lneg:
|
||||
break;
|
||||
case Bytecodes::_lshl:
|
||||
case Bytecodes::_lshr:
|
||||
case Bytecodes::_lushr:
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_fadd:
|
||||
case Bytecodes::_fsub:
|
||||
case Bytecodes::_fmul:
|
||||
case Bytecodes::_fdiv:
|
||||
case Bytecodes::_frem:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_fneg:
|
||||
break;
|
||||
|
||||
case Bytecodes::_dadd:
|
||||
case Bytecodes::_dsub:
|
||||
case Bytecodes::_dmul:
|
||||
case Bytecodes::_ddiv:
|
||||
case Bytecodes::_drem:
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_dneg:
|
||||
break;
|
||||
|
||||
case Bytecodes::_iinc:
|
||||
set_local(iter()->get_index(), false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_lcmp:
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_fcmpl:
|
||||
case Bytecodes::_fcmpg:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_dcmpl:
|
||||
case Bytecodes::_dcmpg:
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_i2l:
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_i2f:
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_i2d:
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_l2i:
|
||||
case Bytecodes::_l2f:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_l2d:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_f2i:
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_f2l:
|
||||
case Bytecodes::_f2d:
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_d2i:
|
||||
case Bytecodes::_d2f:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
case Bytecodes::_d2l:
|
||||
pop();
|
||||
pop();
|
||||
push(false);
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_i2b:
|
||||
case Bytecodes::_i2c:
|
||||
case Bytecodes::_i2s:
|
||||
pop();
|
||||
push(false);
|
||||
break;
|
||||
|
||||
case Bytecodes::_return:
|
||||
case Bytecodes::_ireturn:
|
||||
case Bytecodes::_lreturn:
|
||||
case Bytecodes::_freturn:
|
||||
case Bytecodes::_dreturn:
|
||||
case Bytecodes::_areturn:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharkInlinerHelper::initialize_for_check() {
|
||||
_locals = NEW_RESOURCE_ARRAY(bool, max_locals());
|
||||
_stack = NEW_RESOURCE_ARRAY(bool, max_stack());
|
||||
|
||||
memset(_locals, 0, max_locals() * sizeof(bool));
|
||||
for (int i = 0; i < target()->arg_size(); i++) {
|
||||
SharkValue *arg = entry_state()->stack(target()->arg_size() - 1 - i);
|
||||
if (arg && arg->zero_checked())
|
||||
set_local(i, true);
|
||||
}
|
||||
|
||||
_sp = _stack;
|
||||
}
|
||||
|
||||
bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) {
|
||||
assert(is_get || is_field, "can't inline putstatic");
|
||||
|
||||
// If the holder isn't linked then there isn't a lot we can do
|
||||
if (!target()->holder()->is_linked())
|
||||
return false;
|
||||
|
||||
// Get the field
|
||||
bool will_link;
|
||||
ciField *field = iter()->get_field(will_link);
|
||||
if (!will_link)
|
||||
return false;
|
||||
|
||||
// If the field is mismatched then an exception needs throwing
|
||||
if (is_field == field->is_static())
|
||||
return false;
|
||||
|
||||
// Pop the value off the stack if necessary
|
||||
if (!is_get) {
|
||||
pop();
|
||||
if (field->type()->is_two_word())
|
||||
pop();
|
||||
}
|
||||
|
||||
// Pop and null-check the receiver if necessary
|
||||
if (is_field) {
|
||||
if (!pop())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Push the result if necessary
|
||||
if (is_get) {
|
||||
bool result_pushed = false;
|
||||
if (field->is_constant() && field->is_static()) {
|
||||
SharkConstant *sc = SharkConstant::for_field(iter());
|
||||
if (sc->is_loaded()) {
|
||||
push(sc->is_nonzero());
|
||||
result_pushed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result_pushed)
|
||||
push(false);
|
||||
|
||||
if (field->type()->is_two_word())
|
||||
push(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state) {
|
||||
if (!Inline) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SharkIntrinsics::is_intrinsic(target)) {
|
||||
SharkIntrinsics::inline_intrinsic(target, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (may_be_inlinable(target)) {
|
||||
SharkInlinerHelper inliner(target, state);
|
||||
if (inliner.is_inlinable()) {
|
||||
inliner.do_inline();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKINLINER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKINLINER_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
|
||||
class SharkInliner : public AllStatic {
|
||||
public:
|
||||
static bool attempt_inline(ciMethod* target, SharkState* state);
|
||||
|
||||
private:
|
||||
static bool may_be_inlinable(ciMethod* target);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKINLINER_HPP
|
@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciMethod.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkIntrinsics.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
#include "shark/shark_globals.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool SharkIntrinsics::is_intrinsic(ciMethod *target) {
|
||||
switch (target->intrinsic_id()) {
|
||||
case vmIntrinsics::_none:
|
||||
return false;
|
||||
|
||||
// java.lang.Math
|
||||
case vmIntrinsics::_min:
|
||||
case vmIntrinsics::_max:
|
||||
case vmIntrinsics::_dabs:
|
||||
case vmIntrinsics::_dsin:
|
||||
case vmIntrinsics::_dcos:
|
||||
case vmIntrinsics::_dtan:
|
||||
case vmIntrinsics::_datan2:
|
||||
case vmIntrinsics::_dsqrt:
|
||||
case vmIntrinsics::_dlog:
|
||||
case vmIntrinsics::_dlog10:
|
||||
case vmIntrinsics::_dpow:
|
||||
case vmIntrinsics::_dexp:
|
||||
return true;
|
||||
|
||||
// java.lang.Object
|
||||
case vmIntrinsics::_getClass:
|
||||
return true;
|
||||
|
||||
// java.lang.System
|
||||
case vmIntrinsics::_currentTimeMillis:
|
||||
return true;
|
||||
|
||||
// java.lang.Thread
|
||||
case vmIntrinsics::_currentThread:
|
||||
return true;
|
||||
|
||||
// Unsafe
|
||||
case vmIntrinsics::_compareAndSetInt:
|
||||
return true;
|
||||
|
||||
default:
|
||||
if (SharkPerformanceWarnings) {
|
||||
warning(
|
||||
"unhandled intrinsic vmIntrinsic::%s",
|
||||
vmIntrinsics::name_at(target->intrinsic_id()));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SharkIntrinsics::inline_intrinsic(ciMethod *target, SharkState *state) {
|
||||
SharkIntrinsics intrinsic(state, target);
|
||||
intrinsic.do_intrinsic();
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_intrinsic() {
|
||||
switch (target()->intrinsic_id()) {
|
||||
// java.lang.Math
|
||||
case vmIntrinsics::_min:
|
||||
do_Math_minmax(llvm::ICmpInst::ICMP_SLE);
|
||||
break;
|
||||
case vmIntrinsics::_max:
|
||||
do_Math_minmax(llvm::ICmpInst::ICMP_SGE);
|
||||
break;
|
||||
case vmIntrinsics::_dabs:
|
||||
do_Math_1to1(builder()->fabs());
|
||||
break;
|
||||
case vmIntrinsics::_dsin:
|
||||
do_Math_1to1(builder()->sin());
|
||||
break;
|
||||
case vmIntrinsics::_dcos:
|
||||
do_Math_1to1(builder()->cos());
|
||||
break;
|
||||
case vmIntrinsics::_dtan:
|
||||
do_Math_1to1(builder()->tan());
|
||||
break;
|
||||
case vmIntrinsics::_datan2:
|
||||
do_Math_2to1(builder()->atan2());
|
||||
break;
|
||||
case vmIntrinsics::_dsqrt:
|
||||
do_Math_1to1(builder()->sqrt());
|
||||
break;
|
||||
case vmIntrinsics::_dlog:
|
||||
do_Math_1to1(builder()->log());
|
||||
break;
|
||||
case vmIntrinsics::_dlog10:
|
||||
do_Math_1to1(builder()->log10());
|
||||
break;
|
||||
case vmIntrinsics::_dpow:
|
||||
do_Math_2to1(builder()->pow());
|
||||
break;
|
||||
case vmIntrinsics::_dexp:
|
||||
do_Math_1to1(builder()->exp());
|
||||
break;
|
||||
|
||||
// java.lang.Object
|
||||
case vmIntrinsics::_getClass:
|
||||
do_Object_getClass();
|
||||
break;
|
||||
|
||||
// java.lang.System
|
||||
case vmIntrinsics::_currentTimeMillis:
|
||||
do_System_currentTimeMillis();
|
||||
break;
|
||||
|
||||
// java.lang.Thread
|
||||
case vmIntrinsics::_currentThread:
|
||||
do_Thread_currentThread();
|
||||
break;
|
||||
|
||||
// Unsafe
|
||||
case vmIntrinsics::_compareAndSetInt:
|
||||
do_Unsafe_compareAndSetInt();
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) {
|
||||
// Pop the arguments
|
||||
SharkValue *sb = state()->pop();
|
||||
SharkValue *sa = state()->pop();
|
||||
Value *a = sa->jint_value();
|
||||
Value *b = sb->jint_value();
|
||||
|
||||
// Perform the test
|
||||
BasicBlock *ip = builder()->GetBlockInsertionPoint();
|
||||
BasicBlock *return_a = builder()->CreateBlock(ip, "return_a");
|
||||
BasicBlock *return_b = builder()->CreateBlock(ip, "return_b");
|
||||
BasicBlock *done = builder()->CreateBlock(ip, "done");
|
||||
|
||||
builder()->CreateCondBr(builder()->CreateICmp(p, a, b), return_a, return_b);
|
||||
|
||||
builder()->SetInsertPoint(return_a);
|
||||
builder()->CreateBr(done);
|
||||
|
||||
builder()->SetInsertPoint(return_b);
|
||||
builder()->CreateBr(done);
|
||||
|
||||
builder()->SetInsertPoint(done);
|
||||
PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result");
|
||||
phi->addIncoming(a, return_a);
|
||||
phi->addIncoming(b, return_b);
|
||||
|
||||
// Push the result
|
||||
state()->push(
|
||||
SharkValue::create_jint(
|
||||
phi,
|
||||
sa->zero_checked() && sb->zero_checked()));
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Math_1to1(Value *function) {
|
||||
SharkValue *empty = state()->pop();
|
||||
assert(empty == NULL, "should be");
|
||||
state()->push(
|
||||
SharkValue::create_jdouble(
|
||||
builder()->CreateCall(
|
||||
function, state()->pop()->jdouble_value())));
|
||||
state()->push(NULL);
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Math_2to1(Value *function) {
|
||||
SharkValue *empty = state()->pop();
|
||||
assert(empty == NULL, "should be");
|
||||
Value *y = state()->pop()->jdouble_value();
|
||||
empty = state()->pop();
|
||||
assert(empty == NULL, "should be");
|
||||
Value *x = state()->pop()->jdouble_value();
|
||||
|
||||
state()->push(
|
||||
SharkValue::create_jdouble(
|
||||
builder()->CreateCall2(function, x, y)));
|
||||
state()->push(NULL);
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Object_getClass() {
|
||||
Value *klass = builder()->CreateValueOfStructEntry(
|
||||
state()->pop()->jobject_value(),
|
||||
in_ByteSize(oopDesc::klass_offset_in_bytes()),
|
||||
SharkType::klass_type(),
|
||||
"klass");
|
||||
|
||||
state()->push(
|
||||
SharkValue::create_jobject(
|
||||
builder()->CreateValueOfStructEntry(
|
||||
klass,
|
||||
Klass::java_mirror_offset(),
|
||||
SharkType::oop_type(),
|
||||
"java_mirror"),
|
||||
true));
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_System_currentTimeMillis() {
|
||||
state()->push(
|
||||
SharkValue::create_jlong(
|
||||
builder()->CreateCall(builder()->current_time_millis()),
|
||||
false));
|
||||
state()->push(NULL);
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Thread_currentThread() {
|
||||
state()->push(
|
||||
SharkValue::create_jobject(
|
||||
builder()->CreateValueOfStructEntry(
|
||||
thread(), JavaThread::threadObj_offset(),
|
||||
SharkType::oop_type(),
|
||||
"threadObj"),
|
||||
true));
|
||||
}
|
||||
|
||||
void SharkIntrinsics::do_Unsafe_compareAndSetInt() {
|
||||
// Pop the arguments
|
||||
Value *x = state()->pop()->jint_value();
|
||||
Value *e = state()->pop()->jint_value();
|
||||
SharkValue *empty = state()->pop();
|
||||
assert(empty == NULL, "should be");
|
||||
Value *offset = state()->pop()->jlong_value();
|
||||
Value *object = state()->pop()->jobject_value();
|
||||
Value *unsafe = state()->pop()->jobject_value();
|
||||
|
||||
// Convert the offset
|
||||
offset = builder()->CreateCall(
|
||||
builder()->unsafe_field_offset_to_byte_offset(),
|
||||
offset);
|
||||
|
||||
// Locate the field
|
||||
Value *addr = builder()->CreateIntToPtr(
|
||||
builder()->CreateAdd(
|
||||
builder()->CreatePtrToInt(object, SharkType::intptr_type()),
|
||||
builder()->CreateIntCast(offset, SharkType::intptr_type(), true)),
|
||||
PointerType::getUnqual(SharkType::jint_type()),
|
||||
"addr");
|
||||
|
||||
// Perform the operation
|
||||
Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent);
|
||||
// Push the result
|
||||
state()->push(
|
||||
SharkValue::create_jint(
|
||||
builder()->CreateIntCast(
|
||||
builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true),
|
||||
false));
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKINTRINSICS_HPP
|
||||
#define SHARE_VM_SHARK_SHARKINTRINSICS_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
|
||||
class SharkIntrinsics : public SharkTargetInvariants {
|
||||
public:
|
||||
static bool is_intrinsic(ciMethod* target);
|
||||
static void inline_intrinsic(ciMethod* target, SharkState* state);
|
||||
|
||||
private:
|
||||
SharkIntrinsics(SharkState* state, ciMethod* target)
|
||||
: SharkTargetInvariants(state, target), _state(state) {}
|
||||
|
||||
private:
|
||||
SharkState* _state;
|
||||
|
||||
private:
|
||||
SharkState* state() const {
|
||||
return _state;
|
||||
}
|
||||
|
||||
private:
|
||||
void do_intrinsic();
|
||||
|
||||
private:
|
||||
void do_Math_minmax(llvm::ICmpInst::Predicate p);
|
||||
void do_Math_1to1(llvm::Value* function);
|
||||
void do_Math_2to1(llvm::Value* function);
|
||||
void do_Object_getClass();
|
||||
void do_System_currentTimeMillis();
|
||||
void do_Thread_currentThread();
|
||||
void do_Unsafe_compareAndSetInt();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKINTRINSICS_HPP
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/sharkInvariants.hpp"
|
||||
|
||||
int SharkTargetInvariants::count_monitors() {
|
||||
int result = 0;
|
||||
if (is_synchronized() || target()->has_monitor_bytecodes()) {
|
||||
for (int i = 0; i < flow()->block_count(); i++) {
|
||||
result = MAX2(result, flow()->pre_order_at(i)->monitor_count());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKINVARIANTS_HPP
|
||||
#define SHARE_VM_SHARK_SHARKINVARIANTS_HPP
|
||||
|
||||
#include "ci/ciEnv.hpp"
|
||||
#include "ci/ciInstanceKlass.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "code/dependencies.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
|
||||
// Base classes used to track various values through the compilation.
|
||||
// SharkCompileInvariants is used to track values which remain the
|
||||
// same for the top-level method and any inlined methods it may have
|
||||
// (ie for the whole compilation). SharkTargetInvariants is used to
|
||||
// track values which differ between methods.
|
||||
|
||||
class SharkCompileInvariants : public ResourceObj {
|
||||
protected:
|
||||
SharkCompileInvariants(ciEnv* env, SharkBuilder* builder)
|
||||
: _env(env),
|
||||
_builder(builder),
|
||||
_thread(NULL) {}
|
||||
|
||||
SharkCompileInvariants(const SharkCompileInvariants* parent)
|
||||
: _env(parent->_env),
|
||||
_builder(parent->_builder),
|
||||
_thread(parent->_thread) {}
|
||||
|
||||
private:
|
||||
ciEnv* _env;
|
||||
SharkBuilder* _builder;
|
||||
llvm::Value* _thread;
|
||||
|
||||
// Top-level broker for HotSpot's Compiler Interface.
|
||||
//
|
||||
// Its main purpose is to allow the various CI classes to access
|
||||
// oops in the VM without having to worry about safepointing. In
|
||||
// addition to this it acts as a holder for various recorders and
|
||||
// memory allocators.
|
||||
//
|
||||
// Accessing this directly is kind of ugly, so it's private. Add
|
||||
// new accessors below if you need something from it.
|
||||
protected:
|
||||
ciEnv* env() const {
|
||||
assert(_env != NULL, "env not available");
|
||||
return _env;
|
||||
}
|
||||
|
||||
// The SharkBuilder that is used to build LLVM IR.
|
||||
protected:
|
||||
SharkBuilder* builder() const {
|
||||
return _builder;
|
||||
}
|
||||
|
||||
// Pointer to this thread's JavaThread object. This is not
|
||||
// available until a short way into SharkFunction creation
|
||||
// so a setter is required. Assertions are used to enforce
|
||||
// invariance.
|
||||
protected:
|
||||
llvm::Value* thread() const {
|
||||
assert(_thread != NULL, "thread not available");
|
||||
return _thread;
|
||||
}
|
||||
void set_thread(llvm::Value* thread) {
|
||||
assert(_thread == NULL, "thread already set");
|
||||
_thread = thread;
|
||||
}
|
||||
|
||||
// Objects that handle various aspects of the compilation.
|
||||
protected:
|
||||
DebugInformationRecorder* debug_info() const {
|
||||
return env()->debug_info();
|
||||
}
|
||||
SharkCodeBuffer* code_buffer() const {
|
||||
return builder()->code_buffer();
|
||||
}
|
||||
|
||||
public:
|
||||
Dependencies* dependencies() const {
|
||||
return env()->dependencies();
|
||||
}
|
||||
|
||||
// Commonly used classes
|
||||
protected:
|
||||
ciInstanceKlass* java_lang_Object_klass() const {
|
||||
return env()->Object_klass();
|
||||
}
|
||||
ciInstanceKlass* java_lang_Throwable_klass() const {
|
||||
return env()->Throwable_klass();
|
||||
}
|
||||
};
|
||||
|
||||
class SharkTargetInvariants : public SharkCompileInvariants {
|
||||
protected:
|
||||
SharkTargetInvariants(ciEnv* env, SharkBuilder* builder, ciTypeFlow* flow)
|
||||
: SharkCompileInvariants(env, builder),
|
||||
_target(flow->method()),
|
||||
_flow(flow),
|
||||
_max_monitors(count_monitors()) {}
|
||||
|
||||
SharkTargetInvariants(const SharkCompileInvariants* parent, ciMethod* target)
|
||||
: SharkCompileInvariants(parent),
|
||||
_target(target),
|
||||
_flow(NULL),
|
||||
_max_monitors(count_monitors()) {}
|
||||
|
||||
SharkTargetInvariants(const SharkTargetInvariants* parent)
|
||||
: SharkCompileInvariants(parent),
|
||||
_target(parent->_target),
|
||||
_flow(parent->_flow),
|
||||
_max_monitors(parent->_max_monitors) {}
|
||||
|
||||
private:
|
||||
int count_monitors();
|
||||
|
||||
private:
|
||||
ciMethod* _target;
|
||||
ciTypeFlow* _flow;
|
||||
int _max_monitors;
|
||||
|
||||
// The method being compiled.
|
||||
protected:
|
||||
ciMethod* target() const {
|
||||
return _target;
|
||||
}
|
||||
|
||||
// Typeflow analysis of the method being compiled.
|
||||
protected:
|
||||
ciTypeFlow* flow() const {
|
||||
assert(_flow != NULL, "typeflow not available");
|
||||
return _flow;
|
||||
}
|
||||
|
||||
// Properties of the method.
|
||||
protected:
|
||||
int max_locals() const {
|
||||
return target()->max_locals();
|
||||
}
|
||||
int max_stack() const {
|
||||
return target()->max_stack();
|
||||
}
|
||||
int max_monitors() const {
|
||||
return _max_monitors;
|
||||
}
|
||||
int arg_size() const {
|
||||
return target()->arg_size();
|
||||
}
|
||||
bool is_static() const {
|
||||
return target()->is_static();
|
||||
}
|
||||
bool is_synchronized() const {
|
||||
return target()->is_synchronized();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKINVARIANTS_HPP
|
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkEntry.hpp"
|
||||
#include "shark/sharkMemoryManager.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkMemoryManager::AllocateGOT() {
|
||||
mm()->AllocateGOT();
|
||||
}
|
||||
|
||||
unsigned char* SharkMemoryManager::getGOTBase() const {
|
||||
return mm()->getGOTBase();
|
||||
}
|
||||
|
||||
unsigned char* SharkMemoryManager::allocateStub(const GlobalValue* F,
|
||||
unsigned StubSize,
|
||||
unsigned Alignment) {
|
||||
return mm()->allocateStub(F, StubSize, Alignment);
|
||||
}
|
||||
|
||||
unsigned char* SharkMemoryManager::startFunctionBody(const Function* F,
|
||||
uintptr_t& ActualSize) {
|
||||
return mm()->startFunctionBody(F, ActualSize);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::endFunctionBody(const Function* F,
|
||||
unsigned char* FunctionStart,
|
||||
unsigned char* FunctionEnd) {
|
||||
mm()->endFunctionBody(F, FunctionStart, FunctionEnd);
|
||||
|
||||
SharkEntry *entry = get_entry_for_function(F);
|
||||
if (entry != NULL)
|
||||
entry->set_code_limit(FunctionEnd);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::setMemoryWritable() {
|
||||
mm()->setMemoryWritable();
|
||||
}
|
||||
|
||||
void SharkMemoryManager::setMemoryExecutable() {
|
||||
mm()->setMemoryExecutable();
|
||||
}
|
||||
|
||||
void SharkMemoryManager::deallocateFunctionBody(void *ptr) {
|
||||
mm()->deallocateFunctionBody(ptr);
|
||||
}
|
||||
|
||||
uint8_t* SharkMemoryManager::allocateGlobal(uintptr_t Size,
|
||||
unsigned int Alignment) {
|
||||
return mm()->allocateGlobal(Size, Alignment);
|
||||
}
|
||||
|
||||
void* SharkMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
|
||||
return mm()->getPointerToNamedFunction(Name, AbortOnFailure);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::setPoisonMemory(bool poison) {
|
||||
mm()->setPoisonMemory(poison);
|
||||
}
|
||||
|
||||
unsigned char *SharkMemoryManager::allocateSpace(intptr_t Size,
|
||||
unsigned int Alignment) {
|
||||
return mm()->allocateSpace(Size, Alignment);
|
||||
}
|
||||
|
||||
#if SHARK_LLVM_VERSION <= 32
|
||||
|
||||
uint8_t* SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
|
||||
return mm()->allocateCodeSection(Size, Alignment, SectionID);
|
||||
}
|
||||
|
||||
uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
|
||||
return mm()->allocateDataSection(Size, Alignment, SectionID);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
|
||||
mm()->deallocateExceptionTable(ptr);
|
||||
}
|
||||
|
||||
unsigned char* SharkMemoryManager::startExceptionTable(const Function* F,
|
||||
uintptr_t& ActualSize) {
|
||||
return mm()->startExceptionTable(F, ActualSize);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::endExceptionTable(const Function* F,
|
||||
unsigned char* TableStart,
|
||||
unsigned char* TableEnd,
|
||||
unsigned char* FrameRegister) {
|
||||
mm()->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint8_t *SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) {
|
||||
return mm()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
|
||||
}
|
||||
|
||||
uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) {
|
||||
return mm()->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
|
||||
}
|
||||
|
||||
bool SharkMemoryManager::finalizeMemory(std::string *ErrMsg) {
|
||||
return mm()->finalizeMemory(ErrMsg);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKMEMORYMANAGER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
|
||||
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkEntry.hpp"
|
||||
|
||||
// SharkMemoryManager wraps the LLVM JIT Memory Manager. We could use
|
||||
// this to run our own memory allocation policies, but for now all we
|
||||
// use it for is figuring out where the resulting native code ended up.
|
||||
|
||||
class SharkMemoryManager : public llvm::JITMemoryManager {
|
||||
public:
|
||||
SharkMemoryManager()
|
||||
: _mm(llvm::JITMemoryManager::CreateDefaultMemManager()) {}
|
||||
|
||||
private:
|
||||
llvm::JITMemoryManager* _mm;
|
||||
|
||||
private:
|
||||
llvm::JITMemoryManager* mm() const {
|
||||
return _mm;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<const llvm::Function*, SharkEntry*> _entry_map;
|
||||
|
||||
public:
|
||||
void set_entry_for_function(const llvm::Function* function,
|
||||
SharkEntry* entry) {
|
||||
_entry_map[function] = entry;
|
||||
}
|
||||
SharkEntry* get_entry_for_function(const llvm::Function* function) {
|
||||
return _entry_map[function];
|
||||
}
|
||||
|
||||
public:
|
||||
void AllocateGOT();
|
||||
unsigned char* getGOTBase() const;
|
||||
unsigned char* allocateStub(const llvm::GlobalValue* F,
|
||||
unsigned StubSize,
|
||||
unsigned Alignment);
|
||||
unsigned char* startFunctionBody(const llvm::Function* F,
|
||||
uintptr_t& ActualSize);
|
||||
void endFunctionBody(const llvm::Function* F,
|
||||
unsigned char* FunctionStart,
|
||||
unsigned char* FunctionEnd);
|
||||
|
||||
void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true);
|
||||
void setPoisonMemory(bool);
|
||||
uint8_t* allocateGlobal(uintptr_t, unsigned int);
|
||||
void setMemoryWritable();
|
||||
void setMemoryExecutable();
|
||||
void deallocateFunctionBody(void *ptr);
|
||||
unsigned char *allocateSpace(intptr_t Size,
|
||||
unsigned int Alignment);
|
||||
|
||||
#if SHARK_LLVM_VERSION <= 32
|
||||
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
|
||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
|
||||
unsigned char* startExceptionTable(const llvm::Function* F,
|
||||
uintptr_t& ActualSize);
|
||||
void deallocateExceptionTable(void *ptr);
|
||||
void endExceptionTable(const llvm::Function* F,
|
||||
unsigned char* TableStart,
|
||||
unsigned char* TableEnd,
|
||||
unsigned char* FrameRegister);
|
||||
#else
|
||||
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName);
|
||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool IsReadOnly);
|
||||
bool finalizeMemory(std::string *ErrMsg = 0);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
|
@ -1,354 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkNativeWrapper.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkNativeWrapper::initialize(const char *name) {
|
||||
// Create the function
|
||||
_function = Function::Create(
|
||||
SharkType::entry_point_type(),
|
||||
GlobalVariable::InternalLinkage,
|
||||
name);
|
||||
|
||||
// Get our arguments
|
||||
Function::arg_iterator ai = function()->arg_begin();
|
||||
Argument *method = ai++;
|
||||
method->setName("method");
|
||||
Argument *base_pc = ai++;
|
||||
base_pc->setName("base_pc");
|
||||
code_buffer()->set_base_pc(base_pc);
|
||||
Argument *thread = ai++;
|
||||
thread->setName("thread");
|
||||
set_thread(thread);
|
||||
|
||||
// Create and push our stack frame
|
||||
builder()->SetInsertPoint(CreateBlock());
|
||||
_stack = SharkStack::CreateBuildAndPushFrame(this, method);
|
||||
NOT_PRODUCT(method = NULL);
|
||||
|
||||
// Create the oopmap. We use the one oopmap for every call site in
|
||||
// the wrapper, which results in the odd mild inefficiency but is a
|
||||
// damn sight easier to code.
|
||||
OopMap *oopmap = new OopMap(
|
||||
SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
|
||||
SharkStack::oopmap_slot_munge(arg_size()));
|
||||
|
||||
// Set up the oop_tmp slot if required:
|
||||
// - For static methods we use it to handlize the class argument
|
||||
// for the call, and to protect the same during slow path locks
|
||||
// (if synchronized).
|
||||
// - For methods returning oops, we use it to protect the return
|
||||
// value across safepoints or slow path unlocking.
|
||||
if (is_static() || is_returning_oop()) {
|
||||
_oop_tmp_slot = stack()->slot_addr(
|
||||
stack()->oop_tmp_slot_offset(),
|
||||
SharkType::oop_type(),
|
||||
"oop_tmp_slot");
|
||||
|
||||
oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
|
||||
}
|
||||
|
||||
// Set up the monitor slot, for synchronized methods
|
||||
if (is_synchronized()) {
|
||||
Unimplemented();
|
||||
_lock_slot_offset = 23;
|
||||
}
|
||||
|
||||
// Start building the argument list
|
||||
std::vector<Type*> param_types;
|
||||
std::vector<Value*> param_values;
|
||||
PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
|
||||
|
||||
// First argument is the JNIEnv
|
||||
param_types.push_back(SharkType::jniEnv_type());
|
||||
param_values.push_back(
|
||||
builder()->CreateAddressOfStructEntry(
|
||||
thread,
|
||||
JavaThread::jni_environment_offset(),
|
||||
SharkType::jniEnv_type(),
|
||||
"jni_environment"));
|
||||
|
||||
// For static methods, the second argument is the class
|
||||
if (is_static()) {
|
||||
builder()->CreateStore(
|
||||
builder()->CreateInlineOop(
|
||||
JNIHandles::make_local(
|
||||
target()->method_holder()->java_mirror())),
|
||||
oop_tmp_slot());
|
||||
|
||||
param_types.push_back(box_type);
|
||||
param_values.push_back(oop_tmp_slot());
|
||||
|
||||
_receiver_slot_offset = stack()->oop_tmp_slot_offset();
|
||||
}
|
||||
else if (is_returning_oop()) {
|
||||
// The oop_tmp slot is registered in the oopmap,
|
||||
// so we need to clear it. This is one of the
|
||||
// mild inefficiencies I mentioned earlier.
|
||||
builder()->CreateStore(LLVMValue::null(), oop_tmp_slot());
|
||||
}
|
||||
|
||||
// Parse the arguments
|
||||
for (int i = 0; i < arg_size(); i++) {
|
||||
int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i;
|
||||
int adjusted_offset = slot_offset;
|
||||
BasicBlock *null, *not_null, *merge;
|
||||
Value *box;
|
||||
PHINode *phi;
|
||||
|
||||
switch (arg_type(i)) {
|
||||
case T_VOID:
|
||||
break;
|
||||
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
null = CreateBlock("null");
|
||||
not_null = CreateBlock("not_null");
|
||||
merge = CreateBlock("merge");
|
||||
|
||||
box = stack()->slot_addr(slot_offset, SharkType::oop_type());
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmp(
|
||||
ICmpInst::ICMP_EQ,
|
||||
builder()->CreateLoad(box),
|
||||
LLVMValue::null()),
|
||||
null, not_null);
|
||||
|
||||
builder()->SetInsertPoint(null);
|
||||
builder()->CreateBr(merge);
|
||||
|
||||
builder()->SetInsertPoint(not_null);
|
||||
builder()->CreateBr(merge);
|
||||
|
||||
builder()->SetInsertPoint(merge);
|
||||
phi = builder()->CreatePHI(box_type, 0, "boxed_object");
|
||||
phi->addIncoming(ConstantPointerNull::get(box_type), null);
|
||||
phi->addIncoming(box, not_null);
|
||||
box = phi;
|
||||
|
||||
param_types.push_back(box_type);
|
||||
param_values.push_back(box);
|
||||
|
||||
oopmap->set_oop(SharkStack::slot2reg(slot_offset));
|
||||
|
||||
if (i == 0 && !is_static())
|
||||
_receiver_slot_offset = slot_offset;
|
||||
|
||||
break;
|
||||
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
adjusted_offset--;
|
||||
// fall through
|
||||
|
||||
default:
|
||||
Type *param_type = SharkType::to_stackType(arg_type(i));
|
||||
|
||||
param_types.push_back(param_type);
|
||||
param_values.push_back(
|
||||
builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
|
||||
}
|
||||
}
|
||||
|
||||
// The oopmap is now complete, and everything is written
|
||||
// into the frame except the PC.
|
||||
int pc_offset = code_buffer()->create_unique_offset();
|
||||
|
||||
_oop_maps = new OopMapSet();
|
||||
oop_maps()->add_gc_map(pc_offset, oopmap);
|
||||
|
||||
builder()->CreateStore(
|
||||
builder()->code_buffer_address(pc_offset),
|
||||
stack()->slot_addr(stack()->pc_slot_offset()));
|
||||
|
||||
// Set up the Java frame anchor
|
||||
stack()->CreateSetLastJavaFrame();
|
||||
|
||||
// Lock if necessary
|
||||
if (is_synchronized())
|
||||
Unimplemented();
|
||||
|
||||
// Change the thread state to _thread_in_native
|
||||
CreateSetThreadState(_thread_in_native);
|
||||
|
||||
// Make the call
|
||||
BasicType result_type = target()->result_type();
|
||||
Type* return_type;
|
||||
if (result_type == T_VOID)
|
||||
return_type = SharkType::void_type();
|
||||
else if (is_returning_oop())
|
||||
return_type = box_type;
|
||||
else
|
||||
return_type = SharkType::to_arrayType(result_type);
|
||||
Value* native_function = builder()->CreateIntToPtr(
|
||||
LLVMValue::intptr_constant((intptr_t) target()->native_function()),
|
||||
PointerType::getUnqual(
|
||||
FunctionType::get(return_type, param_types, false)));
|
||||
Value *result = builder()->CreateCall(
|
||||
native_function, llvm::makeArrayRef(param_values));
|
||||
|
||||
// Start the transition back to _thread_in_Java
|
||||
CreateSetThreadState(_thread_in_native_trans);
|
||||
|
||||
// Make sure new state is visible in the GC thread
|
||||
if (os::is_MP()) {
|
||||
if (UseMembar)
|
||||
builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread);
|
||||
else
|
||||
CreateWriteMemorySerializePage();
|
||||
}
|
||||
|
||||
// Handle safepoint operations, pending suspend requests,
|
||||
// and pending asynchronous exceptions.
|
||||
BasicBlock *check_thread = CreateBlock("check_thread");
|
||||
BasicBlock *do_safepoint = CreateBlock("do_safepoint");
|
||||
BasicBlock *safepointed = CreateBlock("safepointed");
|
||||
|
||||
Value *global_state = builder()->CreateLoad(
|
||||
builder()->CreateIntToPtr(
|
||||
LLVMValue::intptr_constant(
|
||||
(intptr_t) SafepointSynchronize::address_of_state()),
|
||||
PointerType::getUnqual(SharkType::jint_type())),
|
||||
"global_state");
|
||||
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpNE(
|
||||
global_state,
|
||||
LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
|
||||
do_safepoint, check_thread);
|
||||
|
||||
builder()->SetInsertPoint(check_thread);
|
||||
Value *thread_state = builder()->CreateValueOfStructEntry(
|
||||
thread,
|
||||
JavaThread::suspend_flags_offset(),
|
||||
SharkType::jint_type(),
|
||||
"thread_state");
|
||||
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpNE(
|
||||
thread_state,
|
||||
LLVMValue::jint_constant(0)),
|
||||
do_safepoint, safepointed);
|
||||
|
||||
builder()->SetInsertPoint(do_safepoint);
|
||||
builder()->CreateCall(
|
||||
builder()->check_special_condition_for_native_trans(), thread);
|
||||
builder()->CreateBr(safepointed);
|
||||
|
||||
// Finally we can change the thread state to _thread_in_Java
|
||||
builder()->SetInsertPoint(safepointed);
|
||||
CreateSetThreadState(_thread_in_Java);
|
||||
|
||||
// Clear the frame anchor
|
||||
stack()->CreateResetLastJavaFrame();
|
||||
|
||||
// If there is a pending exception then we can just unwind and
|
||||
// return. It seems totally wrong that unlocking is skipped here
|
||||
// but apparently the template interpreter does this so we do too.
|
||||
BasicBlock *exception = CreateBlock("exception");
|
||||
BasicBlock *no_exception = CreateBlock("no_exception");
|
||||
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpEQ(
|
||||
CreateLoadPendingException(),
|
||||
LLVMValue::null()),
|
||||
no_exception, exception);
|
||||
|
||||
builder()->SetInsertPoint(exception);
|
||||
CreateResetHandleBlock();
|
||||
stack()->CreatePopFrame(0);
|
||||
builder()->CreateRet(LLVMValue::jint_constant(0));
|
||||
|
||||
builder()->SetInsertPoint(no_exception);
|
||||
|
||||
// If the result was an oop then unbox it before
|
||||
// releasing the handle it might be protected by
|
||||
if (is_returning_oop()) {
|
||||
BasicBlock *null = builder()->GetInsertBlock();
|
||||
BasicBlock *not_null = CreateBlock("not_null");
|
||||
BasicBlock *merge = CreateBlock("merge");
|
||||
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
|
||||
not_null, merge);
|
||||
|
||||
builder()->SetInsertPoint(not_null);
|
||||
#error Needs to be updated for tagged jweak; see JNIHandles.
|
||||
Value *unboxed_result = builder()->CreateLoad(result);
|
||||
builder()->CreateBr(merge);
|
||||
|
||||
builder()->SetInsertPoint(merge);
|
||||
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result");
|
||||
phi->addIncoming(LLVMValue::null(), null);
|
||||
phi->addIncoming(unboxed_result, not_null);
|
||||
result = phi;
|
||||
}
|
||||
|
||||
// Reset handle block
|
||||
CreateResetHandleBlock();
|
||||
|
||||
// Unlock if necessary.
|
||||
if (is_synchronized())
|
||||
Unimplemented();
|
||||
|
||||
// Unwind and return
|
||||
Value *result_addr = stack()->CreatePopFrame(type2size[result_type]);
|
||||
if (result_type != T_VOID) {
|
||||
bool needs_cast = false;
|
||||
bool is_signed = false;
|
||||
switch (result_type) {
|
||||
case T_BOOLEAN:
|
||||
result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0));
|
||||
needs_cast = true;
|
||||
break;
|
||||
|
||||
case T_CHAR:
|
||||
needs_cast = true;
|
||||
break;
|
||||
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
needs_cast = true;
|
||||
is_signed = true;
|
||||
break;
|
||||
}
|
||||
if (needs_cast) {
|
||||
result = builder()->CreateIntCast(
|
||||
result, SharkType::to_stackType(result_type), is_signed);
|
||||
}
|
||||
|
||||
builder()->CreateStore(
|
||||
result,
|
||||
builder()->CreateIntToPtr(
|
||||
result_addr,
|
||||
PointerType::getUnqual(SharkType::to_stackType(result_type))));
|
||||
}
|
||||
builder()->CreateRet(LLVMValue::jint_constant(0));
|
||||
}
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKNATIVEWRAPPER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKNATIVEWRAPPER_HPP
|
||||
|
||||
#include "runtime/handles.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
#include "shark/sharkStack.hpp"
|
||||
|
||||
class SharkNativeWrapper : public SharkCompileInvariants {
|
||||
friend class SharkStackWithNativeFrame;
|
||||
|
||||
public:
|
||||
static SharkNativeWrapper* build(SharkBuilder* builder,
|
||||
methodHandle target,
|
||||
const char* name,
|
||||
BasicType* arg_types,
|
||||
BasicType return_type) {
|
||||
return new SharkNativeWrapper(builder,
|
||||
target,
|
||||
name,
|
||||
arg_types,
|
||||
return_type);
|
||||
}
|
||||
|
||||
private:
|
||||
SharkNativeWrapper(SharkBuilder* builder,
|
||||
methodHandle target,
|
||||
const char* name,
|
||||
BasicType* arg_types,
|
||||
BasicType return_type)
|
||||
: SharkCompileInvariants(NULL, builder),
|
||||
_target(target),
|
||||
_arg_types(arg_types),
|
||||
_return_type(return_type),
|
||||
_lock_slot_offset(0) { initialize(name); }
|
||||
|
||||
private:
|
||||
void initialize(const char* name);
|
||||
|
||||
private:
|
||||
methodHandle _target;
|
||||
BasicType* _arg_types;
|
||||
BasicType _return_type;
|
||||
llvm::Function* _function;
|
||||
SharkStack* _stack;
|
||||
llvm::Value* _oop_tmp_slot;
|
||||
OopMapSet* _oop_maps;
|
||||
int _receiver_slot_offset;
|
||||
int _lock_slot_offset;
|
||||
|
||||
// The method being compiled.
|
||||
protected:
|
||||
methodHandle target() const {
|
||||
return _target;
|
||||
}
|
||||
|
||||
// Properties of the method.
|
||||
protected:
|
||||
int arg_size() const {
|
||||
return target()->size_of_parameters();
|
||||
}
|
||||
BasicType arg_type(int i) const {
|
||||
return _arg_types[i];
|
||||
}
|
||||
BasicType return_type() const {
|
||||
return _return_type;
|
||||
}
|
||||
bool is_static() const {
|
||||
return target()->is_static();
|
||||
}
|
||||
bool is_synchronized() const {
|
||||
return target()->is_synchronized();
|
||||
}
|
||||
bool is_returning_oop() const {
|
||||
return target()->is_returning_oop();
|
||||
}
|
||||
|
||||
// The LLVM function we are building.
|
||||
public:
|
||||
llvm::Function* function() const {
|
||||
return _function;
|
||||
}
|
||||
|
||||
// The Zero stack and our frame on it.
|
||||
protected:
|
||||
SharkStack* stack() const {
|
||||
return _stack;
|
||||
}
|
||||
|
||||
// Temporary oop storage.
|
||||
protected:
|
||||
llvm::Value* oop_tmp_slot() const {
|
||||
assert(is_static() || is_returning_oop(), "should be");
|
||||
return _oop_tmp_slot;
|
||||
}
|
||||
|
||||
// Information required by nmethod::new_native_nmethod().
|
||||
public:
|
||||
int frame_size() const {
|
||||
return stack()->oopmap_frame_size();
|
||||
}
|
||||
ByteSize receiver_offset() const {
|
||||
return in_ByteSize(_receiver_slot_offset * wordSize);
|
||||
}
|
||||
ByteSize lock_offset() const {
|
||||
return in_ByteSize(_lock_slot_offset * wordSize);
|
||||
}
|
||||
OopMapSet* oop_maps() const {
|
||||
return _oop_maps;
|
||||
}
|
||||
|
||||
// Helpers.
|
||||
private:
|
||||
llvm::BasicBlock* CreateBlock(const char* name = "") const {
|
||||
return llvm::BasicBlock::Create(SharkContext::current(), name, function());
|
||||
}
|
||||
llvm::Value* thread_state_address() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(), JavaThread::thread_state_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::jint_type()),
|
||||
"thread_state_address");
|
||||
}
|
||||
llvm::Value* pending_exception_address() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(), Thread::pending_exception_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::oop_type()),
|
||||
"pending_exception_address");
|
||||
}
|
||||
void CreateSetThreadState(JavaThreadState state) const {
|
||||
builder()->CreateStore(
|
||||
LLVMValue::jint_constant(state), thread_state_address());
|
||||
}
|
||||
void CreateWriteMemorySerializePage() const {
|
||||
builder()->CreateStore(
|
||||
LLVMValue::jint_constant(1),
|
||||
builder()->CreateIntToPtr(
|
||||
builder()->CreateAdd(
|
||||
LLVMValue::intptr_constant(
|
||||
(intptr_t) os::get_memory_serialize_page()),
|
||||
builder()->CreateAnd(
|
||||
builder()->CreateLShr(
|
||||
builder()->CreatePtrToInt(thread(), SharkType::intptr_type()),
|
||||
LLVMValue::intptr_constant(os::get_serialize_page_shift_count())),
|
||||
LLVMValue::intptr_constant(os::get_serialize_page_mask()))),
|
||||
llvm::PointerType::getUnqual(SharkType::jint_type())));
|
||||
}
|
||||
void CreateResetHandleBlock() const {
|
||||
llvm::Value *active_handles = builder()->CreateValueOfStructEntry(
|
||||
thread(),
|
||||
JavaThread::active_handles_offset(),
|
||||
SharkType::jniHandleBlock_type(),
|
||||
"active_handles");
|
||||
builder()->CreateStore(
|
||||
LLVMValue::intptr_constant(0),
|
||||
builder()->CreateAddressOfStructEntry(
|
||||
active_handles,
|
||||
in_ByteSize(JNIHandleBlock::top_offset_in_bytes()),
|
||||
llvm::PointerType::getUnqual(SharkType::intptr_type()),
|
||||
"top"));
|
||||
}
|
||||
llvm::LoadInst* CreateLoadPendingException() const {
|
||||
return builder()->CreateLoad(
|
||||
pending_exception_address(), "pending_exception");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKNATIVEWRAPPER_HPP
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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/atomic.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkRuntime.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#ifdef ZERO
|
||||
# include "stack_zero.inline.hpp"
|
||||
#endif
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
JRT_ENTRY(int, SharkRuntime::find_exception_handler(JavaThread* thread,
|
||||
int* indexes,
|
||||
int num_indexes))
|
||||
constantPoolHandle pool(thread, method(thread)->constants());
|
||||
Klass* exc_klass = ((oop) tos_at(thread, 0))->klass();
|
||||
|
||||
for (int i = 0; i < num_indexes; i++) {
|
||||
Klass* tmp = pool->klass_at(indexes[i], CHECK_0);
|
||||
|
||||
if (exc_klass() == tmp)
|
||||
return i;
|
||||
|
||||
if (exc_klass()->is_subtype_of(tmp))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::monitorenter(JavaThread* thread,
|
||||
BasicObjectLock* lock))
|
||||
if (PrintBiasedLockingStatistics)
|
||||
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
|
||||
|
||||
Handle object(thread, lock->obj());
|
||||
assert(Universe::heap()->is_in_reserved_or_null(object()), "should be");
|
||||
if (UseBiasedLocking) {
|
||||
// Retry fast entry if bias is revoked to avoid unnecessary inflation
|
||||
ObjectSynchronizer::fast_enter(object, lock->lock(), true, CHECK);
|
||||
} else {
|
||||
ObjectSynchronizer::slow_enter(object, lock->lock(), CHECK);
|
||||
}
|
||||
assert(Universe::heap()->is_in_reserved_or_null(lock->obj()), "should be");
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::monitorexit(JavaThread* thread,
|
||||
BasicObjectLock* lock))
|
||||
Handle object(thread, lock->obj());
|
||||
assert(Universe::heap()->is_in_reserved_or_null(object()), "should be");
|
||||
if (lock == NULL || object()->is_unlocked()) {
|
||||
THROW(vmSymbols::java_lang_IllegalMonitorStateException());
|
||||
}
|
||||
ObjectSynchronizer::slow_exit(object(), lock->lock(), thread);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::new_instance(JavaThread* thread, int index))
|
||||
Klass* k_oop = method(thread)->constants()->klass_at(index, CHECK);
|
||||
InstanceKlass* klass = InstanceKlass::cast(k);
|
||||
|
||||
// Make sure we are not instantiating an abstract klass
|
||||
klass->check_valid_for_instantiation(true, CHECK);
|
||||
|
||||
// Make sure klass is initialized
|
||||
klass->initialize(CHECK);
|
||||
|
||||
// At this point the class may not be fully initialized
|
||||
// because of recursive initialization. If it is fully
|
||||
// initialized & has_finalized is not set, we rewrite
|
||||
// it into its fast version (Note: no locking is needed
|
||||
// here since this is an atomic byte write and can be
|
||||
// done more than once).
|
||||
//
|
||||
// Note: In case of classes with has_finalized we don't
|
||||
// rewrite since that saves us an extra check in
|
||||
// the fast version which then would call the
|
||||
// slow version anyway (and do a call back into
|
||||
// Java).
|
||||
// If we have a breakpoint, then we don't rewrite
|
||||
// because the _breakpoint bytecode would be lost.
|
||||
oop obj = klass->allocate_instance(CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::newarray(JavaThread* thread,
|
||||
BasicType type,
|
||||
int size))
|
||||
oop obj = oopFactory::new_typeArray(type, size, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::anewarray(JavaThread* thread,
|
||||
int index,
|
||||
int size))
|
||||
Klass* klass = method(thread)->constants()->klass_at(index, CHECK);
|
||||
objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::multianewarray(JavaThread* thread,
|
||||
int index,
|
||||
int ndims,
|
||||
int* dims))
|
||||
Klass* klass = method(thread)->constants()->klass_at(index, CHECK);
|
||||
oop obj = ArrayKlass::cast(klass)->multi_allocate(ndims, dims, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::register_finalizer(JavaThread* thread,
|
||||
oop object))
|
||||
assert(oopDesc::is_oop(object), "should be");
|
||||
assert(object->klass()->has_finalizer(), "should have");
|
||||
InstanceKlass::register_finalizer(instanceOop(object), CHECK);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::throw_ArithmeticException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line))
|
||||
Exceptions::_throw_msg(
|
||||
thread, file, line,
|
||||
vmSymbols::java_lang_ArithmeticException(),
|
||||
"");
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::throw_ArrayIndexOutOfBoundsException(
|
||||
JavaThread* thread,
|
||||
const char* file,
|
||||
int line,
|
||||
int index))
|
||||
char msg[jintAsStringSize];
|
||||
snprintf(msg, sizeof(msg), "%d", index);
|
||||
Exceptions::_throw_msg(
|
||||
thread, file, line,
|
||||
vmSymbols::java_lang_ArrayIndexOutOfBoundsException(),
|
||||
msg);
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::throw_ClassCastException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line))
|
||||
Exceptions::_throw_msg(
|
||||
thread, file, line,
|
||||
vmSymbols::java_lang_ClassCastException(),
|
||||
"");
|
||||
JRT_END
|
||||
|
||||
JRT_ENTRY(void, SharkRuntime::throw_NullPointerException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line))
|
||||
Exceptions::_throw_msg(
|
||||
thread, file, line,
|
||||
vmSymbols::java_lang_NullPointerException(),
|
||||
"");
|
||||
JRT_END
|
||||
|
||||
// Non-VM calls
|
||||
// Nothing in these must ever GC!
|
||||
|
||||
void SharkRuntime::dump(const char *name, intptr_t value) {
|
||||
oop valueOop = (oop) value;
|
||||
tty->print("%s = ", name);
|
||||
if (valueOop->is_oop(true))
|
||||
valueOop->print_on(tty);
|
||||
else if (value >= ' ' && value <= '~')
|
||||
tty->print("'%c' (%d)", value, value);
|
||||
else
|
||||
tty->print("%p", value);
|
||||
tty->print_cr("");
|
||||
}
|
||||
|
||||
bool SharkRuntime::is_subtype_of(Klass* check_klass, Klass* object_klass) {
|
||||
return object_klass->is_subtype_of(check_klass);
|
||||
}
|
||||
|
||||
int SharkRuntime::uncommon_trap(JavaThread* thread, int trap_request) {
|
||||
Thread *THREAD = thread;
|
||||
|
||||
// In C2, uncommon_trap_blob creates a frame, so all the various
|
||||
// deoptimization functions expect to find the frame of the method
|
||||
// being deopted one frame down on the stack. We create a dummy
|
||||
// frame to mirror this.
|
||||
FakeStubFrame *stubframe = FakeStubFrame::build(CHECK_0);
|
||||
thread->push_zero_frame(stubframe);
|
||||
|
||||
// Initiate the trap
|
||||
thread->set_last_Java_frame();
|
||||
Deoptimization::UnrollBlock *urb =
|
||||
Deoptimization::uncommon_trap(thread, trap_request, Deoptimization::Unpack_uncommon_trap);
|
||||
thread->reset_last_Java_frame();
|
||||
assert(urb->unpack_kind() == Deoptimization::Unpack_uncommon_trap, "expected Unpack_uncommon_trap");
|
||||
|
||||
// Pop our dummy frame and the frame being deoptimized
|
||||
thread->pop_zero_frame();
|
||||
thread->pop_zero_frame();
|
||||
|
||||
// Push skeleton frames
|
||||
int number_of_frames = urb->number_of_frames();
|
||||
for (int i = 0; i < number_of_frames; i++) {
|
||||
intptr_t size = urb->frame_sizes()[i];
|
||||
InterpreterFrame *frame = InterpreterFrame::build(size, CHECK_0);
|
||||
thread->push_zero_frame(frame);
|
||||
}
|
||||
|
||||
// Push another dummy frame
|
||||
stubframe = FakeStubFrame::build(CHECK_0);
|
||||
thread->push_zero_frame(stubframe);
|
||||
|
||||
// Fill in the skeleton frames
|
||||
thread->set_last_Java_frame();
|
||||
Deoptimization::unpack_frames(thread, Deoptimization::Unpack_uncommon_trap);
|
||||
thread->reset_last_Java_frame();
|
||||
|
||||
// Pop our dummy frame
|
||||
thread->pop_zero_frame();
|
||||
|
||||
// Fall back into the interpreter
|
||||
return number_of_frames;
|
||||
}
|
||||
|
||||
FakeStubFrame* FakeStubFrame::build(TRAPS) {
|
||||
ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack();
|
||||
stack->overflow_check(header_words, CHECK_NULL);
|
||||
|
||||
stack->push(0); // next_frame, filled in later
|
||||
intptr_t *fp = stack->sp();
|
||||
assert(fp - stack->sp() == next_frame_off, "should be");
|
||||
|
||||
stack->push(FAKE_STUB_FRAME);
|
||||
assert(fp - stack->sp() == frame_type_off, "should be");
|
||||
|
||||
return (FakeStubFrame *) fp;
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKRUNTIME_HPP
|
||||
#define SHARE_VM_SHARK_SHARKRUNTIME_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
|
||||
class SharkRuntime : public AllStatic {
|
||||
// VM calls
|
||||
public:
|
||||
static int find_exception_handler(JavaThread* thread,
|
||||
int* indexes,
|
||||
int num_indexes);
|
||||
|
||||
static void monitorenter(JavaThread* thread, BasicObjectLock* lock);
|
||||
static void monitorexit(JavaThread* thread, BasicObjectLock* lock);
|
||||
|
||||
static void new_instance(JavaThread* thread, int index);
|
||||
static void newarray(JavaThread* thread, BasicType type, int size);
|
||||
static void anewarray(JavaThread* thread, int index, int size);
|
||||
static void multianewarray(JavaThread* thread,
|
||||
int index,
|
||||
int ndims,
|
||||
int* dims);
|
||||
|
||||
static void register_finalizer(JavaThread* thread, oop object);
|
||||
|
||||
static void throw_ArithmeticException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line);
|
||||
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line,
|
||||
int index);
|
||||
static void throw_ClassCastException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line);
|
||||
static void throw_NullPointerException(JavaThread* thread,
|
||||
const char* file,
|
||||
int line);
|
||||
|
||||
// Helpers for VM calls
|
||||
private:
|
||||
static const SharkFrame* last_frame(JavaThread *thread) {
|
||||
return thread->last_frame().zero_sharkframe();
|
||||
}
|
||||
static Method* method(JavaThread *thread) {
|
||||
return last_frame(thread)->method();
|
||||
}
|
||||
static address bcp(JavaThread *thread, int bci) {
|
||||
return method(thread)->code_base() + bci;
|
||||
}
|
||||
static int two_byte_index(JavaThread *thread, int bci) {
|
||||
return Bytes::get_Java_u2(bcp(thread, bci) + 1);
|
||||
}
|
||||
static intptr_t tos_at(JavaThread *thread, int offset) {
|
||||
return *(thread->zero_stack()->sp() + offset);
|
||||
}
|
||||
|
||||
// Non-VM calls
|
||||
public:
|
||||
static void dump(const char *name, intptr_t value);
|
||||
static bool is_subtype_of(Klass* check_klass, Klass* object_klass);
|
||||
static int uncommon_trap(JavaThread* thread, int trap_request);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKRUNTIME_HPP
|
@ -1,267 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkNativeWrapper.hpp"
|
||||
#include "shark/sharkStack.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkStack::initialize(Value* method) {
|
||||
bool setup_sp_and_method = (method != NULL);
|
||||
|
||||
int locals_words = max_locals();
|
||||
int extra_locals = locals_words - arg_size();
|
||||
int header_words = SharkFrame::header_words;
|
||||
int monitor_words = max_monitors()*frame::interpreter_frame_monitor_size();
|
||||
int stack_words = max_stack();
|
||||
int frame_words = header_words + monitor_words + stack_words;
|
||||
|
||||
_extended_frame_size = frame_words + locals_words;
|
||||
|
||||
// Update the stack pointer
|
||||
Value *stack_pointer = builder()->CreateSub(
|
||||
CreateLoadStackPointer(),
|
||||
LLVMValue::intptr_constant((frame_words + extra_locals) * wordSize));
|
||||
CreateStackOverflowCheck(stack_pointer);
|
||||
if (setup_sp_and_method)
|
||||
CreateStoreStackPointer(stack_pointer);
|
||||
|
||||
// Create the frame
|
||||
_frame = builder()->CreateIntToPtr(
|
||||
stack_pointer,
|
||||
PointerType::getUnqual(
|
||||
ArrayType::get(SharkType::intptr_type(), extended_frame_size())),
|
||||
"frame");
|
||||
int offset = 0;
|
||||
|
||||
// Expression stack
|
||||
_stack_slots_offset = offset;
|
||||
offset += stack_words;
|
||||
|
||||
// Monitors
|
||||
_monitors_slots_offset = offset;
|
||||
offset += monitor_words;
|
||||
|
||||
// Temporary oop slot
|
||||
_oop_tmp_slot_offset = offset++;
|
||||
|
||||
// Method pointer
|
||||
_method_slot_offset = offset++;
|
||||
if (setup_sp_and_method) {
|
||||
builder()->CreateStore(
|
||||
method, slot_addr(method_slot_offset(), SharkType::Method_type()));
|
||||
}
|
||||
|
||||
// Unextended SP
|
||||
builder()->CreateStore(stack_pointer, slot_addr(offset++));
|
||||
|
||||
// PC
|
||||
_pc_slot_offset = offset++;
|
||||
|
||||
// Frame header
|
||||
builder()->CreateStore(
|
||||
LLVMValue::intptr_constant(ZeroFrame::SHARK_FRAME), slot_addr(offset++));
|
||||
Value *fp = slot_addr(offset++);
|
||||
|
||||
// Local variables
|
||||
_locals_slots_offset = offset;
|
||||
offset += locals_words;
|
||||
|
||||
// Push the frame
|
||||
assert(offset == extended_frame_size(), "should do");
|
||||
builder()->CreateStore(CreateLoadFramePointer(), fp);
|
||||
CreateStoreFramePointer(
|
||||
builder()->CreatePtrToInt(fp, SharkType::intptr_type()));
|
||||
}
|
||||
|
||||
// This function should match ZeroStack::overflow_check
|
||||
void SharkStack::CreateStackOverflowCheck(Value* sp) {
|
||||
BasicBlock *zero_ok = CreateBlock("zero_stack_ok");
|
||||
BasicBlock *overflow = CreateBlock("stack_overflow");
|
||||
BasicBlock *abi_ok = CreateBlock("abi_stack_ok");
|
||||
|
||||
// Check the Zero stack
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpULT(sp, stack_base()),
|
||||
overflow, zero_ok);
|
||||
|
||||
// Check the ABI stack
|
||||
builder()->SetInsertPoint(zero_ok);
|
||||
Value *stack_top = builder()->CreateSub(
|
||||
builder()->CreateValueOfStructEntry(
|
||||
thread(),
|
||||
Thread::stack_base_offset(),
|
||||
SharkType::intptr_type(),
|
||||
"abi_base"),
|
||||
builder()->CreateValueOfStructEntry(
|
||||
thread(),
|
||||
Thread::stack_size_offset(),
|
||||
SharkType::intptr_type(),
|
||||
"abi_size"));
|
||||
Value *free_stack = builder()->CreateSub(
|
||||
builder()->CreatePtrToInt(
|
||||
builder()->CreateGetFrameAddress(),
|
||||
SharkType::intptr_type(),
|
||||
"abi_sp"),
|
||||
stack_top);
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpULT(
|
||||
free_stack,
|
||||
LLVMValue::intptr_constant(JavaThread::stack_shadow_zone_size())),
|
||||
overflow, abi_ok);
|
||||
|
||||
// Handle overflows
|
||||
builder()->SetInsertPoint(overflow);
|
||||
builder()->CreateCall(builder()->throw_StackOverflowError(), thread());
|
||||
builder()->CreateRet(LLVMValue::jint_constant(0));
|
||||
|
||||
builder()->SetInsertPoint(abi_ok);
|
||||
}
|
||||
|
||||
Value* SharkStack::CreatePopFrame(int result_slots) {
|
||||
assert(result_slots >= 0 && result_slots <= 2, "should be");
|
||||
int locals_to_pop = max_locals() - result_slots;
|
||||
|
||||
Value *fp = CreateLoadFramePointer();
|
||||
Value *sp = builder()->CreateAdd(
|
||||
fp,
|
||||
LLVMValue::intptr_constant((1 + locals_to_pop) * wordSize));
|
||||
|
||||
CreateStoreStackPointer(sp);
|
||||
CreateStoreFramePointer(
|
||||
builder()->CreateLoad(
|
||||
builder()->CreateIntToPtr(
|
||||
fp, PointerType::getUnqual(SharkType::intptr_type()))));
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
Value* SharkStack::slot_addr(int offset,
|
||||
Type* type,
|
||||
const char* name) const {
|
||||
bool needs_cast = type && type != SharkType::intptr_type();
|
||||
|
||||
Value* result = builder()->CreateStructGEP(
|
||||
_frame, offset, needs_cast ? "" : name);
|
||||
|
||||
if (needs_cast) {
|
||||
result = builder()->CreateBitCast(
|
||||
result, PointerType::getUnqual(type), name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// The bits that differentiate stacks with normal and native frames on top
|
||||
|
||||
SharkStack* SharkStack::CreateBuildAndPushFrame(SharkFunction* function,
|
||||
Value* method) {
|
||||
return new SharkStackWithNormalFrame(function, method);
|
||||
}
|
||||
SharkStack* SharkStack::CreateBuildAndPushFrame(SharkNativeWrapper* wrapper,
|
||||
Value* method) {
|
||||
return new SharkStackWithNativeFrame(wrapper, method);
|
||||
}
|
||||
|
||||
SharkStackWithNormalFrame::SharkStackWithNormalFrame(SharkFunction* function,
|
||||
Value* method)
|
||||
: SharkStack(function), _function(function) {
|
||||
// For normal frames, the stack pointer and the method slot will
|
||||
// be set during each decache, so it is not necessary to do them
|
||||
// at the time the frame is created. However, we set them for
|
||||
// non-PRODUCT builds to make crash dumps easier to understand.
|
||||
initialize(PRODUCT_ONLY(NULL) NOT_PRODUCT(method));
|
||||
}
|
||||
SharkStackWithNativeFrame::SharkStackWithNativeFrame(SharkNativeWrapper* wrp,
|
||||
Value* method)
|
||||
: SharkStack(wrp), _wrapper(wrp) {
|
||||
initialize(method);
|
||||
}
|
||||
|
||||
int SharkStackWithNormalFrame::arg_size() const {
|
||||
return function()->arg_size();
|
||||
}
|
||||
int SharkStackWithNativeFrame::arg_size() const {
|
||||
return wrapper()->arg_size();
|
||||
}
|
||||
|
||||
int SharkStackWithNormalFrame::max_locals() const {
|
||||
return function()->max_locals();
|
||||
}
|
||||
int SharkStackWithNativeFrame::max_locals() const {
|
||||
return wrapper()->arg_size();
|
||||
}
|
||||
|
||||
int SharkStackWithNormalFrame::max_stack() const {
|
||||
return function()->max_stack();
|
||||
}
|
||||
int SharkStackWithNativeFrame::max_stack() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SharkStackWithNormalFrame::max_monitors() const {
|
||||
return function()->max_monitors();
|
||||
}
|
||||
int SharkStackWithNativeFrame::max_monitors() const {
|
||||
return wrapper()->is_synchronized() ? 1 : 0;
|
||||
}
|
||||
|
||||
BasicBlock* SharkStackWithNormalFrame::CreateBlock(const char* name) const {
|
||||
return function()->CreateBlock(name);
|
||||
}
|
||||
BasicBlock* SharkStackWithNativeFrame::CreateBlock(const char* name) const {
|
||||
return wrapper()->CreateBlock(name);
|
||||
}
|
||||
|
||||
address SharkStackWithNormalFrame::interpreter_entry_point() const {
|
||||
return (address) CppInterpreter::normal_entry;
|
||||
}
|
||||
address SharkStackWithNativeFrame::interpreter_entry_point() const {
|
||||
return (address) CppInterpreter::native_entry;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void SharkStack::CreateAssertLastJavaSPIsNull() const {
|
||||
#ifdef ASSERT
|
||||
BasicBlock *fail = CreateBlock("assert_failed");
|
||||
BasicBlock *pass = CreateBlock("assert_ok");
|
||||
|
||||
builder()->CreateCondBr(
|
||||
builder()->CreateICmpEQ(
|
||||
builder()->CreateLoad(last_Java_sp_addr()),
|
||||
LLVMValue::intptr_constant(0)),
|
||||
pass, fail);
|
||||
|
||||
builder()->SetInsertPoint(fail);
|
||||
builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
|
||||
builder()->CreateUnreachable();
|
||||
|
||||
builder()->SetInsertPoint(pass);
|
||||
#endif // ASSERT
|
||||
}
|
||||
#endif // !PRODUCT
|
@ -1,299 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKSTACK_HPP
|
||||
#define SHARE_VM_SHARK_SHARKSTACK_HPP
|
||||
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
|
||||
class SharkFunction;
|
||||
class SharkNativeWrapper;
|
||||
class SharkStackWithNormalFrame;
|
||||
class SharkStackWithNativeFrame;
|
||||
|
||||
class SharkStack : public SharkCompileInvariants {
|
||||
public:
|
||||
static SharkStack* CreateBuildAndPushFrame(
|
||||
SharkFunction* function, llvm::Value* method);
|
||||
static SharkStack* CreateBuildAndPushFrame(
|
||||
SharkNativeWrapper* wrapper, llvm::Value* method);
|
||||
|
||||
protected:
|
||||
SharkStack(const SharkCompileInvariants* parent)
|
||||
: SharkCompileInvariants(parent) {}
|
||||
|
||||
protected:
|
||||
void initialize(llvm::Value* method);
|
||||
|
||||
protected:
|
||||
void CreateStackOverflowCheck(llvm::Value* sp);
|
||||
|
||||
// Properties of the method being compiled
|
||||
protected:
|
||||
virtual int arg_size() const = 0;
|
||||
virtual int max_locals() const = 0;
|
||||
virtual int max_stack() const = 0;
|
||||
virtual int max_monitors() const = 0;
|
||||
|
||||
// BasicBlock creation
|
||||
protected:
|
||||
virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0;
|
||||
|
||||
// Interpreter entry point for bailouts
|
||||
protected:
|
||||
virtual address interpreter_entry_point() const = 0;
|
||||
|
||||
// Interface with the Zero stack
|
||||
private:
|
||||
llvm::Value* zero_stack() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(),
|
||||
JavaThread::zero_stack_offset(),
|
||||
SharkType::zeroStack_type(),
|
||||
"zero_stack");
|
||||
}
|
||||
llvm::Value* stack_base() const {
|
||||
return builder()->CreateValueOfStructEntry(
|
||||
zero_stack(),
|
||||
ZeroStack::base_offset(),
|
||||
SharkType::intptr_type(),
|
||||
"stack_base");
|
||||
}
|
||||
llvm::Value* stack_pointer_addr() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
zero_stack(),
|
||||
ZeroStack::sp_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::intptr_type()),
|
||||
"stack_pointer_addr");
|
||||
}
|
||||
llvm::Value* frame_pointer_addr() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(),
|
||||
JavaThread::top_zero_frame_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::intptr_type()),
|
||||
"frame_pointer_addr");
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::LoadInst* CreateLoadStackPointer(const char *name = "") {
|
||||
return builder()->CreateLoad(stack_pointer_addr(), name);
|
||||
}
|
||||
llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) {
|
||||
return builder()->CreateStore(value, stack_pointer_addr());
|
||||
}
|
||||
llvm::LoadInst* CreateLoadFramePointer(const char *name = "") {
|
||||
return builder()->CreateLoad(frame_pointer_addr(), name);
|
||||
}
|
||||
llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) {
|
||||
return builder()->CreateStore(value, frame_pointer_addr());
|
||||
}
|
||||
llvm::Value* CreatePopFrame(int result_slots);
|
||||
|
||||
// Interface with the frame anchor
|
||||
private:
|
||||
llvm::Value* last_Java_sp_addr() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(),
|
||||
JavaThread::last_Java_sp_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::intptr_type()),
|
||||
"last_Java_sp_addr");
|
||||
}
|
||||
llvm::Value* last_Java_fp_addr() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(),
|
||||
JavaThread::last_Java_fp_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::intptr_type()),
|
||||
"last_Java_fp_addr");
|
||||
}
|
||||
|
||||
public:
|
||||
void CreateSetLastJavaFrame() {
|
||||
// Note that whenever _last_Java_sp != NULL other anchor fields
|
||||
// must be valid. The profiler apparently depends on this.
|
||||
NOT_PRODUCT(CreateAssertLastJavaSPIsNull());
|
||||
builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr());
|
||||
// XXX There's last_Java_pc as well, but I don't think anything uses it
|
||||
// Also XXX: should we fence here? Zero doesn't...
|
||||
builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr());
|
||||
// Also also XXX: we could probably cache the sp (and the fp we know??)
|
||||
}
|
||||
void CreateResetLastJavaFrame() {
|
||||
builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr());
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN;
|
||||
|
||||
// Our method's frame
|
||||
private:
|
||||
llvm::Value* _frame;
|
||||
int _extended_frame_size;
|
||||
int _stack_slots_offset;
|
||||
|
||||
public:
|
||||
int extended_frame_size() const {
|
||||
return _extended_frame_size;
|
||||
}
|
||||
int oopmap_frame_size() const {
|
||||
return extended_frame_size() - arg_size();
|
||||
}
|
||||
|
||||
// Offsets of things in the frame
|
||||
private:
|
||||
int _monitors_slots_offset;
|
||||
int _oop_tmp_slot_offset;
|
||||
int _method_slot_offset;
|
||||
int _pc_slot_offset;
|
||||
int _locals_slots_offset;
|
||||
|
||||
public:
|
||||
int stack_slots_offset() const {
|
||||
return _stack_slots_offset;
|
||||
}
|
||||
int oop_tmp_slot_offset() const {
|
||||
return _oop_tmp_slot_offset;
|
||||
}
|
||||
int method_slot_offset() const {
|
||||
return _method_slot_offset;
|
||||
}
|
||||
int pc_slot_offset() const {
|
||||
return _pc_slot_offset;
|
||||
}
|
||||
int locals_slots_offset() const {
|
||||
return _locals_slots_offset;
|
||||
}
|
||||
int monitor_offset(int index) const {
|
||||
assert(index >= 0 && index < max_monitors(), "invalid monitor index");
|
||||
return _monitors_slots_offset +
|
||||
(max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size();
|
||||
}
|
||||
int monitor_object_offset(int index) const {
|
||||
return monitor_offset(index) +
|
||||
(BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
|
||||
}
|
||||
int monitor_header_offset(int index) const {
|
||||
return monitor_offset(index) +
|
||||
((BasicObjectLock::lock_offset_in_bytes() +
|
||||
BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord);
|
||||
}
|
||||
|
||||
// Addresses of things in the frame
|
||||
public:
|
||||
llvm::Value* slot_addr(int offset,
|
||||
llvm::Type* type = NULL,
|
||||
const char* name = "") const;
|
||||
|
||||
llvm::Value* monitor_addr(int index) const {
|
||||
return slot_addr(
|
||||
monitor_offset(index),
|
||||
SharkType::monitor_type(),
|
||||
"monitor");
|
||||
}
|
||||
llvm::Value* monitor_object_addr(int index) const {
|
||||
return slot_addr(
|
||||
monitor_object_offset(index),
|
||||
SharkType::oop_type(),
|
||||
"object_addr");
|
||||
}
|
||||
llvm::Value* monitor_header_addr(int index) const {
|
||||
return slot_addr(
|
||||
monitor_header_offset(index),
|
||||
SharkType::intptr_type(),
|
||||
"displaced_header_addr");
|
||||
}
|
||||
|
||||
// oopmap helpers
|
||||
public:
|
||||
static int oopmap_slot_munge(int offset) {
|
||||
return offset << (LogBytesPerWord - LogBytesPerInt);
|
||||
}
|
||||
static VMReg slot2reg(int offset) {
|
||||
return VMRegImpl::stack2reg(oopmap_slot_munge(offset));
|
||||
}
|
||||
};
|
||||
|
||||
class SharkStackWithNormalFrame : public SharkStack {
|
||||
friend class SharkStack;
|
||||
|
||||
protected:
|
||||
SharkStackWithNormalFrame(SharkFunction* function, llvm::Value* method);
|
||||
|
||||
private:
|
||||
SharkFunction* _function;
|
||||
|
||||
private:
|
||||
SharkFunction* function() const {
|
||||
return _function;
|
||||
}
|
||||
|
||||
// Properties of the method being compiled
|
||||
private:
|
||||
int arg_size() const;
|
||||
int max_locals() const;
|
||||
int max_stack() const;
|
||||
int max_monitors() const;
|
||||
|
||||
// BasicBlock creation
|
||||
private:
|
||||
llvm::BasicBlock* CreateBlock(const char* name = "") const;
|
||||
|
||||
// Interpreter entry point for bailouts
|
||||
private:
|
||||
address interpreter_entry_point() const;
|
||||
};
|
||||
|
||||
class SharkStackWithNativeFrame : public SharkStack {
|
||||
friend class SharkStack;
|
||||
|
||||
protected:
|
||||
SharkStackWithNativeFrame(SharkNativeWrapper* wrapper, llvm::Value* method);
|
||||
|
||||
private:
|
||||
SharkNativeWrapper* _wrapper;
|
||||
|
||||
private:
|
||||
SharkNativeWrapper* wrapper() const {
|
||||
return _wrapper;
|
||||
}
|
||||
|
||||
// Properties of the method being compiled
|
||||
private:
|
||||
int arg_size() const;
|
||||
int max_locals() const;
|
||||
int max_stack() const;
|
||||
int max_monitors() const;
|
||||
|
||||
// BasicBlock creation
|
||||
private:
|
||||
llvm::BasicBlock* CreateBlock(const char* name = "") const;
|
||||
|
||||
// Interpreter entry point for bailouts
|
||||
private:
|
||||
address interpreter_entry_point() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKSTACK_HPP
|
@ -1,397 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciType.hpp"
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkCacheDecache.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkTopLevelBlock.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkState::initialize(const SharkState *state) {
|
||||
_locals = NEW_RESOURCE_ARRAY(SharkValue*, max_locals());
|
||||
_stack = NEW_RESOURCE_ARRAY(SharkValue*, max_stack());
|
||||
|
||||
NOT_PRODUCT(memset(_locals, 23, max_locals() * sizeof(SharkValue *)));
|
||||
NOT_PRODUCT(memset(_stack, 23, max_stack() * sizeof(SharkValue *)));
|
||||
_sp = _stack;
|
||||
|
||||
if (state) {
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
SharkValue *value = state->local(i);
|
||||
if (value)
|
||||
value = value->clone();
|
||||
set_local(i, value);
|
||||
}
|
||||
|
||||
for (int i = state->stack_depth() - 1; i >= 0; i--) {
|
||||
SharkValue *value = state->stack(i);
|
||||
if (value)
|
||||
value = value->clone();
|
||||
push(value);
|
||||
}
|
||||
}
|
||||
|
||||
set_num_monitors(state ? state->num_monitors() : 0);
|
||||
}
|
||||
|
||||
bool SharkState::equal_to(SharkState *other) {
|
||||
if (target() != other->target())
|
||||
return false;
|
||||
|
||||
if (method() != other->method())
|
||||
return false;
|
||||
|
||||
if (oop_tmp() != other->oop_tmp())
|
||||
return false;
|
||||
|
||||
if (max_locals() != other->max_locals())
|
||||
return false;
|
||||
|
||||
if (stack_depth() != other->stack_depth())
|
||||
return false;
|
||||
|
||||
if (num_monitors() != other->num_monitors())
|
||||
return false;
|
||||
|
||||
if (has_safepointed() != other->has_safepointed())
|
||||
return false;
|
||||
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
SharkValue *value = local(i);
|
||||
SharkValue *other_value = other->local(i);
|
||||
|
||||
if (value == NULL) {
|
||||
if (other_value != NULL)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (other_value == NULL)
|
||||
return false;
|
||||
|
||||
if (!value->equal_to(other_value))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
for (int i = 0; i < stack_depth(); i++) {
|
||||
SharkValue *value = stack(i);
|
||||
SharkValue *other_value = other->stack(i);
|
||||
|
||||
if (value == NULL) {
|
||||
if (other_value != NULL)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (other_value == NULL)
|
||||
return false;
|
||||
|
||||
if (!value->equal_to(other_value))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharkState::merge(SharkState* other,
|
||||
BasicBlock* other_block,
|
||||
BasicBlock* this_block) {
|
||||
// Method
|
||||
Value *this_method = this->method();
|
||||
Value *other_method = other->method();
|
||||
if (this_method != other_method) {
|
||||
PHINode *phi = builder()->CreatePHI(SharkType::Method_type(), 0, "method");
|
||||
phi->addIncoming(this_method, this_block);
|
||||
phi->addIncoming(other_method, other_block);
|
||||
set_method(phi);
|
||||
}
|
||||
|
||||
// Temporary oop slot
|
||||
Value *this_oop_tmp = this->oop_tmp();
|
||||
Value *other_oop_tmp = other->oop_tmp();
|
||||
if (this_oop_tmp != other_oop_tmp) {
|
||||
assert(this_oop_tmp && other_oop_tmp, "can't merge NULL with non-NULL");
|
||||
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "oop_tmp");
|
||||
phi->addIncoming(this_oop_tmp, this_block);
|
||||
phi->addIncoming(other_oop_tmp, other_block);
|
||||
set_oop_tmp(phi);
|
||||
}
|
||||
|
||||
// Monitors
|
||||
assert(this->num_monitors() == other->num_monitors(), "should be");
|
||||
|
||||
// Local variables
|
||||
assert(this->max_locals() == other->max_locals(), "should be");
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
SharkValue *this_value = this->local(i);
|
||||
SharkValue *other_value = other->local(i);
|
||||
assert((this_value == NULL) == (other_value == NULL), "should be");
|
||||
if (this_value != NULL) {
|
||||
char name[18];
|
||||
snprintf(name, sizeof(name), "local_%d_", i);
|
||||
set_local(i, this_value->merge(
|
||||
builder(), other_value, other_block, this_block, name));
|
||||
}
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
assert(this->stack_depth() == other->stack_depth(), "should be");
|
||||
for (int i = 0; i < stack_depth(); i++) {
|
||||
SharkValue *this_value = this->stack(i);
|
||||
SharkValue *other_value = other->stack(i);
|
||||
assert((this_value == NULL) == (other_value == NULL), "should be");
|
||||
if (this_value != NULL) {
|
||||
char name[18];
|
||||
snprintf(name, sizeof(name), "stack_%d_", i);
|
||||
set_stack(i, this_value->merge(
|
||||
builder(), other_value, other_block, this_block, name));
|
||||
}
|
||||
}
|
||||
|
||||
// Safepointed status
|
||||
set_has_safepointed(this->has_safepointed() && other->has_safepointed());
|
||||
}
|
||||
|
||||
void SharkState::replace_all(SharkValue* old_value, SharkValue* new_value) {
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
if (local(i) == old_value)
|
||||
set_local(i, new_value);
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
for (int i = 0; i < stack_depth(); i++) {
|
||||
if (stack(i) == old_value)
|
||||
set_stack(i, new_value);
|
||||
}
|
||||
}
|
||||
|
||||
SharkNormalEntryState::SharkNormalEntryState(SharkTopLevelBlock* block,
|
||||
Value* method)
|
||||
: SharkState(block) {
|
||||
assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
|
||||
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
ciType *type = block->local_type_at_entry(i);
|
||||
|
||||
SharkValue *value = NULL;
|
||||
switch (type->basic_type()) {
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE:
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
if (i >= arg_size()) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
value = SharkValue::create_generic(type, NULL, i == 0 && !is_static());
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_NULL:
|
||||
value = SharkValue::null();
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_BOTTOM:
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_LONG2:
|
||||
case ciTypeFlow::StateVector::T_DOUBLE2:
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
set_local(i, value);
|
||||
}
|
||||
SharkNormalEntryCacher(block->function(), method).scan(this);
|
||||
}
|
||||
|
||||
SharkOSREntryState::SharkOSREntryState(SharkTopLevelBlock* block,
|
||||
Value* method,
|
||||
Value* osr_buf)
|
||||
: SharkState(block) {
|
||||
assert(block->stack_depth_at_entry() == 0, "entry block shouldn't have stack");
|
||||
set_num_monitors(block->ciblock()->monitor_count());
|
||||
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
ciType *type = block->local_type_at_entry(i);
|
||||
|
||||
SharkValue *value = NULL;
|
||||
switch (type->basic_type()) {
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE:
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
value = SharkValue::create_generic(type, NULL, false);
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_NULL:
|
||||
value = SharkValue::null();
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_BOTTOM:
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_LONG2:
|
||||
case ciTypeFlow::StateVector::T_DOUBLE2:
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
set_local(i, value);
|
||||
}
|
||||
SharkOSREntryCacher(block->function(), method, osr_buf).scan(this);
|
||||
}
|
||||
|
||||
SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
|
||||
: SharkState(block), _block(block) {
|
||||
BasicBlock *saved_insert_point = builder()->GetInsertBlock();
|
||||
builder()->SetInsertPoint(block->entry_block());
|
||||
char name[18];
|
||||
|
||||
// Method
|
||||
set_method(builder()->CreatePHI(SharkType::Method_type(), 0, "method"));
|
||||
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
ciType *type = block->local_type_at_entry(i);
|
||||
if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
|
||||
// XXX we could do all kinds of clever stuff here
|
||||
type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
|
||||
}
|
||||
|
||||
SharkValue *value = NULL;
|
||||
switch (type->basic_type()) {
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE:
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
snprintf(name, sizeof(name), "local_%d_", i);
|
||||
value = SharkValue::create_phi(
|
||||
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
|
||||
break;
|
||||
|
||||
case T_ADDRESS:
|
||||
value = SharkValue::address_constant(type->as_return_address()->bci());
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_BOTTOM:
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_LONG2:
|
||||
case ciTypeFlow::StateVector::T_DOUBLE2:
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
set_local(i, value);
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
for (int i = 0; i < block->stack_depth_at_entry(); i++) {
|
||||
ciType *type = block->stack_type_at_entry(i);
|
||||
if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
|
||||
// XXX we could do all kinds of clever stuff here
|
||||
type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
|
||||
}
|
||||
|
||||
SharkValue *value = NULL;
|
||||
switch (type->basic_type()) {
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE:
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
snprintf(name, sizeof(name), "stack_%d_", i);
|
||||
value = SharkValue::create_phi(
|
||||
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
|
||||
break;
|
||||
|
||||
case T_ADDRESS:
|
||||
value = SharkValue::address_constant(type->as_return_address()->bci());
|
||||
break;
|
||||
|
||||
case ciTypeFlow::StateVector::T_LONG2:
|
||||
case ciTypeFlow::StateVector::T_DOUBLE2:
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
push(value);
|
||||
}
|
||||
|
||||
// Monitors
|
||||
set_num_monitors(block->ciblock()->monitor_count());
|
||||
|
||||
builder()->SetInsertPoint(saved_insert_point);
|
||||
}
|
||||
|
||||
void SharkPHIState::add_incoming(SharkState* incoming_state) {
|
||||
BasicBlock *predecessor = builder()->GetInsertBlock();
|
||||
|
||||
// Method
|
||||
((PHINode *) method())->addIncoming(incoming_state->method(), predecessor);
|
||||
|
||||
// Local variables
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
if (local(i) != NULL)
|
||||
local(i)->addIncoming(incoming_state->local(i), predecessor);
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
int stack_depth = block()->stack_depth_at_entry();
|
||||
assert(stack_depth == incoming_state->stack_depth(), "should be");
|
||||
for (int i = 0; i < stack_depth; i++) {
|
||||
assert((stack(i) == NULL) == (incoming_state->stack(i) == NULL), "oops");
|
||||
if (stack(i))
|
||||
stack(i)->addIncoming(incoming_state->stack(i), predecessor);
|
||||
}
|
||||
|
||||
// Monitors
|
||||
assert(num_monitors() == incoming_state->num_monitors(), "should be");
|
||||
|
||||
// Temporary oop slot
|
||||
assert(oop_tmp() == incoming_state->oop_tmp(), "should be");
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKSTATE_HPP
|
||||
#define SHARE_VM_SHARK_SHARKSTATE_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
class SharkState : public SharkTargetInvariants {
|
||||
public:
|
||||
SharkState(const SharkTargetInvariants* parent)
|
||||
: SharkTargetInvariants(parent),
|
||||
_method(NULL),
|
||||
_oop_tmp(NULL),
|
||||
_has_safepointed(false) { initialize(NULL); }
|
||||
|
||||
SharkState(const SharkState* state)
|
||||
: SharkTargetInvariants(state),
|
||||
_method(state->_method),
|
||||
_oop_tmp(state->_oop_tmp),
|
||||
_has_safepointed(state->_has_safepointed) { initialize(state); }
|
||||
|
||||
private:
|
||||
void initialize(const SharkState* state);
|
||||
|
||||
private:
|
||||
llvm::Value* _method;
|
||||
SharkValue** _locals;
|
||||
SharkValue** _stack;
|
||||
SharkValue** _sp;
|
||||
int _num_monitors;
|
||||
llvm::Value* _oop_tmp;
|
||||
bool _has_safepointed;
|
||||
|
||||
// Method
|
||||
public:
|
||||
llvm::Value** method_addr() {
|
||||
return &_method;
|
||||
}
|
||||
llvm::Value* method() const {
|
||||
return _method;
|
||||
}
|
||||
protected:
|
||||
void set_method(llvm::Value* method) {
|
||||
_method = method;
|
||||
}
|
||||
|
||||
// Local variables
|
||||
public:
|
||||
SharkValue** local_addr(int index) const {
|
||||
assert(index >= 0 && index < max_locals(), "bad local variable index");
|
||||
return &_locals[index];
|
||||
}
|
||||
SharkValue* local(int index) const {
|
||||
return *local_addr(index);
|
||||
}
|
||||
void set_local(int index, SharkValue* value) {
|
||||
*local_addr(index) = value;
|
||||
}
|
||||
|
||||
// Expression stack
|
||||
public:
|
||||
SharkValue** stack_addr(int slot) const {
|
||||
assert(slot >= 0 && slot < stack_depth(), "bad stack slot");
|
||||
return &_sp[-(slot + 1)];
|
||||
}
|
||||
SharkValue* stack(int slot) const {
|
||||
return *stack_addr(slot);
|
||||
}
|
||||
protected:
|
||||
void set_stack(int slot, SharkValue* value) {
|
||||
*stack_addr(slot) = value;
|
||||
}
|
||||
public:
|
||||
int stack_depth() const {
|
||||
return _sp - _stack;
|
||||
}
|
||||
void push(SharkValue* value) {
|
||||
assert(stack_depth() < max_stack(), "stack overrun");
|
||||
*(_sp++) = value;
|
||||
}
|
||||
SharkValue* pop() {
|
||||
assert(stack_depth() > 0, "stack underrun");
|
||||
return *(--_sp);
|
||||
}
|
||||
|
||||
// Monitors
|
||||
public:
|
||||
int num_monitors() const {
|
||||
return _num_monitors;
|
||||
}
|
||||
void set_num_monitors(int num_monitors) {
|
||||
_num_monitors = num_monitors;
|
||||
}
|
||||
|
||||
// Temporary oop slot
|
||||
public:
|
||||
llvm::Value** oop_tmp_addr() {
|
||||
return &_oop_tmp;
|
||||
}
|
||||
llvm::Value* oop_tmp() const {
|
||||
return _oop_tmp;
|
||||
}
|
||||
void set_oop_tmp(llvm::Value* oop_tmp) {
|
||||
_oop_tmp = oop_tmp;
|
||||
}
|
||||
|
||||
// Safepointed status
|
||||
public:
|
||||
bool has_safepointed() const {
|
||||
return _has_safepointed;
|
||||
}
|
||||
void set_has_safepointed(bool has_safepointed) {
|
||||
_has_safepointed = has_safepointed;
|
||||
}
|
||||
|
||||
// Comparison
|
||||
public:
|
||||
bool equal_to(SharkState* other);
|
||||
|
||||
// Copy and merge
|
||||
public:
|
||||
SharkState* copy() const {
|
||||
return new SharkState(this);
|
||||
}
|
||||
void merge(SharkState* other,
|
||||
llvm::BasicBlock* other_block,
|
||||
llvm::BasicBlock* this_block);
|
||||
|
||||
// Value replacement
|
||||
public:
|
||||
void replace_all(SharkValue* old_value, SharkValue* new_value);
|
||||
};
|
||||
|
||||
class SharkTopLevelBlock;
|
||||
|
||||
// SharkNormalEntryState objects are used to create the state
|
||||
// that the method will be entered with for a normal invocation.
|
||||
class SharkNormalEntryState : public SharkState {
|
||||
public:
|
||||
SharkNormalEntryState(SharkTopLevelBlock* block,
|
||||
llvm::Value* method);
|
||||
};
|
||||
|
||||
// SharkOSREntryState objects are used to create the state
|
||||
// that the method will be entered with for an OSR invocation.
|
||||
class SharkOSREntryState : public SharkState {
|
||||
public:
|
||||
SharkOSREntryState(SharkTopLevelBlock* block,
|
||||
llvm::Value* method,
|
||||
llvm::Value* osr_buf);
|
||||
};
|
||||
|
||||
// SharkPHIState objects are used to manage the entry state
|
||||
// for blocks with more than one entry path or for blocks
|
||||
// entered from blocks that will be compiled later.
|
||||
class SharkPHIState : public SharkState {
|
||||
public:
|
||||
SharkPHIState(SharkTopLevelBlock* block);
|
||||
|
||||
private:
|
||||
SharkTopLevelBlock* _block;
|
||||
|
||||
private:
|
||||
SharkTopLevelBlock* block() const {
|
||||
return _block;
|
||||
}
|
||||
|
||||
public:
|
||||
void add_incoming(SharkState* incoming_state);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKSTATE_HPP
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/sharkState.hpp"
|
||||
#include "shark/sharkStateScanner.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void SharkStateScanner::scan(SharkState* state) {
|
||||
start_frame();
|
||||
|
||||
// Expression stack
|
||||
stack_integrity_checks(state);
|
||||
start_stack(state->stack_depth());
|
||||
for (int i = state->stack_depth() - 1; i >= 0; i--) {
|
||||
process_stack_slot(
|
||||
i,
|
||||
state->stack_addr(i),
|
||||
stack()->stack_slots_offset() +
|
||||
i + max_stack() - state->stack_depth());
|
||||
}
|
||||
end_stack();
|
||||
|
||||
// Monitors
|
||||
start_monitors(state->num_monitors());
|
||||
for (int i = 0; i < state->num_monitors(); i++) {
|
||||
process_monitor(
|
||||
i,
|
||||
stack()->monitor_offset(i),
|
||||
stack()->monitor_object_offset(i));
|
||||
}
|
||||
end_monitors();
|
||||
|
||||
// Frame header
|
||||
start_frame_header();
|
||||
process_oop_tmp_slot(
|
||||
state->oop_tmp_addr(), stack()->oop_tmp_slot_offset());
|
||||
process_method_slot(state->method_addr(), stack()->method_slot_offset());
|
||||
process_pc_slot(stack()->pc_slot_offset());
|
||||
end_frame_header();
|
||||
|
||||
// Local variables
|
||||
locals_integrity_checks(state);
|
||||
start_locals();
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
process_local_slot(
|
||||
i,
|
||||
state->local_addr(i),
|
||||
stack()->locals_slots_offset() + max_locals() - 1 - i);
|
||||
}
|
||||
end_locals();
|
||||
|
||||
end_frame();
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void SharkStateScanner::stack_integrity_checks(SharkState* state) {
|
||||
for (int i = 0; i < state->stack_depth(); i++) {
|
||||
if (state->stack(i)) {
|
||||
if (state->stack(i)->is_two_word())
|
||||
assert(state->stack(i - 1) == NULL, "should be");
|
||||
}
|
||||
else {
|
||||
assert(state->stack(i + 1)->is_two_word(), "should be");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharkStateScanner::locals_integrity_checks(SharkState* state) {
|
||||
for (int i = 0; i < max_locals(); i++) {
|
||||
if (state->local(i)) {
|
||||
if (state->local(i)->is_two_word())
|
||||
assert(state->local(i + 1) == NULL, "should be");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !PRODUCT
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKSTATESCANNER_HPP
|
||||
#define SHARE_VM_SHARK_SHARKSTATESCANNER_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkInvariants.hpp"
|
||||
|
||||
class SharkState;
|
||||
|
||||
class SharkStateScanner : public SharkTargetInvariants {
|
||||
protected:
|
||||
SharkStateScanner(SharkFunction* function)
|
||||
: SharkTargetInvariants(function), _stack(function->stack()) {}
|
||||
|
||||
private:
|
||||
SharkStack* _stack;
|
||||
|
||||
protected:
|
||||
SharkStack* stack() const {
|
||||
return _stack;
|
||||
}
|
||||
|
||||
// Scan the frame
|
||||
public:
|
||||
void scan(SharkState* state);
|
||||
|
||||
// Callbacks
|
||||
// Note that the offsets supplied to the various process_* callbacks
|
||||
// are specified in wordSize words from the frame's unextended_sp.
|
||||
protected:
|
||||
virtual void start_frame() {}
|
||||
|
||||
virtual void start_stack(int stack_depth) {}
|
||||
virtual void process_stack_slot(int index, SharkValue** value, int offset) {}
|
||||
virtual void end_stack() {}
|
||||
|
||||
virtual void start_monitors(int num_monitors) {}
|
||||
virtual void process_monitor(int index, int box_offset, int obj_offset) {}
|
||||
virtual void end_monitors() {}
|
||||
|
||||
virtual void start_frame_header() {}
|
||||
virtual void process_oop_tmp_slot(llvm::Value** value, int offset) {}
|
||||
virtual void process_method_slot(llvm::Value** value, int offset) {}
|
||||
virtual void process_pc_slot(int offset) {}
|
||||
virtual void end_frame_header() {}
|
||||
|
||||
virtual void start_locals() {}
|
||||
virtual void process_local_slot(int index, SharkValue** value, int offset) {}
|
||||
virtual void end_locals() {}
|
||||
|
||||
virtual void end_frame() {}
|
||||
|
||||
// Integrity checks
|
||||
private:
|
||||
void stack_integrity_checks(SharkState* state) PRODUCT_RETURN;
|
||||
void locals_integrity_checks(SharkState* state) PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKSTATESCANNER_HPP
|
File diff suppressed because it is too large
Load Diff
@ -1,447 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKTOPLEVELBLOCK_HPP
|
||||
#define SHARE_VM_SHARK_SHARKTOPLEVELBLOCK_HPP
|
||||
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "ci/ciType.hpp"
|
||||
#include "ci/ciTypeFlow.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkBlock.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkFunction.hpp"
|
||||
#include "shark/sharkState.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
class SharkTopLevelBlock : public SharkBlock {
|
||||
public:
|
||||
SharkTopLevelBlock(SharkFunction* function, ciTypeFlow::Block* ciblock)
|
||||
: SharkBlock(function),
|
||||
_function(function),
|
||||
_ciblock(ciblock),
|
||||
_entered(false),
|
||||
_has_trap(false),
|
||||
_needs_phis(false),
|
||||
_entry_state(NULL),
|
||||
_entry_block(NULL) {}
|
||||
|
||||
private:
|
||||
SharkFunction* _function;
|
||||
ciTypeFlow::Block* _ciblock;
|
||||
|
||||
public:
|
||||
SharkFunction* function() const {
|
||||
return _function;
|
||||
}
|
||||
ciTypeFlow::Block* ciblock() const {
|
||||
return _ciblock;
|
||||
}
|
||||
|
||||
// Function properties
|
||||
public:
|
||||
SharkStack* stack() const {
|
||||
return function()->stack();
|
||||
}
|
||||
|
||||
// Typeflow properties
|
||||
public:
|
||||
int index() const {
|
||||
return ciblock()->pre_order();
|
||||
}
|
||||
bool is_backedge_copy() const {
|
||||
return ciblock()->is_backedge_copy();
|
||||
}
|
||||
int stack_depth_at_entry() const {
|
||||
return ciblock()->stack_size();
|
||||
}
|
||||
ciType* local_type_at_entry(int index) const {
|
||||
return ciblock()->local_type_at(index);
|
||||
}
|
||||
ciType* stack_type_at_entry(int slot) const {
|
||||
return ciblock()->stack_type_at(slot);
|
||||
}
|
||||
int start() const {
|
||||
return ciblock()->start();
|
||||
}
|
||||
int limit() const {
|
||||
return ciblock()->limit();
|
||||
}
|
||||
bool falls_through() const {
|
||||
return ciblock()->control() == ciBlock::fall_through_bci;
|
||||
}
|
||||
int num_successors() const {
|
||||
return ciblock()->successors()->length();
|
||||
}
|
||||
SharkTopLevelBlock* successor(int index) const {
|
||||
return function()->block(ciblock()->successors()->at(index)->pre_order());
|
||||
}
|
||||
SharkTopLevelBlock* bci_successor(int bci) const;
|
||||
|
||||
// Exceptions
|
||||
private:
|
||||
GrowableArray<ciExceptionHandler*>* _exc_handlers;
|
||||
GrowableArray<SharkTopLevelBlock*>* _exceptions;
|
||||
|
||||
private:
|
||||
void compute_exceptions();
|
||||
|
||||
private:
|
||||
int num_exceptions() const {
|
||||
return _exc_handlers->length();
|
||||
}
|
||||
ciExceptionHandler* exc_handler(int index) const {
|
||||
return _exc_handlers->at(index);
|
||||
}
|
||||
SharkTopLevelBlock* exception(int index) const {
|
||||
return _exceptions->at(index);
|
||||
}
|
||||
|
||||
// Traps
|
||||
private:
|
||||
bool _has_trap;
|
||||
int _trap_request;
|
||||
int _trap_bci;
|
||||
|
||||
void set_trap(int trap_request, int trap_bci) {
|
||||
assert(!has_trap(), "shouldn't have");
|
||||
_has_trap = true;
|
||||
_trap_request = trap_request;
|
||||
_trap_bci = trap_bci;
|
||||
}
|
||||
|
||||
private:
|
||||
bool has_trap() {
|
||||
return _has_trap;
|
||||
}
|
||||
int trap_request() {
|
||||
assert(has_trap(), "should have");
|
||||
return _trap_request;
|
||||
}
|
||||
int trap_bci() {
|
||||
assert(has_trap(), "should have");
|
||||
return _trap_bci;
|
||||
}
|
||||
|
||||
private:
|
||||
void scan_for_traps();
|
||||
|
||||
private:
|
||||
bool static_field_ok_in_clinit(ciField* field);
|
||||
|
||||
// Entry state
|
||||
private:
|
||||
bool _entered;
|
||||
bool _needs_phis;
|
||||
|
||||
public:
|
||||
bool entered() const {
|
||||
return _entered;
|
||||
}
|
||||
bool needs_phis() const {
|
||||
return _needs_phis;
|
||||
}
|
||||
|
||||
private:
|
||||
void enter(SharkTopLevelBlock* predecessor, bool is_exception);
|
||||
|
||||
public:
|
||||
void enter() {
|
||||
enter(NULL, false);
|
||||
}
|
||||
|
||||
private:
|
||||
SharkState* _entry_state;
|
||||
|
||||
private:
|
||||
SharkState* entry_state();
|
||||
|
||||
private:
|
||||
llvm::BasicBlock* _entry_block;
|
||||
|
||||
public:
|
||||
llvm::BasicBlock* entry_block() const {
|
||||
return _entry_block;
|
||||
}
|
||||
|
||||
public:
|
||||
void initialize();
|
||||
|
||||
public:
|
||||
void add_incoming(SharkState* incoming_state);
|
||||
|
||||
// Method
|
||||
public:
|
||||
llvm::Value* method() {
|
||||
return current_state()->method();
|
||||
}
|
||||
|
||||
// Temporary oop storage
|
||||
public:
|
||||
void set_oop_tmp(llvm::Value* value) {
|
||||
assert(value, "value must be non-NULL (will be reset by get_oop_tmp)");
|
||||
assert(!current_state()->oop_tmp(), "oop_tmp gets and sets must match");
|
||||
current_state()->set_oop_tmp(value);
|
||||
}
|
||||
llvm::Value* get_oop_tmp() {
|
||||
llvm::Value* value = current_state()->oop_tmp();
|
||||
assert(value, "oop_tmp gets and sets must match");
|
||||
current_state()->set_oop_tmp(NULL);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Cache and decache
|
||||
private:
|
||||
void decache_for_Java_call(ciMethod* callee);
|
||||
void cache_after_Java_call(ciMethod* callee);
|
||||
void decache_for_VM_call();
|
||||
void cache_after_VM_call();
|
||||
void decache_for_trap();
|
||||
|
||||
// Monitors
|
||||
private:
|
||||
int num_monitors() {
|
||||
return current_state()->num_monitors();
|
||||
}
|
||||
int set_num_monitors(int num_monitors) {
|
||||
current_state()->set_num_monitors(num_monitors);
|
||||
}
|
||||
|
||||
// Code generation
|
||||
public:
|
||||
void emit_IR();
|
||||
|
||||
// Branch helpers
|
||||
private:
|
||||
void do_branch(int successor_index);
|
||||
|
||||
// Zero checks
|
||||
private:
|
||||
void do_zero_check(SharkValue* value);
|
||||
void zero_check_value(SharkValue* value, llvm::BasicBlock* continue_block);
|
||||
|
||||
public:
|
||||
void do_deferred_zero_check(SharkValue* value,
|
||||
int bci,
|
||||
SharkState* saved_state,
|
||||
llvm::BasicBlock* continue_block);
|
||||
// Exceptions
|
||||
private:
|
||||
llvm::Value* pending_exception_address() const {
|
||||
return builder()->CreateAddressOfStructEntry(
|
||||
thread(), Thread::pending_exception_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::oop_type()),
|
||||
"pending_exception_addr");
|
||||
}
|
||||
llvm::LoadInst* get_pending_exception() const {
|
||||
return builder()->CreateLoad(
|
||||
pending_exception_address(), "pending_exception");
|
||||
}
|
||||
void clear_pending_exception() const {
|
||||
builder()->CreateStore(LLVMValue::null(), pending_exception_address());
|
||||
}
|
||||
public:
|
||||
enum ExceptionActionMask {
|
||||
// The actual bitmasks that things test against
|
||||
EAM_CHECK = 1, // whether to check for pending exceptions
|
||||
EAM_HANDLE = 2, // whether to attempt to handle pending exceptions
|
||||
EAM_MONITOR_FUDGE = 4, // whether the monitor count needs adjusting
|
||||
|
||||
// More convenient values for passing
|
||||
EX_CHECK_NONE = 0,
|
||||
EX_CHECK_NO_CATCH = EAM_CHECK,
|
||||
EX_CHECK_FULL = EAM_CHECK | EAM_HANDLE
|
||||
};
|
||||
void check_pending_exception(int action);
|
||||
void handle_exception(llvm::Value* exception, int action);
|
||||
void marshal_exception_fast(int num_options);
|
||||
void marshal_exception_slow(int num_options);
|
||||
llvm::BasicBlock* handler_for_exception(int index);
|
||||
|
||||
// VM calls
|
||||
private:
|
||||
llvm::CallInst* call_vm(llvm::Value* callee,
|
||||
llvm::Value** args_start,
|
||||
llvm::Value** args_end,
|
||||
int exception_action) {
|
||||
decache_for_VM_call();
|
||||
stack()->CreateSetLastJavaFrame();
|
||||
llvm::CallInst *res = builder()->CreateCall(callee, llvm::makeArrayRef(args_start, args_end));
|
||||
stack()->CreateResetLastJavaFrame();
|
||||
cache_after_VM_call();
|
||||
if (exception_action & EAM_CHECK) {
|
||||
check_pending_exception(exception_action);
|
||||
current_state()->set_has_safepointed(true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::CallInst* call_vm(llvm::Value* callee,
|
||||
int exception_action) {
|
||||
llvm::Value *args[] = {thread()};
|
||||
return call_vm(callee, args, args + 1, exception_action);
|
||||
}
|
||||
llvm::CallInst* call_vm(llvm::Value* callee,
|
||||
llvm::Value* arg1,
|
||||
int exception_action) {
|
||||
llvm::Value *args[] = {thread(), arg1};
|
||||
return call_vm(callee, args, args + 2, exception_action);
|
||||
}
|
||||
llvm::CallInst* call_vm(llvm::Value* callee,
|
||||
llvm::Value* arg1,
|
||||
llvm::Value* arg2,
|
||||
int exception_action) {
|
||||
llvm::Value *args[] = {thread(), arg1, arg2};
|
||||
return call_vm(callee, args, args + 3, exception_action);
|
||||
}
|
||||
llvm::CallInst* call_vm(llvm::Value* callee,
|
||||
llvm::Value* arg1,
|
||||
llvm::Value* arg2,
|
||||
llvm::Value* arg3,
|
||||
int exception_action) {
|
||||
llvm::Value *args[] = {thread(), arg1, arg2, arg3};
|
||||
return call_vm(callee, args, args + 4, exception_action);
|
||||
}
|
||||
|
||||
// VM call oop return handling
|
||||
private:
|
||||
llvm::LoadInst* get_vm_result() const {
|
||||
llvm::Value *addr = builder()->CreateAddressOfStructEntry(
|
||||
thread(), JavaThread::vm_result_offset(),
|
||||
llvm::PointerType::getUnqual(SharkType::oop_type()),
|
||||
"vm_result_addr");
|
||||
llvm::LoadInst *result = builder()->CreateLoad(addr, "vm_result");
|
||||
builder()->CreateStore(LLVMValue::null(), addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Synchronization
|
||||
private:
|
||||
void acquire_lock(llvm::Value* lockee, int exception_action);
|
||||
void release_lock(int exception_action);
|
||||
|
||||
public:
|
||||
void acquire_method_lock();
|
||||
|
||||
// Bounds checks
|
||||
private:
|
||||
void check_bounds(SharkValue* array, SharkValue* index);
|
||||
|
||||
// Safepoints
|
||||
private:
|
||||
void maybe_add_safepoint();
|
||||
void maybe_add_backedge_safepoint();
|
||||
|
||||
// Loop safepoint removal
|
||||
private:
|
||||
bool _can_reach_visited;
|
||||
|
||||
bool can_reach(SharkTopLevelBlock* other);
|
||||
bool can_reach_helper(SharkTopLevelBlock* other);
|
||||
|
||||
// Traps
|
||||
private:
|
||||
llvm::BasicBlock* make_trap(int trap_bci, int trap_request);
|
||||
void do_trap(int trap_request);
|
||||
|
||||
// Returns
|
||||
private:
|
||||
void call_register_finalizer(llvm::Value* receiver);
|
||||
void handle_return(BasicType type, llvm::Value* exception);
|
||||
|
||||
// arraylength
|
||||
private:
|
||||
void do_arraylength();
|
||||
|
||||
// *aload and *astore
|
||||
private:
|
||||
void do_aload(BasicType basic_type);
|
||||
void do_astore(BasicType basic_type);
|
||||
|
||||
// *return and athrow
|
||||
private:
|
||||
void do_return(BasicType type);
|
||||
void do_athrow();
|
||||
|
||||
// goto*
|
||||
private:
|
||||
void do_goto();
|
||||
|
||||
// jsr* and ret
|
||||
private:
|
||||
void do_jsr();
|
||||
void do_ret();
|
||||
|
||||
// if*
|
||||
private:
|
||||
void do_if_helper(llvm::ICmpInst::Predicate p,
|
||||
llvm::Value* b,
|
||||
llvm::Value* a,
|
||||
SharkState* if_taken_state,
|
||||
SharkState* not_taken_state);
|
||||
void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
|
||||
|
||||
// tableswitch and lookupswitch
|
||||
private:
|
||||
void do_switch();
|
||||
|
||||
// invoke*
|
||||
private:
|
||||
ciMethod* improve_virtual_call(ciMethod* caller,
|
||||
ciInstanceKlass* klass,
|
||||
ciMethod* dest_method,
|
||||
ciType* receiver_type);
|
||||
llvm::Value* get_direct_callee(ciMethod* method);
|
||||
llvm::Value* get_virtual_callee(SharkValue* receiver, int vtable_index);
|
||||
llvm::Value* get_interface_callee(SharkValue* receiver, ciMethod* method);
|
||||
|
||||
void do_call();
|
||||
|
||||
// checkcast and instanceof
|
||||
private:
|
||||
bool static_subtype_check(ciKlass* check_klass, ciKlass* object_klass);
|
||||
void do_full_instance_check(ciKlass* klass);
|
||||
void do_trapping_instance_check(ciKlass* klass);
|
||||
|
||||
void do_instance_check();
|
||||
bool maybe_do_instanceof_if();
|
||||
|
||||
// new and *newarray
|
||||
private:
|
||||
void do_new();
|
||||
void do_newarray();
|
||||
void do_anewarray();
|
||||
void do_multianewarray();
|
||||
|
||||
// monitorenter and monitorexit
|
||||
private:
|
||||
void do_monitorenter();
|
||||
void do_monitorexit();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKTOPLEVELBLOCK_HPP
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKTYPE_HPP
|
||||
#define SHARE_VM_SHARK_SHARKTYPE_HPP
|
||||
|
||||
#include "ci/ciType.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/sharkContext.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
class SharkType : public AllStatic {
|
||||
private:
|
||||
static SharkContext& context() {
|
||||
return SharkContext::current();
|
||||
}
|
||||
|
||||
// Basic types
|
||||
public:
|
||||
static llvm::Type* void_type() {
|
||||
return context().void_type();
|
||||
}
|
||||
static llvm::IntegerType* bit_type() {
|
||||
return context().bit_type();
|
||||
}
|
||||
static llvm::IntegerType* jbyte_type() {
|
||||
return context().jbyte_type();
|
||||
}
|
||||
static llvm::IntegerType* jshort_type() {
|
||||
return context().jshort_type();
|
||||
}
|
||||
static llvm::IntegerType* jint_type() {
|
||||
return context().jint_type();
|
||||
}
|
||||
static llvm::IntegerType* jlong_type() {
|
||||
return context().jlong_type();
|
||||
}
|
||||
static llvm::Type* jfloat_type() {
|
||||
return context().jfloat_type();
|
||||
}
|
||||
static llvm::Type* jdouble_type() {
|
||||
return context().jdouble_type();
|
||||
}
|
||||
static llvm::IntegerType* intptr_type() {
|
||||
return context().intptr_type();
|
||||
}
|
||||
|
||||
// Compound types
|
||||
public:
|
||||
static llvm::PointerType* itableOffsetEntry_type() {
|
||||
return context().itableOffsetEntry_type();
|
||||
}
|
||||
static llvm::PointerType* jniEnv_type() {
|
||||
return context().jniEnv_type();
|
||||
}
|
||||
static llvm::PointerType* jniHandleBlock_type() {
|
||||
return context().jniHandleBlock_type();
|
||||
}
|
||||
static llvm::PointerType* Metadata_type() {
|
||||
return context().Metadata_type();
|
||||
}
|
||||
static llvm::PointerType* klass_type() {
|
||||
return context().klass_type();
|
||||
}
|
||||
static llvm::PointerType* Method_type() {
|
||||
return context().Method_type();
|
||||
}
|
||||
static llvm::ArrayType* monitor_type() {
|
||||
return context().monitor_type();
|
||||
}
|
||||
static llvm::PointerType* oop_type() {
|
||||
return context().oop_type();
|
||||
}
|
||||
static llvm::PointerType* thread_type() {
|
||||
return context().thread_type();
|
||||
}
|
||||
static llvm::PointerType* zeroStack_type() {
|
||||
return context().zeroStack_type();
|
||||
}
|
||||
static llvm::FunctionType* entry_point_type() {
|
||||
return context().entry_point_type();
|
||||
}
|
||||
static llvm::FunctionType* osr_entry_point_type() {
|
||||
return context().osr_entry_point_type();
|
||||
}
|
||||
|
||||
// Mappings
|
||||
public:
|
||||
static llvm::Type* to_stackType(BasicType type) {
|
||||
return context().to_stackType(type);
|
||||
}
|
||||
static llvm::Type* to_stackType(ciType* type) {
|
||||
return to_stackType(type->basic_type());
|
||||
}
|
||||
static llvm::Type* to_arrayType(BasicType type) {
|
||||
return context().to_arrayType(type);
|
||||
}
|
||||
static llvm::Type* to_arrayType(ciType* type) {
|
||||
return to_arrayType(type->basic_type());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKTYPE_HPP
|
@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "ci/ciType.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkBuilder.hpp"
|
||||
#include "shark/sharkValue.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// Cloning
|
||||
|
||||
SharkValue* SharkNormalValue::clone() const {
|
||||
return SharkValue::create_generic(type(), generic_value(), zero_checked());
|
||||
}
|
||||
SharkValue* SharkPHIValue::clone() const {
|
||||
return SharkValue::create_phi(type(), (PHINode *) generic_value(), this);
|
||||
}
|
||||
SharkValue* SharkAddressValue::clone() const {
|
||||
return SharkValue::address_constant(address_value());
|
||||
}
|
||||
|
||||
// Casting
|
||||
|
||||
bool SharkValue::is_phi() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkPHIValue::is_phi() const {
|
||||
return true;
|
||||
}
|
||||
SharkPHIValue* SharkValue::as_phi() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
SharkPHIValue* SharkPHIValue::as_phi() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Comparison
|
||||
|
||||
bool SharkNormalValue::equal_to(SharkValue *other) const {
|
||||
return (this->type() == other->type() &&
|
||||
this->generic_value() == other->generic_value() &&
|
||||
this->zero_checked() == other->zero_checked());
|
||||
}
|
||||
bool SharkAddressValue::equal_to(SharkValue *other) const {
|
||||
return (this->address_value() == other->address_value());
|
||||
}
|
||||
|
||||
// Type access
|
||||
|
||||
ciType* SharkValue::type() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
ciType* SharkNormalValue::type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
BasicType SharkNormalValue::basic_type() const {
|
||||
return type()->basic_type();
|
||||
}
|
||||
BasicType SharkAddressValue::basic_type() const {
|
||||
return T_ADDRESS;
|
||||
}
|
||||
|
||||
int SharkNormalValue::size() const {
|
||||
return type()->size();
|
||||
}
|
||||
int SharkAddressValue::size() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool SharkValue::is_jint() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_jlong() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_jfloat() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_jdouble() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_jobject() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_jarray() const {
|
||||
return false;
|
||||
}
|
||||
bool SharkValue::is_address() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SharkNormalValue::is_jint() const {
|
||||
return llvm_value()->getType() == SharkType::jint_type();
|
||||
}
|
||||
bool SharkNormalValue::is_jlong() const {
|
||||
return llvm_value()->getType() == SharkType::jlong_type();
|
||||
}
|
||||
bool SharkNormalValue::is_jfloat() const {
|
||||
return llvm_value()->getType() == SharkType::jfloat_type();
|
||||
}
|
||||
bool SharkNormalValue::is_jdouble() const {
|
||||
return llvm_value()->getType() == SharkType::jdouble_type();
|
||||
}
|
||||
bool SharkNormalValue::is_jobject() const {
|
||||
return llvm_value()->getType() == SharkType::oop_type();
|
||||
}
|
||||
bool SharkNormalValue::is_jarray() const {
|
||||
return basic_type() == T_ARRAY;
|
||||
}
|
||||
bool SharkAddressValue::is_address() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Typed conversions from SharkValues
|
||||
|
||||
Value* SharkValue::jint_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkValue::jlong_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkValue::jfloat_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkValue::jdouble_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkValue::jobject_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkValue::jarray_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
int SharkValue::address_value() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
Value* SharkNormalValue::jint_value() const {
|
||||
assert(is_jint(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkNormalValue::jlong_value() const {
|
||||
assert(is_jlong(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkNormalValue::jfloat_value() const {
|
||||
assert(is_jfloat(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkNormalValue::jdouble_value() const {
|
||||
assert(is_jdouble(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkNormalValue::jobject_value() const {
|
||||
assert(is_jobject(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkNormalValue::jarray_value() const {
|
||||
// XXX assert(is_jarray(), "should be");
|
||||
// XXX http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=324
|
||||
assert(is_jobject(), "should be");
|
||||
return llvm_value();
|
||||
}
|
||||
int SharkAddressValue::address_value() const {
|
||||
return _bci;
|
||||
}
|
||||
|
||||
// Type-losing conversions -- use with care!
|
||||
|
||||
Value* SharkNormalValue::generic_value() const {
|
||||
return llvm_value();
|
||||
}
|
||||
Value* SharkAddressValue::generic_value() const {
|
||||
return LLVMValue::intptr_constant(address_value());
|
||||
}
|
||||
|
||||
Value* SharkValue::intptr_value(SharkBuilder* builder) const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
Value* SharkNormalValue::intptr_value(SharkBuilder* builder) const {
|
||||
return builder->CreatePtrToInt(jobject_value(), SharkType::intptr_type());
|
||||
}
|
||||
|
||||
// Phi-style stuff for SharkPHIState::add_incoming
|
||||
|
||||
void SharkValue::addIncoming(SharkValue *value, BasicBlock* block) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
void SharkPHIValue::addIncoming(SharkValue *value, BasicBlock* block) {
|
||||
assert(!is_clone(), "shouldn't be");
|
||||
((llvm::PHINode *) generic_value())->addIncoming(
|
||||
value->generic_value(), block);
|
||||
if (!value->zero_checked())
|
||||
_all_incomers_zero_checked = false;
|
||||
}
|
||||
void SharkAddressValue::addIncoming(SharkValue *value, BasicBlock* block) {
|
||||
assert(this->equal_to(value), "should be");
|
||||
}
|
||||
|
||||
// Phi-style stuff for SharkState::merge
|
||||
|
||||
SharkValue* SharkNormalValue::merge(SharkBuilder* builder,
|
||||
SharkValue* other,
|
||||
BasicBlock* other_block,
|
||||
BasicBlock* this_block,
|
||||
const char* name) {
|
||||
assert(type() == other->type(), "should be");
|
||||
assert(zero_checked() == other->zero_checked(), "should be");
|
||||
|
||||
PHINode *phi = builder->CreatePHI(SharkType::to_stackType(type()), 0, name);
|
||||
phi->addIncoming(this->generic_value(), this_block);
|
||||
phi->addIncoming(other->generic_value(), other_block);
|
||||
return SharkValue::create_generic(type(), phi, zero_checked());
|
||||
}
|
||||
SharkValue* SharkAddressValue::merge(SharkBuilder* builder,
|
||||
SharkValue* other,
|
||||
BasicBlock* other_block,
|
||||
BasicBlock* this_block,
|
||||
const char* name) {
|
||||
assert(this->equal_to(other), "should be");
|
||||
return this;
|
||||
}
|
||||
|
||||
// Repeated null and divide-by-zero check removal
|
||||
|
||||
bool SharkValue::zero_checked() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
void SharkValue::set_zero_checked(bool zero_checked) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
bool SharkNormalValue::zero_checked() const {
|
||||
return _zero_checked;
|
||||
}
|
||||
void SharkNormalValue::set_zero_checked(bool zero_checked) {
|
||||
_zero_checked = zero_checked;
|
||||
}
|
@ -1,343 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARKVALUE_HPP
|
||||
#define SHARE_VM_SHARK_SHARKVALUE_HPP
|
||||
|
||||
#include "ci/ciType.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "shark/llvmHeaders.hpp"
|
||||
#include "shark/llvmValue.hpp"
|
||||
#include "shark/sharkType.hpp"
|
||||
|
||||
// Items on the stack and in local variables are tracked using
|
||||
// SharkValue objects.
|
||||
//
|
||||
// All SharkValues are one of two core types, SharkNormalValue
|
||||
// and SharkAddressValue, but no code outside this file should
|
||||
// ever refer to those directly. The split is because of the
|
||||
// way JSRs are handled: the typeflow pass expands them into
|
||||
// multiple copies, so the return addresses pushed by jsr and
|
||||
// popped by ret only exist at compile time. Having separate
|
||||
// classes for these allows us to check that our jsr handling
|
||||
// is correct, via assertions.
|
||||
//
|
||||
// There is one more type, SharkPHIValue, which is a subclass
|
||||
// of SharkNormalValue with a couple of extra methods. Use of
|
||||
// SharkPHIValue outside of this file is acceptable, so long
|
||||
// as it is obtained via SharkValue::as_phi().
|
||||
|
||||
class SharkBuilder;
|
||||
class SharkPHIValue;
|
||||
|
||||
class SharkValue : public ResourceObj {
|
||||
protected:
|
||||
SharkValue() {}
|
||||
|
||||
// Cloning
|
||||
public:
|
||||
virtual SharkValue* clone() const = 0;
|
||||
|
||||
// Casting
|
||||
public:
|
||||
virtual bool is_phi() const;
|
||||
virtual SharkPHIValue* as_phi();
|
||||
|
||||
// Comparison
|
||||
public:
|
||||
virtual bool equal_to(SharkValue* other) const = 0;
|
||||
|
||||
// Type access
|
||||
public:
|
||||
virtual BasicType basic_type() const = 0;
|
||||
virtual ciType* type() const;
|
||||
|
||||
virtual bool is_jint() const;
|
||||
virtual bool is_jlong() const;
|
||||
virtual bool is_jfloat() const;
|
||||
virtual bool is_jdouble() const;
|
||||
virtual bool is_jobject() const;
|
||||
virtual bool is_jarray() const;
|
||||
virtual bool is_address() const;
|
||||
|
||||
virtual int size() const = 0;
|
||||
|
||||
bool is_one_word() const {
|
||||
return size() == 1;
|
||||
}
|
||||
bool is_two_word() const {
|
||||
return size() == 2;
|
||||
}
|
||||
|
||||
// Typed conversion from SharkValues
|
||||
public:
|
||||
virtual llvm::Value* jint_value() const;
|
||||
virtual llvm::Value* jlong_value() const;
|
||||
virtual llvm::Value* jfloat_value() const;
|
||||
virtual llvm::Value* jdouble_value() const;
|
||||
virtual llvm::Value* jobject_value() const;
|
||||
virtual llvm::Value* jarray_value() const;
|
||||
virtual int address_value() const;
|
||||
|
||||
// Typed conversion to SharkValues
|
||||
public:
|
||||
static SharkValue* create_jint(llvm::Value* value, bool zero_checked) {
|
||||
assert(value->getType() == SharkType::jint_type(), "should be");
|
||||
return create_generic(ciType::make(T_INT), value, zero_checked);
|
||||
}
|
||||
static SharkValue* create_jlong(llvm::Value* value, bool zero_checked) {
|
||||
assert(value->getType() == SharkType::jlong_type(), "should be");
|
||||
return create_generic(ciType::make(T_LONG), value, zero_checked);
|
||||
}
|
||||
static SharkValue* create_jfloat(llvm::Value* value) {
|
||||
assert(value->getType() == SharkType::jfloat_type(), "should be");
|
||||
return create_generic(ciType::make(T_FLOAT), value, false);
|
||||
}
|
||||
static SharkValue* create_jdouble(llvm::Value* value) {
|
||||
assert(value->getType() == SharkType::jdouble_type(), "should be");
|
||||
return create_generic(ciType::make(T_DOUBLE), value, false);
|
||||
}
|
||||
static SharkValue* create_jobject(llvm::Value* value, bool zero_checked) {
|
||||
assert(value->getType() == SharkType::oop_type(), "should be");
|
||||
return create_generic(ciType::make(T_OBJECT), value, zero_checked);
|
||||
}
|
||||
|
||||
// Typed conversion from constants of various types
|
||||
public:
|
||||
static SharkValue* jint_constant(jint value) {
|
||||
return create_jint(LLVMValue::jint_constant(value), value != 0);
|
||||
}
|
||||
static SharkValue* jlong_constant(jlong value) {
|
||||
return create_jlong(LLVMValue::jlong_constant(value), value != 0);
|
||||
}
|
||||
static SharkValue* jfloat_constant(jfloat value) {
|
||||
return create_jfloat(LLVMValue::jfloat_constant(value));
|
||||
}
|
||||
static SharkValue* jdouble_constant(jdouble value) {
|
||||
return create_jdouble(LLVMValue::jdouble_constant(value));
|
||||
}
|
||||
static SharkValue* null() {
|
||||
return create_jobject(LLVMValue::null(), false);
|
||||
}
|
||||
static inline SharkValue* address_constant(int bci);
|
||||
|
||||
// Type-losing conversions -- use with care!
|
||||
public:
|
||||
virtual llvm::Value* generic_value() const = 0;
|
||||
virtual llvm::Value* intptr_value(SharkBuilder* builder) const;
|
||||
|
||||
static inline SharkValue* create_generic(ciType* type,
|
||||
llvm::Value* value,
|
||||
bool zero_checked);
|
||||
static inline SharkValue* create_phi(ciType* type,
|
||||
llvm::PHINode* phi,
|
||||
const SharkPHIValue* parent = NULL);
|
||||
|
||||
// Phi-style stuff
|
||||
public:
|
||||
virtual void addIncoming(SharkValue* value, llvm::BasicBlock* block);
|
||||
virtual SharkValue* merge(SharkBuilder* builder,
|
||||
SharkValue* other,
|
||||
llvm::BasicBlock* other_block,
|
||||
llvm::BasicBlock* this_block,
|
||||
const char* name) = 0;
|
||||
|
||||
// Repeated null and divide-by-zero check removal
|
||||
public:
|
||||
virtual bool zero_checked() const;
|
||||
virtual void set_zero_checked(bool zero_checked);
|
||||
};
|
||||
|
||||
class SharkNormalValue : public SharkValue {
|
||||
friend class SharkValue;
|
||||
|
||||
protected:
|
||||
SharkNormalValue(ciType* type, llvm::Value* value, bool zero_checked)
|
||||
: _type(type), _llvm_value(value), _zero_checked(zero_checked) {}
|
||||
|
||||
private:
|
||||
ciType* _type;
|
||||
llvm::Value* _llvm_value;
|
||||
bool _zero_checked;
|
||||
|
||||
private:
|
||||
llvm::Value* llvm_value() const {
|
||||
return _llvm_value;
|
||||
}
|
||||
|
||||
// Cloning
|
||||
public:
|
||||
SharkValue* clone() const;
|
||||
|
||||
// Comparison
|
||||
public:
|
||||
bool equal_to(SharkValue* other) const;
|
||||
|
||||
// Type access
|
||||
public:
|
||||
ciType* type() const;
|
||||
BasicType basic_type() const;
|
||||
int size() const;
|
||||
|
||||
public:
|
||||
bool is_jint() const;
|
||||
bool is_jlong() const;
|
||||
bool is_jfloat() const;
|
||||
bool is_jdouble() const;
|
||||
bool is_jobject() const;
|
||||
bool is_jarray() const;
|
||||
|
||||
// Typed conversions to LLVM values
|
||||
public:
|
||||
llvm::Value* jint_value() const;
|
||||
llvm::Value* jlong_value() const;
|
||||
llvm::Value* jfloat_value() const;
|
||||
llvm::Value* jdouble_value() const;
|
||||
llvm::Value* jobject_value() const;
|
||||
llvm::Value* jarray_value() const;
|
||||
|
||||
// Type-losing conversions, use with care
|
||||
public:
|
||||
llvm::Value* generic_value() const;
|
||||
llvm::Value* intptr_value(SharkBuilder* builder) const;
|
||||
|
||||
// Phi-style stuff
|
||||
public:
|
||||
SharkValue* merge(SharkBuilder* builder,
|
||||
SharkValue* other,
|
||||
llvm::BasicBlock* other_block,
|
||||
llvm::BasicBlock* this_block,
|
||||
const char* name);
|
||||
|
||||
// Repeated null and divide-by-zero check removal
|
||||
public:
|
||||
bool zero_checked() const;
|
||||
void set_zero_checked(bool zero_checked);
|
||||
};
|
||||
|
||||
class SharkPHIValue : public SharkNormalValue {
|
||||
friend class SharkValue;
|
||||
|
||||
protected:
|
||||
SharkPHIValue(ciType* type, llvm::PHINode* phi, const SharkPHIValue *parent)
|
||||
: SharkNormalValue(type, phi, parent && parent->zero_checked()),
|
||||
_parent(parent),
|
||||
_all_incomers_zero_checked(true) {}
|
||||
|
||||
private:
|
||||
const SharkPHIValue* _parent;
|
||||
bool _all_incomers_zero_checked;
|
||||
|
||||
private:
|
||||
const SharkPHIValue* parent() const {
|
||||
return _parent;
|
||||
}
|
||||
bool is_clone() const {
|
||||
return parent() != NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
bool all_incomers_zero_checked() const {
|
||||
if (is_clone())
|
||||
return parent()->all_incomers_zero_checked();
|
||||
|
||||
return _all_incomers_zero_checked;
|
||||
}
|
||||
|
||||
// Cloning
|
||||
public:
|
||||
SharkValue* clone() const;
|
||||
|
||||
// Casting
|
||||
public:
|
||||
bool is_phi() const;
|
||||
SharkPHIValue* as_phi();
|
||||
|
||||
// Phi-style stuff
|
||||
public:
|
||||
void addIncoming(SharkValue *value, llvm::BasicBlock* block);
|
||||
};
|
||||
|
||||
class SharkAddressValue : public SharkValue {
|
||||
friend class SharkValue;
|
||||
|
||||
protected:
|
||||
SharkAddressValue(int bci)
|
||||
: _bci(bci) {}
|
||||
|
||||
private:
|
||||
int _bci;
|
||||
|
||||
// Cloning
|
||||
public:
|
||||
SharkValue* clone() const;
|
||||
|
||||
// Comparison
|
||||
public:
|
||||
bool equal_to(SharkValue* other) const;
|
||||
|
||||
// Type access
|
||||
public:
|
||||
BasicType basic_type() const;
|
||||
int size() const;
|
||||
bool is_address() const;
|
||||
|
||||
// Typed conversion from SharkValues
|
||||
public:
|
||||
int address_value() const;
|
||||
|
||||
// Type-losing conversion -- use with care!
|
||||
public:
|
||||
llvm::Value* generic_value() const;
|
||||
|
||||
// Phi-style stuff
|
||||
public:
|
||||
void addIncoming(SharkValue *value, llvm::BasicBlock* block);
|
||||
SharkValue* merge(SharkBuilder* builder,
|
||||
SharkValue* other,
|
||||
llvm::BasicBlock* other_block,
|
||||
llvm::BasicBlock* this_block,
|
||||
const char* name);
|
||||
};
|
||||
|
||||
// SharkValue methods that can't be declared above
|
||||
|
||||
inline SharkValue* SharkValue::create_generic(ciType* type,
|
||||
llvm::Value* value,
|
||||
bool zero_checked) {
|
||||
return new SharkNormalValue(type, value, zero_checked);
|
||||
}
|
||||
|
||||
inline SharkValue* SharkValue::create_phi(ciType* type,
|
||||
llvm::PHINode* phi,
|
||||
const SharkPHIValue* parent) {
|
||||
return new SharkPHIValue(type, phi, parent);
|
||||
}
|
||||
|
||||
inline SharkValue* SharkValue::address_constant(int bci) {
|
||||
return new SharkAddressValue(bci);
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARKVALUE_HPP
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "shark/shark_globals.hpp"
|
||||
|
||||
SHARK_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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_SHARK_SHARK_GLOBALS_HPP
|
||||
#define SHARE_VM_SHARK_SHARK_GLOBALS_HPP
|
||||
|
||||
#include "runtime/globals.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#ifdef ZERO
|
||||
# include "shark_globals_zero.hpp"
|
||||
#endif
|
||||
|
||||
#define SHARK_FLAGS(develop, develop_pd, product, product_pd, diagnostic, diagnostic_pd, notproduct) \
|
||||
\
|
||||
product(intx, MaxNodeLimit, 65000, \
|
||||
"Maximum number of nodes") \
|
||||
\
|
||||
/* inlining */ \
|
||||
product(intx, SharkMaxInlineSize, 32, \
|
||||
"Maximum bytecode size of methods to inline when using Shark") \
|
||||
\
|
||||
product(bool, EliminateNestedLocks, true, \
|
||||
"Eliminate nested locks of the same object when possible") \
|
||||
\
|
||||
product(ccstr, SharkOptimizationLevel, "Default", \
|
||||
"The optimization level passed to LLVM, possible values: None, Less, Default and Agressive") \
|
||||
\
|
||||
/* compiler debugging */ \
|
||||
develop(ccstr, SharkPrintTypeflowOf, NULL, \
|
||||
"Print the typeflow of the specified method") \
|
||||
\
|
||||
diagnostic(ccstr, SharkPrintBitcodeOf, NULL, \
|
||||
"Print the LLVM bitcode of the specified method") \
|
||||
\
|
||||
diagnostic(ccstr, SharkPrintAsmOf, NULL, \
|
||||
"Print the asm of the specified method") \
|
||||
\
|
||||
develop(bool, SharkTraceBytecodes, false, \
|
||||
"Trace bytecode compilation") \
|
||||
\
|
||||
diagnostic(bool, SharkTraceInstalls, false, \
|
||||
"Trace method installation") \
|
||||
\
|
||||
diagnostic(bool, SharkPerformanceWarnings, false, \
|
||||
"Warn about things that could be made faster") \
|
||||
\
|
||||
develop(ccstr, SharkVerifyFunction, NULL, \
|
||||
"Runs LLVM verify over LLVM IR") \
|
||||
|
||||
|
||||
SHARK_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_PD_DIAGNOSTIC_FLAG,
|
||||
DECLARE_NOTPRODUCT_FLAG)
|
||||
|
||||
#endif // SHARE_VM_SHARK_SHARK_GLOBALS_HPP
|
@ -346,14 +346,6 @@
|
||||
#define NOT_ZERO(code) code
|
||||
#endif
|
||||
|
||||
#if defined(SHARK)
|
||||
#define SHARK_ONLY(code) code
|
||||
#define NOT_SHARK(code)
|
||||
#else
|
||||
#define SHARK_ONLY(code)
|
||||
#define NOT_SHARK(code) code
|
||||
#endif
|
||||
|
||||
#if defined(IA32) || defined(AMD64)
|
||||
#define X86
|
||||
#define X86_ONLY(code) code
|
||||
|
@ -189,20 +189,10 @@ void VMError::print_stack_trace(outputStream* st, JavaThread* jt,
|
||||
if (!has_last_Java_frame)
|
||||
jt->set_last_Java_frame();
|
||||
st->print("Java frames:");
|
||||
|
||||
// If the top frame is a Shark frame and the frame anchor isn't
|
||||
// set up then it's possible that the information in the frame
|
||||
// is garbage: it could be from a previous decache, or it could
|
||||
// simply have never been written. So we print a warning...
|
||||
StackFrameStream sfs(jt);
|
||||
if (!has_last_Java_frame && !sfs.is_done()) {
|
||||
if (sfs.current()->zeroframe()->is_shark_frame()) {
|
||||
st->print(" (TOP FRAME MAY BE JUNK)");
|
||||
}
|
||||
}
|
||||
st->cr();
|
||||
|
||||
// Print the frames
|
||||
StackFrameStream sfs(jt);
|
||||
for(int i = 0; !sfs.is_done(); sfs.next(), i++) {
|
||||
sfs.current()->zero_print_on_error(i, st, buf, buflen);
|
||||
st->cr();
|
||||
|
@ -51,7 +51,7 @@ public abstract class CompilerWhiteBoxTest {
|
||||
public static final int COMP_LEVEL_LIMITED_PROFILE = 2;
|
||||
/** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */
|
||||
public static final int COMP_LEVEL_FULL_PROFILE = 3;
|
||||
/** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */
|
||||
/** {@code CompLevel::CompLevel_full_optimization} -- C2 */
|
||||
public static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
|
||||
/** Maximal value for CompLevel */
|
||||
public static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
|
||||
|
Loading…
x
Reference in New Issue
Block a user