mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-29 00:02:34 +00:00
6976186: integrate Shark HotSpot changes
Shark is a JIT compiler for Zero that uses the LLVM compiler infrastructure. Reviewed-by: kvn, twisti
This commit is contained in:
parent
c9ac8cc788
commit
d7310fb0f7
@ -85,6 +85,7 @@ C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1
|
||||
C2_VM_TARGETS=product fastdebug optimized jvmg
|
||||
KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel
|
||||
ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero
|
||||
SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark
|
||||
|
||||
# JDK directory list
|
||||
JDK_DIRS=bin include jre lib demo
|
||||
@ -107,6 +108,12 @@ all_fastdebugzero: fastdebugzero docs export_fastdebug
|
||||
all_debugzero: jvmgzero docs export_debug
|
||||
all_optimizedzero: optimizedzero docs export_optimized
|
||||
|
||||
allshark: all_productshark all_fastdebugshark
|
||||
all_productshark: productshark docs export_product
|
||||
all_fastdebugshark: fastdebugshark docs export_fastdebug
|
||||
all_debugshark: jvmgshark docs export_debug
|
||||
all_optimizedshark: optimizedshark docs export_optimized
|
||||
|
||||
# Do everything
|
||||
world: all create_jdk
|
||||
|
||||
@ -137,6 +144,10 @@ $(ZERO_VM_TARGETS):
|
||||
$(CD) $(GAMMADIR)/make; \
|
||||
$(MAKE) VM_TARGET=$@ generic_buildzero $(ALT_OUT)
|
||||
|
||||
$(SHARK_VM_TARGETS):
|
||||
$(CD) $(GAMMADIR)/make; \
|
||||
$(MAKE) VM_TARGET=$@ generic_buildshark $(ALT_OUT)
|
||||
|
||||
# Build compiler1 (client) rule, different for platforms
|
||||
generic_build1:
|
||||
$(MKDIR) -p $(OUTPUTDIR)
|
||||
@ -203,6 +214,12 @@ generic_buildzero:
|
||||
$(MAKE) -f $(ABS_OS_MAKEFILE) \
|
||||
$(MAKE_ARGS) $(VM_TARGET)
|
||||
|
||||
generic_buildshark:
|
||||
$(MKDIR) -p $(OUTPUTDIR)
|
||||
$(CD) $(OUTPUTDIR); \
|
||||
$(MAKE) -f $(ABS_OS_MAKEFILE) \
|
||||
$(MAKE_ARGS) $(VM_TARGET)
|
||||
|
||||
# Export file rule
|
||||
generic_export: $(EXPORT_LIST)
|
||||
export_product:
|
||||
@ -234,15 +251,22 @@ C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1
|
||||
C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2
|
||||
KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel
|
||||
ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero
|
||||
SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark
|
||||
C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR)
|
||||
C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR)
|
||||
KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR)
|
||||
ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR)
|
||||
SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR)
|
||||
|
||||
# Misc files and generated files need to come from C1 or C2 area
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
ifeq ($(SHARK_BUILD), true)
|
||||
MISC_DIR=$(SHARK_DIR)
|
||||
GEN_DIR=$(SHARK_BASE_DIR)/generated
|
||||
else
|
||||
MISC_DIR=$(ZERO_DIR)
|
||||
GEN_DIR=$(ZERO_BASE_DIR)/generated
|
||||
endif
|
||||
else
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
MISC_DIR=$(C1_DIR)
|
||||
@ -296,10 +320,17 @@ endif
|
||||
# Shared Library
|
||||
ifneq ($(OSNAME),windows)
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
ifeq ($(SHARK_BUILD), true)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(SHARK_DIR)/%.so
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.so: $(SHARK_DIR)/%.so
|
||||
$(install-file)
|
||||
else
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(ZERO_DIR)/%.so
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.so: $(ZERO_DIR)/%.so
|
||||
$(install-file)
|
||||
endif
|
||||
else
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(C1_DIR)/%.so
|
||||
$(install-file)
|
||||
@ -356,6 +387,7 @@ clean_build:
|
||||
$(RM) -r $(C2_DIR)
|
||||
$(RM) -r $(KERNEL_DIR)
|
||||
$(RM) -r $(ZERO_DIR)
|
||||
$(RM) -r $(SHARK_DIR)
|
||||
clean_export:
|
||||
$(RM) -r $(EXPORT_PATH)
|
||||
clean_jdk:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -168,6 +168,13 @@ VARIANTARCH = $(subst i386,i486,$(ZERO_LIBARCH))
|
||||
# profiledzero zero <os>_<arch>_zero/profiled
|
||||
# productzero zero <os>_<arch>_zero/product
|
||||
#
|
||||
# debugshark shark <os>_<arch>_shark/debug
|
||||
# fastdebugshark shark <os>_<arch>_shark/fastdebug
|
||||
# jvmgshark shark <os>_<arch>_shark/jvmg
|
||||
# optimizedshark shark <os>_<arch>_shark/optimized
|
||||
# profiledshark shark <os>_<arch>_shark/profiled
|
||||
# productshark shark <os>_<arch>_shark/product
|
||||
#
|
||||
# What you get with each target:
|
||||
#
|
||||
# debug* - "thin" libjvm_g - debug info linked into the gamma_g launcher
|
||||
@ -191,12 +198,14 @@ SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS))
|
||||
SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS))
|
||||
SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS))
|
||||
SUBDIRS_ZERO = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS))
|
||||
SUBDIRS_SHARK = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS))
|
||||
|
||||
TARGETS_C2 = $(TARGETS)
|
||||
TARGETS_C1 = $(addsuffix 1,$(TARGETS))
|
||||
TARGETS_TIERED = $(addsuffix tiered,$(TARGETS))
|
||||
TARGETS_CORE = $(addsuffix core,$(TARGETS))
|
||||
TARGETS_ZERO = $(addsuffix zero,$(TARGETS))
|
||||
TARGETS_SHARK = $(addsuffix shark,$(TARGETS))
|
||||
|
||||
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
|
||||
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
|
||||
@ -213,6 +222,7 @@ all:
|
||||
@echo " $(TARGETS_C1)"
|
||||
@echo " $(TARGETS_CORE)"
|
||||
@echo " $(TARGETS_ZERO)"
|
||||
@echo " $(TARGETS_SHARK)"
|
||||
|
||||
checks: check_os_version check_j2se_version
|
||||
|
||||
@ -266,6 +276,10 @@ $(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
|
||||
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
|
||||
$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
|
||||
|
||||
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
|
||||
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
|
||||
$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
|
||||
|
||||
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
|
||||
$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
|
||||
|
||||
@ -306,11 +320,19 @@ ifdef INSTALL
|
||||
cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install
|
||||
endif
|
||||
|
||||
$(TARGETS_SHARK): $(SUBDIRS_SHARK)
|
||||
cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS)
|
||||
cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && ./test_gamma
|
||||
ifdef INSTALL
|
||||
cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install
|
||||
endif
|
||||
|
||||
# Just build the tree, and nothing else:
|
||||
tree: $(SUBDIRS_C2)
|
||||
tree1: $(SUBDIRS_C1)
|
||||
treecore: $(SUBDIRS_CORE)
|
||||
treezero: $(SUBDIRS_ZERO)
|
||||
treeshark: $(SUBDIRS_SHARK)
|
||||
|
||||
# Doc target. This is the same for all build options.
|
||||
# Hence create a docs directory beside ...$(ARCH)_[...]
|
||||
@ -327,20 +349,22 @@ core: jvmgcore productcore
|
||||
|
||||
zero: jvmgzero productzero
|
||||
|
||||
shark: jvmgshark productshark
|
||||
|
||||
clean_docs:
|
||||
rm -rf $(SUBDIR_DOCS)
|
||||
|
||||
clean_compiler1 clean_compiler2 clean_core clean_zero:
|
||||
clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark:
|
||||
rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@)
|
||||
|
||||
clean: clean_compiler2 clean_compiler1 clean_core clean_zero clean_docs
|
||||
clean: clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_docs
|
||||
|
||||
include $(GAMMADIR)/make/$(OSNAME)/makefiles/cscope.make
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO)
|
||||
.PHONY: tree tree1 treecore treezero
|
||||
.PHONY: all compiler1 compiler2 core zero
|
||||
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero docs clean_docs
|
||||
.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK)
|
||||
.PHONY: tree tree1 treecore treezero treeshark
|
||||
.PHONY: all compiler1 compiler2 core zero shark
|
||||
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
|
||||
.PHONY: checks check_os_version check_j2se_version
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,6 +61,9 @@ VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
CFLAGS += $(LIBFFI_CFLAGS)
|
||||
endif
|
||||
ifeq ($(SHARK_BUILD), true)
|
||||
CFLAGS += $(LLVM_CFLAGS)
|
||||
endif
|
||||
CFLAGS += $(VM_PICFLAG)
|
||||
CFLAGS += -fno-rtti
|
||||
CFLAGS += -fno-exceptions
|
||||
|
||||
32
hotspot/make/linux/makefiles/shark.make
Normal file
32
hotspot/make/linux/makefiles/shark.make
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright 2008, 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.
|
||||
#
|
||||
#
|
||||
|
||||
# Sets make macros for making Shark version of VM
|
||||
|
||||
TYPE = SHARK
|
||||
|
||||
VM_SUBDIR = server
|
||||
|
||||
CFLAGS += -DSHARK
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,7 @@ Include_DBs/COMPILER1 = $(Include_DBs/CORE) $(VM)/includeDB_compiler1
|
||||
Include_DBs/COMPILER2 = $(Include_DBs/CORE) $(VM)/includeDB_compiler2
|
||||
Include_DBs/TIERED = $(Include_DBs/CORE) $(VM)/includeDB_compiler1 $(VM)/includeDB_compiler2
|
||||
Include_DBs/ZERO = $(Include_DBs/CORE) $(VM)/includeDB_zero
|
||||
Include_DBs/SHARK = $(Include_DBs/ZERO) $(VM)/includeDB_shark
|
||||
Include_DBs = $(Include_DBs/$(TYPE))
|
||||
|
||||
Cached_plat = $(GENERATED)/platform.current
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -137,10 +137,14 @@ mapfile_reorder : mapfile $(REORDERFILE)
|
||||
vm.def: $(Res_Files) $(Obj_Files)
|
||||
sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
|
||||
|
||||
ifeq ($(ZERO_LIBARCH), ppc64)
|
||||
ifeq ($(SHARK_BUILD), true)
|
||||
STATIC_CXX = false
|
||||
else
|
||||
STATIC_CXX = true
|
||||
ifeq ($(ZERO_LIBARCH), ppc64)
|
||||
STATIC_CXX = false
|
||||
else
|
||||
STATIC_CXX = true
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(LINK_INTO),AOUT)
|
||||
@ -168,6 +172,10 @@ endif
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
LIBS_VM += $(LIBFFI_LIBS)
|
||||
endif
|
||||
ifeq ($(SHARK_BUILD), true)
|
||||
LFLAGS_VM += $(LLVM_LDFLAGS)
|
||||
LIBS_VM += $(LLVM_LIBS)
|
||||
endif
|
||||
|
||||
LINK_VM = $(LINK_LIB.c)
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
* Copyright 2007, 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
|
||||
@ -23,13 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// The disassembler prints out zero code annotated
|
||||
// with Java specific information.
|
||||
|
||||
static int pd_instruction_alignment() {
|
||||
ShouldNotCallThis();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char* pd_cpu_opts() {
|
||||
ShouldNotCallThis();
|
||||
return "";
|
||||
}
|
||||
|
||||
62
hotspot/src/cpu/zero/vm/shark_globals_zero.hpp
Normal file
62
hotspot/src/cpu/zero/vm/shark_globals_zero.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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, BackEdgeThreshold, 100000);
|
||||
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(intx, InlineSmallCode, 1000 );
|
||||
define_pd_global(intx, NewRatio, 12 );
|
||||
define_pd_global(intx, NewSizeThreadIncrease, 4*K );
|
||||
define_pd_global(intx, InitialCodeCacheSize, 160*K);
|
||||
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
|
||||
define_pd_global(bool, ProfileInterpreter, false);
|
||||
define_pd_global(intx, CodeCacheExpansionSize, 32*K );
|
||||
define_pd_global(uintx, CodeCacheMinBlockLength, 1 );
|
||||
define_pd_global(uintx, PermSize, 12*M );
|
||||
define_pd_global(uintx, MaxPermSize, 64*M );
|
||||
define_pd_global(bool, NeverActAsServerClassMachine, true );
|
||||
define_pd_global(uint64_t, MaxRAM, 1ULL*G);
|
||||
define_pd_global(bool, CICompileOSR, true );
|
||||
@ -55,10 +55,10 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
_exception_handlers = NULL;
|
||||
_liveness = NULL;
|
||||
_method_blocks = NULL;
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
_flow = NULL;
|
||||
_bcea = NULL;
|
||||
#endif // COMPILER2
|
||||
#endif // COMPILER2 || SHARK
|
||||
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
if (env->jvmti_can_hotswap_or_post_breakpoint() && _is_compilable) {
|
||||
@ -123,10 +123,10 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
|
||||
_can_be_statically_bound = false;
|
||||
_method_blocks = NULL;
|
||||
_method_data = NULL;
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
_flow = NULL;
|
||||
_bcea = NULL;
|
||||
#endif // COMPILER2
|
||||
#endif // COMPILER2 || SHARK
|
||||
}
|
||||
|
||||
|
||||
@ -229,6 +229,20 @@ 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;
|
||||
return klassItable::compute_itable_index(get_methodOop());
|
||||
}
|
||||
#endif // SHARK
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::native_entry
|
||||
//
|
||||
@ -294,34 +308,34 @@ bool ciMethod::has_balanced_monitors() {
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::get_flow_analysis
|
||||
ciTypeFlow* ciMethod::get_flow_analysis() {
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
if (_flow == NULL) {
|
||||
ciEnv* env = CURRENT_ENV;
|
||||
_flow = new (env->arena()) ciTypeFlow(env, this);
|
||||
_flow->do_flow();
|
||||
}
|
||||
return _flow;
|
||||
#else // COMPILER2
|
||||
#else // COMPILER2 || SHARK
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
#endif // COMPILER2
|
||||
#endif // COMPILER2 || SHARK
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::get_osr_flow_analysis
|
||||
ciTypeFlow* ciMethod::get_osr_flow_analysis(int osr_bci) {
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
// 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
|
||||
#else // COMPILER2 || SHARK
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
#endif // COMPILER2
|
||||
#endif // COMPILER2 || SHARK
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@ -70,7 +70,7 @@ class ciMethod : public ciObject {
|
||||
|
||||
// Optional liveness analyzer.
|
||||
MethodLiveness* _liveness;
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
ciTypeFlow* _flow;
|
||||
BCEscapeAnalyzer* _bcea;
|
||||
#endif
|
||||
@ -141,6 +141,9 @@ class ciMethod : public ciObject {
|
||||
|
||||
// Runtime information.
|
||||
int vtable_index();
|
||||
#ifdef SHARK
|
||||
int itable_index();
|
||||
#endif // SHARK
|
||||
address native_entry();
|
||||
address interpreter_entry();
|
||||
|
||||
|
||||
@ -65,6 +65,11 @@ bool nmethod::is_compiled_by_c2() const {
|
||||
if (is_native_method()) return false;
|
||||
return compiler()->is_c2();
|
||||
}
|
||||
bool nmethod::is_compiled_by_shark() const {
|
||||
if (is_native_method()) return false;
|
||||
assert(compiler() != NULL, "must be");
|
||||
return compiler()->is_shark();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1353,6 +1358,10 @@ void nmethod::flush() {
|
||||
CodeCache::remove_saved_code(this);
|
||||
}
|
||||
|
||||
#ifdef SHARK
|
||||
((SharkCompiler *) compiler())->free_compiled_method(instructions_begin());
|
||||
#endif // SHARK
|
||||
|
||||
((CodeBlob*)(this))->flush();
|
||||
|
||||
CodeCache::free(this);
|
||||
@ -1769,6 +1778,7 @@ bool nmethod::detect_scavenge_root_oops() {
|
||||
// Method that knows how to preserve outgoing arguments at call. This method must be
|
||||
// called with a frame corresponding to a Java invoke
|
||||
void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
|
||||
#ifndef SHARK
|
||||
if (!method()->is_native()) {
|
||||
SimpleScopeDesc ssd(this, fr.pc());
|
||||
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
|
||||
@ -1776,6 +1786,7 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map
|
||||
symbolOop signature = call->signature();
|
||||
fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
|
||||
}
|
||||
#endif // !SHARK
|
||||
}
|
||||
|
||||
|
||||
@ -2279,6 +2290,8 @@ 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 {
|
||||
tty->print("(nm) ");
|
||||
}
|
||||
|
||||
@ -329,6 +329,7 @@ class nmethod : public CodeBlob {
|
||||
|
||||
bool is_compiled_by_c1() const;
|
||||
bool is_compiled_by_c2() const;
|
||||
bool is_compiled_by_shark() const;
|
||||
|
||||
// boundaries for different parts
|
||||
address code_begin () const { return _entry_point; }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,18 +45,26 @@ class AbstractCompiler : public CHeapObj {
|
||||
// Missing feature tests
|
||||
virtual bool supports_native() { return true; }
|
||||
virtual bool supports_osr () { return true; }
|
||||
#if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2))
|
||||
#if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK))
|
||||
virtual bool is_c1 () { return false; }
|
||||
virtual bool is_c2 () { return false; }
|
||||
virtual bool is_shark() { return false; }
|
||||
#else
|
||||
#ifdef COMPILER1
|
||||
bool is_c1 () { return true; }
|
||||
bool is_c2 () { return false; }
|
||||
bool is_shark() { return false; }
|
||||
#endif // COMPILER1
|
||||
#ifdef COMPILER2
|
||||
bool is_c1 () { return false; }
|
||||
bool is_c2 () { return true; }
|
||||
bool is_shark() { return false; }
|
||||
#endif // COMPILER2
|
||||
#ifdef SHARK
|
||||
bool is_c1 () { return false; }
|
||||
bool is_c2 () { return false; }
|
||||
bool is_shark() { return true; }
|
||||
#endif // SHARK
|
||||
#endif // TIERED
|
||||
|
||||
// Customization
|
||||
|
||||
@ -568,6 +568,14 @@ void CompileBroker::compilation_init() {
|
||||
#endif
|
||||
#endif // COMPILER2
|
||||
|
||||
#ifdef SHARK
|
||||
#if defined(COMPILER1) || defined(COMPILER2)
|
||||
#error "Can't use COMPILER1 or COMPILER2 with shark"
|
||||
#endif
|
||||
_compilers[0] = new SharkCompiler();
|
||||
_compilers[1] = _compilers[0];
|
||||
#endif
|
||||
|
||||
// Initialize the CompileTask free list
|
||||
_task_free_list = NULL;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -423,8 +423,14 @@ void Disassembler::decode(nmethod* nm, outputStream* st) {
|
||||
env.output()->print_cr("Decoding compiled method " INTPTR_FORMAT ":", nm);
|
||||
env.output()->print_cr("Code:");
|
||||
|
||||
#ifdef SHARK
|
||||
SharkEntry* entry = (SharkEntry *) nm->instructions_begin();
|
||||
unsigned char* p = entry->code_start();
|
||||
unsigned char* end = entry->code_limit();
|
||||
#else
|
||||
unsigned char* p = nm->instructions_begin();
|
||||
unsigned char* end = nm->instructions_end();
|
||||
#endif // SHARK
|
||||
|
||||
// If there has been profiling, print the buckets.
|
||||
if (FlatProfiler::bucket_start_for(p) != NULL) {
|
||||
|
||||
371
hotspot/src/share/vm/includeDB_shark
Normal file
371
hotspot/src/share/vm/includeDB_shark
Normal file
@ -0,0 +1,371 @@
|
||||
//
|
||||
// Copyright (c) 1999, 2007, 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.
|
||||
//
|
||||
//
|
||||
|
||||
// NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
|
||||
|
||||
ciMethod.cpp ciTypeFlow.hpp
|
||||
ciMethod.cpp methodOop.hpp
|
||||
|
||||
ciTypeFlow.cpp allocation.inline.hpp
|
||||
ciTypeFlow.cpp bytecode.hpp
|
||||
ciTypeFlow.cpp bytecodes.hpp
|
||||
ciTypeFlow.cpp ciConstant.hpp
|
||||
ciTypeFlow.cpp ciField.hpp
|
||||
ciTypeFlow.cpp ciMethod.hpp
|
||||
ciTypeFlow.cpp ciMethodData.hpp
|
||||
ciTypeFlow.cpp ciObjArrayKlass.hpp
|
||||
ciTypeFlow.cpp ciStreams.hpp
|
||||
ciTypeFlow.cpp ciTypeArrayKlass.hpp
|
||||
ciTypeFlow.cpp ciTypeFlow.hpp
|
||||
ciTypeFlow.cpp compileLog.hpp
|
||||
ciTypeFlow.cpp deoptimization.hpp
|
||||
ciTypeFlow.cpp growableArray.hpp
|
||||
ciTypeFlow.cpp shark_globals.hpp
|
||||
|
||||
ciTypeFlow.hpp ciEnv.hpp
|
||||
ciTypeFlow.hpp ciKlass.hpp
|
||||
ciTypeFlow.hpp ciMethodBlocks.hpp
|
||||
|
||||
cppInterpreter_<arch>.cpp shark_globals.hpp
|
||||
|
||||
compileBroker.cpp sharkCompiler.hpp
|
||||
|
||||
disassembler.cpp sharkEntry.hpp
|
||||
|
||||
globals.hpp shark_globals_<arch>.hpp
|
||||
|
||||
globals.cpp shark_globals.hpp
|
||||
|
||||
llvmValue.hpp llvmHeaders.hpp
|
||||
llvmValue.hpp sharkContext.hpp
|
||||
llvmValue.hpp sharkType.hpp
|
||||
|
||||
nmethod.cpp sharkCompiler.hpp
|
||||
|
||||
sharedRuntime_<arch>.cpp compileBroker.hpp
|
||||
sharedRuntime_<arch>.cpp sharkCompiler.hpp
|
||||
|
||||
shark_globals.cpp shark_globals.hpp
|
||||
|
||||
shark_globals.hpp shark_globals_<arch>.hpp
|
||||
shark_globals.hpp globals.hpp
|
||||
|
||||
sharkBlock.cpp debug.hpp
|
||||
sharkBlock.cpp bytecodes.hpp
|
||||
sharkBlock.cpp llvmHeaders.hpp
|
||||
sharkBlock.cpp llvmValue.hpp
|
||||
sharkBlock.cpp shark_globals.hpp
|
||||
sharkBlock.cpp sharkBlock.hpp
|
||||
sharkBlock.cpp sharkBuilder.hpp
|
||||
sharkBlock.cpp sharkConstant.hpp
|
||||
sharkBlock.cpp sharkState.hpp
|
||||
sharkBlock.cpp sharkValue.hpp
|
||||
|
||||
sharkBlock.hpp allocation.hpp
|
||||
sharkBlock.hpp ciMethod.hpp
|
||||
sharkBlock.hpp ciStreams.hpp
|
||||
sharkBlock.hpp debug.hpp
|
||||
sharkBlock.hpp llvmHeaders.hpp
|
||||
sharkBlock.hpp sharkBuilder.hpp
|
||||
sharkBlock.hpp sharkConstant.hpp
|
||||
sharkBlock.hpp sharkInvariants.hpp
|
||||
sharkBlock.hpp sharkState.hpp
|
||||
sharkBlock.hpp sharkValue.hpp
|
||||
|
||||
sharkBuilder.cpp ciMethod.hpp
|
||||
sharkBuilder.cpp debug.hpp
|
||||
sharkBuilder.cpp llvmHeaders.hpp
|
||||
sharkBuilder.cpp llvmValue.hpp
|
||||
sharkBuilder.cpp methodOop.hpp
|
||||
sharkBuilder.cpp os.hpp
|
||||
sharkBuilder.cpp resourceArea.hpp
|
||||
sharkBuilder.cpp llvmHeaders.hpp
|
||||
sharkBuilder.cpp sharkBuilder.hpp
|
||||
sharkBuilder.cpp sharkContext.hpp
|
||||
sharkBuilder.cpp sharkRuntime.hpp
|
||||
sharkBuilder.cpp synchronizer.hpp
|
||||
sharkBuilder.cpp thread.hpp
|
||||
|
||||
sharkBuilder.hpp barrierSet.hpp
|
||||
sharkBuilder.hpp cardTableModRefBS.hpp
|
||||
sharkBuilder.hpp ciType.hpp
|
||||
sharkBuilder.hpp debug.hpp
|
||||
sharkBuilder.hpp llvmHeaders.hpp
|
||||
sharkBuilder.hpp llvmValue.hpp
|
||||
sharkBuilder.hpp sizes.hpp
|
||||
sharkBuilder.hpp sharkCodeBuffer.hpp
|
||||
sharkBuilder.hpp sharkType.hpp
|
||||
sharkBuilder.hpp sharkValue.hpp
|
||||
sharkBuilder.hpp sharkEntry.hpp
|
||||
|
||||
sharkCacheDecache.cpp ciMethod.hpp
|
||||
sharkCacheDecache.cpp debugInfoRec.hpp
|
||||
sharkCacheDecache.cpp llvmValue.hpp
|
||||
sharkCacheDecache.cpp sharkBuilder.hpp
|
||||
sharkCacheDecache.cpp sharkCacheDecache.hpp
|
||||
sharkCacheDecache.cpp sharkFunction.hpp
|
||||
sharkCacheDecache.cpp sharkState.hpp
|
||||
|
||||
sharkCacheDecache.hpp ciMethod.hpp
|
||||
sharkCacheDecache.hpp debugInfoRec.hpp
|
||||
sharkCacheDecache.hpp sharkBuilder.hpp
|
||||
sharkCacheDecache.hpp sharkFunction.hpp
|
||||
sharkCacheDecache.hpp sharkStateScanner.hpp
|
||||
|
||||
sharkCodeBuffer.hpp allocation.hpp
|
||||
sharkCodeBuffer.hpp codeBuffer.hpp
|
||||
sharkCodeBuffer.hpp llvmHeaders.hpp
|
||||
|
||||
sharkCompiler.cpp abstractCompiler.hpp
|
||||
sharkCompiler.cpp ciEnv.hpp
|
||||
sharkCompiler.cpp ciMethod.hpp
|
||||
sharkCompiler.cpp debug.hpp
|
||||
sharkCompiler.cpp debugInfoRec.hpp
|
||||
sharkCompiler.cpp dependencies.hpp
|
||||
sharkCompiler.cpp exceptionHandlerTable.hpp
|
||||
sharkCompiler.cpp llvmHeaders.hpp
|
||||
sharkCompiler.cpp oopMap.hpp
|
||||
sharkCompiler.cpp oopRecorder.hpp
|
||||
sharkCompiler.cpp shark_globals.hpp
|
||||
sharkCompiler.cpp sharkBuilder.hpp
|
||||
sharkCompiler.cpp sharkCodeBuffer.hpp
|
||||
sharkCompiler.cpp sharkCompiler.hpp
|
||||
sharkCompiler.cpp sharkContext.hpp
|
||||
sharkCompiler.cpp sharkEntry.hpp
|
||||
sharkCompiler.cpp sharkFunction.hpp
|
||||
sharkCompiler.cpp sharkMemoryManager.hpp
|
||||
sharkCompiler.cpp sharkNativeWrapper.hpp
|
||||
|
||||
sharkCompiler.hpp abstractCompiler.hpp
|
||||
sharkCompiler.hpp ciEnv.hpp
|
||||
sharkCompiler.hpp ciMethod.hpp
|
||||
sharkCompiler.hpp compileBroker.hpp
|
||||
sharkCompiler.hpp llvmHeaders.hpp
|
||||
sharkCompiler.hpp sharkMemoryManager.hpp
|
||||
|
||||
sharkContext.cpp arrayOop.hpp
|
||||
sharkContext.cpp globalDefinitions.hpp
|
||||
sharkContext.cpp llvmHeaders.hpp
|
||||
sharkContext.cpp oop.hpp
|
||||
sharkContext.cpp sharkContext.hpp
|
||||
|
||||
sharkContext.hpp llvmHeaders.hpp
|
||||
sharkContext.hpp sharkCompiler.hpp
|
||||
|
||||
sharkConstant.cpp ciInstance.hpp
|
||||
sharkConstant.cpp ciStreams.hpp
|
||||
sharkConstant.cpp sharkBuilder.hpp
|
||||
sharkConstant.cpp sharkConstant.hpp
|
||||
sharkConstant.cpp sharkValue.hpp
|
||||
|
||||
sharkConstant.hpp allocation.hpp
|
||||
sharkConstant.hpp ciStreams.hpp
|
||||
sharkConstant.hpp sharkBuilder.hpp
|
||||
sharkConstant.hpp sharkValue.hpp
|
||||
|
||||
sharkEntry.hpp llvmHeaders.hpp
|
||||
|
||||
sharkFunction.cpp allocation.hpp
|
||||
sharkFunction.cpp ciTypeFlow.hpp
|
||||
sharkFunction.cpp debug.hpp
|
||||
sharkFunction.cpp llvmHeaders.hpp
|
||||
sharkFunction.cpp llvmValue.hpp
|
||||
sharkFunction.cpp shark_globals.hpp
|
||||
sharkFunction.cpp sharkBuilder.hpp
|
||||
sharkFunction.cpp sharkEntry.hpp
|
||||
sharkFunction.cpp sharkFunction.hpp
|
||||
sharkFunction.cpp sharkState.hpp
|
||||
sharkFunction.cpp sharkTopLevelBlock.hpp
|
||||
|
||||
sharkFunction.hpp allocation.hpp
|
||||
sharkFunction.hpp ciEnv.hpp
|
||||
sharkFunction.hpp ciStreams.hpp
|
||||
sharkFunction.hpp ciTypeFlow.hpp
|
||||
sharkFunction.hpp llvmHeaders.hpp
|
||||
sharkFunction.hpp llvmValue.hpp
|
||||
sharkFunction.hpp sharkBuilder.hpp
|
||||
sharkFunction.hpp sharkContext.hpp
|
||||
sharkFunction.hpp sharkInvariants.hpp
|
||||
sharkFunction.hpp sharkStack.hpp
|
||||
|
||||
sharkInliner.cpp allocation.hpp
|
||||
sharkInliner.cpp bytecodes.hpp
|
||||
sharkInliner.cpp ciField.hpp
|
||||
sharkInliner.cpp ciMethod.hpp
|
||||
sharkInliner.cpp ciStreams.hpp
|
||||
sharkInliner.cpp shark_globals.hpp
|
||||
sharkInliner.cpp sharkBlock.hpp
|
||||
sharkInliner.cpp sharkConstant.hpp
|
||||
sharkInliner.cpp sharkInliner.hpp
|
||||
sharkInliner.cpp sharkIntrinsics.hpp
|
||||
sharkInliner.cpp sharkState.hpp
|
||||
sharkInliner.cpp sharkValue.hpp
|
||||
|
||||
sharkInliner.hpp allocation.hpp
|
||||
sharkInliner.hpp ciMethod.hpp
|
||||
sharkInliner.hpp llvmHeaders.hpp
|
||||
sharkInliner.hpp sharkState.hpp
|
||||
|
||||
sharkIntrinsics.cpp ciMethod.hpp
|
||||
sharkIntrinsics.cpp llvmHeaders.hpp
|
||||
sharkIntrinsics.cpp shark_globals.hpp
|
||||
sharkIntrinsics.cpp sharkIntrinsics.hpp
|
||||
sharkIntrinsics.cpp sharkState.hpp
|
||||
sharkIntrinsics.cpp sharkValue.hpp
|
||||
|
||||
sharkIntrinsics.hpp allocation.hpp
|
||||
sharkIntrinsics.hpp ciMethod.hpp
|
||||
sharkIntrinsics.hpp llvmHeaders.hpp
|
||||
sharkIntrinsics.hpp sharkState.hpp
|
||||
|
||||
sharkInvariants.cpp sharkInvariants.hpp
|
||||
|
||||
sharkInvariants.hpp allocation.hpp
|
||||
sharkInvariants.hpp ciEnv.hpp
|
||||
sharkInvariants.hpp ciMethod.hpp
|
||||
sharkInvariants.hpp ciInstanceKlass.hpp
|
||||
sharkInvariants.hpp ciTypeFlow.hpp
|
||||
sharkInvariants.hpp debugInfoRec.hpp
|
||||
sharkInvariants.hpp dependencies.hpp
|
||||
sharkInvariants.hpp llvmHeaders.hpp
|
||||
sharkInvariants.hpp sharkBuilder.hpp
|
||||
|
||||
sharkMemoryManager.hpp llvmHeaders.hpp
|
||||
sharkMemoryManager.hpp sharkEntry.hpp
|
||||
|
||||
sharkMemoryManager.cpp llvmHeaders.hpp
|
||||
sharkMemoryManager.cpp sharkEntry.hpp
|
||||
sharkMemoryManager.cpp sharkMemoryManager.hpp
|
||||
|
||||
sharkNativeWrapper.cpp llvmHeaders.hpp
|
||||
sharkNativeWrapper.cpp sharkNativeWrapper.hpp
|
||||
sharkNativeWrapper.cpp sharkType.hpp
|
||||
|
||||
sharkNativeWrapper.hpp handles.hpp
|
||||
sharkNativeWrapper.hpp llvmHeaders.hpp
|
||||
sharkNativeWrapper.hpp sharkBuilder.hpp
|
||||
sharkNativeWrapper.hpp sharkContext.hpp
|
||||
sharkNativeWrapper.hpp sharkInvariants.hpp
|
||||
sharkNativeWrapper.hpp sharkStack.hpp
|
||||
|
||||
sharkRuntime.cpp biasedLocking.hpp
|
||||
sharkRuntime.cpp deoptimization.hpp
|
||||
sharkRuntime.cpp llvmHeaders.hpp
|
||||
sharkRuntime.cpp klassOop.hpp
|
||||
sharkRuntime.cpp sharkRuntime.hpp
|
||||
sharkRuntime.cpp stack_<arch>.inline.hpp
|
||||
sharkRuntime.cpp thread.hpp
|
||||
|
||||
sharkRuntime.hpp allocation.hpp
|
||||
sharkRuntime.hpp llvmHeaders.hpp
|
||||
sharkRuntime.hpp llvmValue.hpp
|
||||
sharkRuntime.hpp klassOop.hpp
|
||||
sharkRuntime.hpp thread.hpp
|
||||
|
||||
sharkStack.cpp llvmHeaders.hpp
|
||||
sharkStack.cpp sharkFunction.hpp
|
||||
sharkStack.cpp sharkNativeWrapper.hpp
|
||||
sharkStack.cpp sharkStack.hpp
|
||||
sharkStack.cpp sharkType.hpp
|
||||
|
||||
sharkStack.hpp llvmHeaders.hpp
|
||||
sharkStack.hpp sharkInvariants.hpp
|
||||
sharkStack.hpp sharkType.hpp
|
||||
|
||||
sharkState.cpp allocation.hpp
|
||||
sharkState.cpp ciType.hpp
|
||||
sharkState.cpp ciTypeFlow.hpp
|
||||
sharkState.cpp sharkBuilder.hpp
|
||||
sharkState.cpp sharkCacheDecache.hpp
|
||||
sharkState.cpp sharkState.hpp
|
||||
sharkState.cpp sharkTopLevelBlock.hpp
|
||||
sharkState.cpp sharkType.hpp
|
||||
sharkState.cpp sharkValue.hpp
|
||||
|
||||
sharkState.hpp allocation.hpp
|
||||
sharkState.hpp ciMethod.hpp
|
||||
sharkState.hpp llvmHeaders.hpp
|
||||
sharkState.hpp sharkBuilder.hpp
|
||||
sharkState.hpp sharkInvariants.hpp
|
||||
sharkState.hpp sharkValue.hpp
|
||||
|
||||
sharkStateScanner.cpp sharkState.hpp
|
||||
sharkStateScanner.cpp sharkStateScanner.hpp
|
||||
|
||||
sharkStateScanner.hpp allocation.hpp
|
||||
sharkStateScanner.hpp llvmHeaders.hpp
|
||||
sharkStateScanner.hpp sharkFunction.hpp
|
||||
sharkStateScanner.hpp sharkInvariants.hpp
|
||||
|
||||
sharkTopLevelBlock.cpp allocation.hpp
|
||||
sharkTopLevelBlock.cpp bytecodes.hpp
|
||||
sharkTopLevelBlock.cpp ciField.hpp
|
||||
sharkTopLevelBlock.cpp ciInstance.hpp
|
||||
sharkTopLevelBlock.cpp ciObjArrayKlass.hpp
|
||||
sharkTopLevelBlock.cpp ciStreams.hpp
|
||||
sharkTopLevelBlock.cpp ciType.hpp
|
||||
sharkTopLevelBlock.cpp ciTypeFlow.hpp
|
||||
sharkTopLevelBlock.cpp debug.hpp
|
||||
sharkTopLevelBlock.cpp deoptimization.hpp
|
||||
sharkTopLevelBlock.cpp llvmHeaders.hpp
|
||||
sharkTopLevelBlock.cpp llvmValue.hpp
|
||||
sharkTopLevelBlock.cpp shark_globals.hpp
|
||||
sharkTopLevelBlock.cpp sharkCacheDecache.hpp
|
||||
sharkTopLevelBlock.cpp sharkTopLevelBlock.hpp
|
||||
sharkTopLevelBlock.cpp sharkBuilder.hpp
|
||||
sharkTopLevelBlock.cpp sharkConstant.hpp
|
||||
sharkTopLevelBlock.cpp sharkInliner.hpp
|
||||
sharkTopLevelBlock.cpp sharkState.hpp
|
||||
sharkTopLevelBlock.cpp sharkValue.hpp
|
||||
|
||||
sharkTopLevelBlock.hpp allocation.hpp
|
||||
sharkTopLevelBlock.hpp bytecodes.hpp
|
||||
sharkTopLevelBlock.hpp ciStreams.hpp
|
||||
sharkTopLevelBlock.hpp ciType.hpp
|
||||
sharkTopLevelBlock.hpp ciTypeFlow.hpp
|
||||
sharkTopLevelBlock.hpp llvmHeaders.hpp
|
||||
sharkTopLevelBlock.hpp sharkBlock.hpp
|
||||
sharkTopLevelBlock.hpp sharkBuilder.hpp
|
||||
sharkTopLevelBlock.hpp sharkFunction.hpp
|
||||
sharkTopLevelBlock.hpp sharkState.hpp
|
||||
sharkTopLevelBlock.hpp sharkValue.hpp
|
||||
|
||||
sharkType.hpp allocation.hpp
|
||||
sharkType.hpp ciType.hpp
|
||||
sharkType.hpp globalDefinitions.hpp
|
||||
sharkType.hpp llvmHeaders.hpp
|
||||
sharkType.hpp sharkContext.hpp
|
||||
|
||||
sharkValue.cpp ciType.hpp
|
||||
sharkValue.cpp llvmHeaders.hpp
|
||||
sharkValue.cpp llvmValue.hpp
|
||||
sharkValue.cpp sharkBuilder.hpp
|
||||
sharkValue.cpp sharkValue.hpp
|
||||
|
||||
sharkValue.hpp allocation.hpp
|
||||
sharkValue.hpp ciType.hpp
|
||||
sharkValue.hpp llvmHeaders.hpp
|
||||
sharkValue.hpp llvmValue.hpp
|
||||
sharkValue.hpp sharkType.hpp
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,6 +44,7 @@ class CardTableModRefBS: public ModRefBarrierSet {
|
||||
friend class VMStructs;
|
||||
friend class CardTableRS;
|
||||
friend class CheckForUnmarkedOops; // Needs access to raw card bytes.
|
||||
friend class SharkBuilder;
|
||||
#ifndef PRODUCT
|
||||
// For debugging.
|
||||
friend class GuaranteeNotModClosure;
|
||||
|
||||
@ -751,10 +751,14 @@ void methodOopDesc::set_code(methodHandle mh, nmethod *code) {
|
||||
}
|
||||
|
||||
OrderAccess::storestore();
|
||||
#ifdef SHARK
|
||||
mh->_from_interpreted_entry = code->instructions_begin();
|
||||
#else
|
||||
mh->_from_compiled_entry = code->verified_entry_point();
|
||||
OrderAccess::storestore();
|
||||
// Instantly compiled code can execute.
|
||||
mh->_from_interpreted_entry = mh->get_i2c_entry();
|
||||
#endif // SHARK
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -254,6 +254,7 @@ 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
|
||||
@ -270,6 +271,10 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking");
|
||||
Events::log("fetch unroll sp " INTPTR_FORMAT, unpack_sp);
|
||||
#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
|
||||
// where it will be very difficult to figure out what went wrong. Better
|
||||
@ -380,7 +385,9 @@ 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
|
||||
|
||||
UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
|
||||
caller_adjustment * BytesPerWord,
|
||||
@ -1073,7 +1080,7 @@ JRT_LEAF(void, Deoptimization::popframe_preserve_args(JavaThread* thread, int by
|
||||
JRT_END
|
||||
|
||||
|
||||
#ifdef COMPILER2
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
|
||||
// in case of an unresolved klass entry, load the class.
|
||||
if (constant_pool->tag_at(index).is_unresolved_klass()) {
|
||||
@ -1835,7 +1842,7 @@ void Deoptimization::print_statistics() {
|
||||
if (xtty != NULL) xtty->tail("statistics");
|
||||
}
|
||||
}
|
||||
#else // COMPILER2
|
||||
#else // COMPILER2 || SHARK
|
||||
|
||||
|
||||
// Stubs for C1 only system.
|
||||
@ -1871,4 +1878,4 @@ const char* Deoptimization::format_trap_state(char* buf, size_t buflen,
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
#endif // COMPILER2 || SHARK
|
||||
|
||||
@ -1100,6 +1100,10 @@ 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();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -181,6 +181,18 @@ void Flag::print_as_flag(outputStream* st) {
|
||||
#define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 notproduct}", DEFAULT },
|
||||
#endif
|
||||
|
||||
#define SHARK_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{Shark product}", DEFAULT },
|
||||
#define SHARK_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, "{Shark pd product}", DEFAULT },
|
||||
#define SHARK_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{Shark diagnostic}", DEFAULT },
|
||||
#ifdef PRODUCT
|
||||
#define SHARK_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
|
||||
#define SHARK_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */
|
||||
#define SHARK_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc)
|
||||
#else
|
||||
#define SHARK_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{Shark}", DEFAULT },
|
||||
#define SHARK_PD_DEVELOP_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, "{Shark pd}", DEFAULT },
|
||||
#define SHARK_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{Shark notproduct}", DEFAULT },
|
||||
#endif
|
||||
|
||||
static Flag flagTable[] = {
|
||||
RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT)
|
||||
@ -193,6 +205,9 @@ static Flag flagTable[] = {
|
||||
#endif
|
||||
#ifdef COMPILER2
|
||||
C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
|
||||
#endif
|
||||
#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_NOTPRODUCT_FLAG_STRUCT)
|
||||
#endif
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2)
|
||||
#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
|
||||
define_pd_global(bool, BackgroundCompilation, false);
|
||||
define_pd_global(bool, UseTLAB, false);
|
||||
define_pd_global(bool, CICompileOSR, false);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -95,7 +95,11 @@ void Abstract_VM_Version::initialize() {
|
||||
#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")
|
||||
|
||||
95
hotspot/src/share/vm/shark/llvmHeaders.hpp
Normal file
95
hotspot/src/share/vm/shark/llvmHeaders.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define SHARK_DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#include <llvm/Argument.h>
|
||||
#include <llvm/Constants.h>
|
||||
#include <llvm/DerivedTypes.h>
|
||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
#include <llvm/Instructions.h>
|
||||
#include <llvm/LLVMContext.h>
|
||||
#include <llvm/Module.h>
|
||||
#if SHARK_LLVM_VERSION < 27
|
||||
#include <llvm/ModuleProvider.h>
|
||||
#endif
|
||||
#include <llvm/Support/IRBuilder.h>
|
||||
#include <llvm/System/Threading.h>
|
||||
#include <llvm/Target/TargetSelect.h>
|
||||
#include <llvm/Type.h>
|
||||
#include <llvm/ExecutionEngine/JITMemoryManager.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
#include <llvm/ExecutionEngine/JIT.h>
|
||||
#include <llvm/ADT/StringMap.h>
|
||||
#include <llvm/Support/Debug.h>
|
||||
#include <llvm/System/Host.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
// from hotspot/src/share/vm/utilities/debug.hpp
|
||||
#ifdef ASSERT
|
||||
#ifndef USE_REPEATED_ASSERTS
|
||||
#define assert(p, msg) \
|
||||
do { \
|
||||
if (!(p)) { \
|
||||
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
|
||||
BREAKPOINT; \
|
||||
} \
|
||||
} while (0)
|
||||
#else // #ifndef USE_REPEATED_ASSERTS
|
||||
#define assert(p, msg)
|
||||
do { \
|
||||
for (int __i = 0; __i < AssertRepeat; __i++) { \
|
||||
if (!(p)) { \
|
||||
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
|
||||
BREAKPOINT; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif // #ifndef USE_REPEATED_ASSERTS
|
||||
#else
|
||||
#define assert(p, msg)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#ifdef SHARK_DEBUG
|
||||
#define DEBUG
|
||||
#undef SHARK_DEBUG
|
||||
#endif
|
||||
62
hotspot/src/share/vm/shark/llvmValue.hpp
Normal file
62
hotspot/src/share/vm/shark/llvmValue.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
1260
hotspot/src/share/vm/shark/sharkBlock.cpp
Normal file
1260
hotspot/src/share/vm/shark/sharkBlock.cpp
Normal file
File diff suppressed because it is too large
Load Diff
281
hotspot/src/share/vm/shark/sharkBlock.hpp
Normal file
281
hotspot/src/share/vm/shark/sharkBlock.hpp
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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();
|
||||
};
|
||||
591
hotspot/src/share/vm/shark/sharkBuilder.cpp
Normal file
591
hotspot/src/share/vm/shark/sharkBuilder.cpp
Normal file
@ -0,0 +1,591 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkBuilder.cpp.incl"
|
||||
|
||||
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,
|
||||
const Type* type,
|
||||
const char* name) {
|
||||
return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name);
|
||||
}
|
||||
|
||||
LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base,
|
||||
ByteSize offset,
|
||||
const 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,
|
||||
const 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.
|
||||
|
||||
const 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();
|
||||
|
||||
// Miscellaneous
|
||||
case 'v':
|
||||
assert(void_ok, "should be");
|
||||
return SharkType::void_type();
|
||||
case '1':
|
||||
return SharkType::bit_type();
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
const FunctionType* SharkBuilder::make_ftype(const char* params,
|
||||
const char* ret) {
|
||||
std::vector<const Type*> param_types;
|
||||
for (const char* c = params; *c; c++)
|
||||
param_types.push_back(make_type(*c, false));
|
||||
|
||||
assert(strlen(ret) == 1, "should be");
|
||||
const 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, "OO", "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() {
|
||||
extern jlong Unsafe_field_offset_to_byte_offset(jlong field_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");
|
||||
}
|
||||
|
||||
// Low-level non-VM calls
|
||||
|
||||
// The ARM-specific code here is to work around unimplemented
|
||||
// atomic exchange and memory barrier intrinsics in LLVM.
|
||||
//
|
||||
// Delegating to external functions for these would normally
|
||||
// incur a speed penalty, but Linux on ARM is a special case
|
||||
// in that atomic operations on that platform are handled by
|
||||
// external functions anyway. It would be *preferable* for
|
||||
// the calls to be hidden away in LLVM, but it's not hurting
|
||||
// performance so having the calls here is acceptable.
|
||||
//
|
||||
// If you are building Shark on a platform without atomic
|
||||
// exchange and/or memory barrier intrinsics then it is only
|
||||
// acceptable to mimic this approach if your platform cannot
|
||||
// perform these operations without delegating to a function.
|
||||
|
||||
#ifdef ARM
|
||||
static jint zero_cmpxchg_int(volatile jint *ptr, jint oldval, jint newval) {
|
||||
return Atomic::cmpxchg(newval, ptr, oldval);
|
||||
}
|
||||
#endif // ARM
|
||||
|
||||
Value* SharkBuilder::cmpxchg_int() {
|
||||
return make_function(
|
||||
#ifdef ARM
|
||||
(address) zero_cmpxchg_int,
|
||||
#else
|
||||
"llvm.atomic.cmp.swap.i32.p0i32",
|
||||
#endif // ARM
|
||||
"Iii", "i");
|
||||
}
|
||||
|
||||
#ifdef ARM
|
||||
static intptr_t zero_cmpxchg_ptr(volatile intptr_t* ptr,
|
||||
intptr_t oldval,
|
||||
intptr_t newval) {
|
||||
return Atomic::cmpxchg_ptr(newval, ptr, oldval);
|
||||
}
|
||||
#endif // ARM
|
||||
|
||||
Value* SharkBuilder::cmpxchg_ptr() {
|
||||
return make_function(
|
||||
#ifdef ARM
|
||||
(address) zero_cmpxchg_ptr,
|
||||
#else
|
||||
"llvm.atomic.cmp.swap.i" LP64_ONLY("64") NOT_LP64("32") ".p0i" LP64_ONLY("64") NOT_LP64("32"),
|
||||
#endif // ARM
|
||||
"Xxx", "x");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::frame_address() {
|
||||
return make_function("llvm.frameaddress", "i", "C");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::memory_barrier() {
|
||||
return make_function(
|
||||
#ifdef ARM
|
||||
(address) 0xffff0fa0, // __kernel_dmb
|
||||
#else
|
||||
"llvm.memory.barrier",
|
||||
#endif // ARM
|
||||
"11111", "v");
|
||||
}
|
||||
|
||||
Value* SharkBuilder::memset() {
|
||||
#if SHARK_LLVM_VERSION >= 28
|
||||
// LLVM 2.8 added a fifth isVolatile field for memset
|
||||
// introduced with LLVM r100304
|
||||
return make_function("llvm.memset.i32", "Cciii", "v");
|
||||
#else
|
||||
return make_function("llvm.memset.i32", "Ccii", "v");
|
||||
#endif
|
||||
}
|
||||
|
||||
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::CreateCmpxchgInt(Value* exchange_value,
|
||||
Value* dst,
|
||||
Value* compare_value) {
|
||||
return CreateCall3(cmpxchg_int(), dst, compare_value, exchange_value);
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateCmpxchgPtr(Value* exchange_value,
|
||||
Value* dst,
|
||||
Value* compare_value) {
|
||||
return CreateCall3(cmpxchg_ptr(), dst, compare_value, exchange_value);
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateGetFrameAddress() {
|
||||
return CreateCall(frame_address(), LLVMValue::jint_constant(0));
|
||||
}
|
||||
|
||||
CallInst *SharkBuilder::CreateMemoryBarrier(int flags) {
|
||||
Value *args[] = {
|
||||
LLVMValue::bit_constant((flags & BARRIER_LOADLOAD) ? 1 : 0),
|
||||
LLVMValue::bit_constant((flags & BARRIER_LOADSTORE) ? 1 : 0),
|
||||
LLVMValue::bit_constant((flags & BARRIER_STORELOAD) ? 1 : 0),
|
||||
LLVMValue::bit_constant((flags & BARRIER_STORESTORE) ? 1 : 0),
|
||||
LLVMValue::bit_constant(1)};
|
||||
|
||||
return CreateCall(memory_barrier(), args, args + 5);
|
||||
}
|
||||
|
||||
CallInst* SharkBuilder::CreateMemset(Value* dst,
|
||||
Value* value,
|
||||
Value* len,
|
||||
Value* align) {
|
||||
#if SHARK_LLVM_VERSION >= 28
|
||||
return CreateCall5(memset(), dst, value, len, align,
|
||||
LLVMValue::jint_constant(0));
|
||||
#else
|
||||
return CreateCall4(memset(), dst, value, len, align);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 = 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()->
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
isIntegerTy()
|
||||
#else
|
||||
isInteger()
|
||||
#endif
|
||||
)
|
||||
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::CardTableModRef)
|
||||
Unimplemented();
|
||||
|
||||
CreateStore(
|
||||
LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
|
||||
CreateIntToPtr(
|
||||
CreateAdd(
|
||||
LLVMValue::intptr_constant(
|
||||
(intptr_t) ((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::CreateInlineData(void* data,
|
||||
size_t size,
|
||||
const 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);
|
||||
}
|
||||
209
hotspot/src/share/vm/shark/sharkBuilder.hpp
Normal file
209
hotspot/src/share/vm/shark/sharkBuilder.hpp
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Helpers for accessing structures.
|
||||
public:
|
||||
llvm::Value* CreateAddressOfStructEntry(llvm::Value* base,
|
||||
ByteSize offset,
|
||||
const llvm::Type* type,
|
||||
const char *name = "");
|
||||
llvm::LoadInst* CreateValueOfStructEntry(llvm::Value* base,
|
||||
ByteSize offset,
|
||||
const llvm::Type* type,
|
||||
const char *name = "");
|
||||
|
||||
// Helpers for accessing arrays.
|
||||
public:
|
||||
llvm::LoadInst* CreateArrayLength(llvm::Value* arrayoop);
|
||||
llvm::Value* CreateArrayAddress(llvm::Value* arrayoop,
|
||||
const 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 const llvm::Type* make_type(char type, bool void_ok);
|
||||
static const 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* memory_barrier();
|
||||
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* CreateCmpxchgInt(llvm::Value* exchange_value,
|
||||
llvm::Value* dst,
|
||||
llvm::Value* compare_value);
|
||||
llvm::CallInst* CreateCmpxchgPtr(llvm::Value* exchange_value,
|
||||
llvm::Value* dst,
|
||||
llvm::Value* compare_value);
|
||||
llvm::CallInst* CreateGetFrameAddress();
|
||||
llvm::CallInst* CreateMemoryBarrier(int flags);
|
||||
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));
|
||||
|
||||
// Flags for CreateMemoryBarrier.
|
||||
public:
|
||||
enum BarrierFlags {
|
||||
BARRIER_LOADLOAD = 1,
|
||||
BARRIER_LOADSTORE = 2,
|
||||
BARRIER_STORELOAD = 4,
|
||||
BARRIER_STORESTORE = 8
|
||||
};
|
||||
|
||||
// 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* CreateInlineData(void* data,
|
||||
size_t size,
|
||||
const 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;
|
||||
};
|
||||
259
hotspot/src/share/vm/shark/sharkCacheDecache.cpp
Normal file
259
hotspot/src/share/vm/shark/sharkCacheDecache.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkCacheDecache.cpp.incl"
|
||||
|
||||
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::methodOop_type(),
|
||||
*value,
|
||||
offset);
|
||||
|
||||
oopmap()->set_oop(slot2reg(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
|
||||
debug_info()->describe_scope(
|
||||
pc_offset(),
|
||||
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::methodOop_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,
|
||||
const 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(const Type* type,
|
||||
Value* value,
|
||||
int offset) {
|
||||
builder()->CreateStore(value, stack()->slot_addr(offset, type));
|
||||
}
|
||||
|
||||
Value* SharkCacher::read_value_from_frame(const Type* type, int offset) {
|
||||
return builder()->CreateLoad(stack()->slot_addr(offset, type));
|
||||
}
|
||||
417
hotspot/src/share/vm/shark/sharkCacheDecache.hpp
Normal file
417
hotspot/src/share/vm/shark/sharkCacheDecache.hpp
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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(const 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(const 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, const llvm::Type* type);
|
||||
};
|
||||
87
hotspot/src/share/vm/shark/sharkCodeBuffer.hpp
Normal file
87
hotspot/src/share/vm/shark/sharkCodeBuffer.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
340
hotspot/src/share/vm/shark/sharkCompiler.cpp
Normal file
340
hotspot/src/share/vm/shark/sharkCompiler.cpp
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkCompiler.cpp.incl"
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
namespace {
|
||||
cl::opt<std::string>
|
||||
MCPU("mcpu");
|
||||
|
||||
cl::list<std::string>
|
||||
MAttrs("mattr",
|
||||
cl::CommaSeparated);
|
||||
}
|
||||
#endif
|
||||
|
||||
SharkCompiler::SharkCompiler()
|
||||
: AbstractCompiler() {
|
||||
// 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();
|
||||
|
||||
// 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();
|
||||
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
// 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);
|
||||
_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());
|
||||
#else
|
||||
_execution_engine = ExecutionEngine::createJIT(
|
||||
_normal_context->module_provider(),
|
||||
NULL, memory_manager(), CodeGenOpt::Default);
|
||||
execution_engine()->addModuleProvider(
|
||||
_native_context->module_provider());
|
||||
#endif
|
||||
|
||||
// All done
|
||||
mark_initialized();
|
||||
}
|
||||
|
||||
void SharkCompiler::initialize() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void SharkCompiler::compile_method(ciEnv* env,
|
||||
ciMethod* target,
|
||||
int entry_bci) {
|
||||
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);
|
||||
|
||||
// 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,
|
||||
env->comp_level(),
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,
|
||||
methodHandle target,
|
||||
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,
|
||||
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();
|
||||
}
|
||||
|
||||
// Compile to native code
|
||||
address code = NULL;
|
||||
context()->add_function(function);
|
||||
{
|
||||
MutexLocker locker(execution_engine_lock());
|
||||
free_queued_methods();
|
||||
|
||||
if (SharkPrintAsmOf != NULL) {
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
#ifndef NDEBUG
|
||||
if (!fnmatch(SharkPrintAsmOf, name, 0)) {
|
||||
llvm::SetCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
|
||||
llvm::DebugFlag = true;
|
||||
}
|
||||
else {
|
||||
llvm::SetCurrentDebugType("");
|
||||
llvm::DebugFlag = false;
|
||||
}
|
||||
#endif // !NDEBUG
|
||||
#else
|
||||
// NB you need to patch LLVM with http://tinyurl.com/yf3baln for this
|
||||
std::vector<const char*> args;
|
||||
args.push_back(""); // program name
|
||||
if (!fnmatch(SharkPrintAsmOf, name, 0))
|
||||
args.push_back("-debug-only=x86-emitter");
|
||||
else
|
||||
args.push_back("-debug-only=none");
|
||||
args.push_back(0); // terminator
|
||||
cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
|
||||
#endif // SHARK_LLVM_VERSION
|
||||
}
|
||||
memory_manager()->set_entry_for_function(function, entry);
|
||||
code = (address) execution_engine()->getPointerToFunction(function);
|
||||
}
|
||||
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_VM_thread(), "must be called by VM thread");
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
|
||||
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;
|
||||
}
|
||||
119
hotspot/src/share/vm/shark/sharkCompiler.hpp
Normal file
119
hotspot/src/share/vm/shark/sharkCompiler.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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; }
|
||||
|
||||
// Customization
|
||||
bool needs_adapters() { return false; }
|
||||
bool needs_stubs() { return false; }
|
||||
|
||||
// Initialization
|
||||
void initialize();
|
||||
|
||||
// Compile a normal (bytecode) method and install it in the VM
|
||||
void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
|
||||
|
||||
// Generate a wrapper for a native (JNI) method
|
||||
nmethod* generate_native_wrapper(MacroAssembler* masm,
|
||||
methodHandle target,
|
||||
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_fast_compile);
|
||||
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();
|
||||
};
|
||||
128
hotspot/src/share/vm/shark/sharkConstant.cpp
Normal file
128
hotspot/src/share/vm/shark/sharkConstant.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkConstant.cpp.incl"
|
||||
|
||||
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();
|
||||
if (constant.as_object()->is_klass())
|
||||
type = env->Class_klass();
|
||||
else
|
||||
type = env->String_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_klass()) {
|
||||
// The constant returned for a klass is the ciKlass
|
||||
// for the entry, but we want the java_mirror.
|
||||
ciKlass *klass = object->as_klass();
|
||||
if (!klass->is_loaded()) {
|
||||
_is_loaded = false;
|
||||
return;
|
||||
}
|
||||
object = klass->java_mirror();
|
||||
}
|
||||
if (object->is_null_object() || !object->can_be_constant()) {
|
||||
_is_loaded = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_value = NULL;
|
||||
_object = object;
|
||||
_type = type;
|
||||
_is_loaded = true;
|
||||
_is_nonzero = true;
|
||||
_is_two_word = false;
|
||||
}
|
||||
64
hotspot/src/share/vm/shark/sharkConstant.hpp
Normal file
64
hotspot/src/share/vm/shark/sharkConstant.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
180
hotspot/src/share/vm/shark/sharkContext.cpp
Normal file
180
hotspot/src/share/vm/shark/sharkContext.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkContext.cpp.incl"
|
||||
|
||||
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));
|
||||
|
||||
_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)));
|
||||
|
||||
_methodOop_type = PointerType::getUnqual(
|
||||
ArrayType::get(jbyte_type(), sizeof(methodOopDesc)));
|
||||
|
||||
_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<const Type*> params;
|
||||
params.push_back(methodOop_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(methodOop_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 {
|
||||
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;
|
||||
}
|
||||
187
hotspot/src/share/vm/shark/sharkContext.hpp
Normal file
187
hotspot/src/share/vm/shark/sharkContext.hpp
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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;
|
||||
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
public:
|
||||
#else
|
||||
private:
|
||||
#endif
|
||||
llvm::Module* module() const {
|
||||
return _module;
|
||||
}
|
||||
|
||||
// Get this thread's SharkContext
|
||||
public:
|
||||
static SharkContext& current() {
|
||||
return *SharkCompiler::compiler()->context();
|
||||
}
|
||||
|
||||
// Module accessors
|
||||
public:
|
||||
#if SHARK_LLVM_VERSION < 27
|
||||
llvm::ModuleProvider* module_provider() const {
|
||||
return new llvm::ExistingModuleProvider(module());
|
||||
}
|
||||
#endif
|
||||
void add_function(llvm::Function* function) const {
|
||||
module()->getFunctionList().push_back(function);
|
||||
}
|
||||
llvm::Constant* get_external(const char* name,
|
||||
const llvm::FunctionType* sig) {
|
||||
return module()->getOrInsertFunction(name, sig);
|
||||
}
|
||||
|
||||
// Basic types
|
||||
private:
|
||||
const llvm::Type* _void_type;
|
||||
const llvm::IntegerType* _bit_type;
|
||||
const llvm::IntegerType* _jbyte_type;
|
||||
const llvm::IntegerType* _jshort_type;
|
||||
const llvm::IntegerType* _jint_type;
|
||||
const llvm::IntegerType* _jlong_type;
|
||||
const llvm::Type* _jfloat_type;
|
||||
const llvm::Type* _jdouble_type;
|
||||
|
||||
public:
|
||||
const llvm::Type* void_type() const {
|
||||
return _void_type;
|
||||
}
|
||||
const llvm::IntegerType* bit_type() const {
|
||||
return _bit_type;
|
||||
}
|
||||
const llvm::IntegerType* jbyte_type() const {
|
||||
return _jbyte_type;
|
||||
}
|
||||
const llvm::IntegerType* jshort_type() const {
|
||||
return _jshort_type;
|
||||
}
|
||||
const llvm::IntegerType* jint_type() const {
|
||||
return _jint_type;
|
||||
}
|
||||
const llvm::IntegerType* jlong_type() const {
|
||||
return _jlong_type;
|
||||
}
|
||||
const llvm::Type* jfloat_type() const {
|
||||
return _jfloat_type;
|
||||
}
|
||||
const llvm::Type* jdouble_type() const {
|
||||
return _jdouble_type;
|
||||
}
|
||||
const llvm::IntegerType* intptr_type() const {
|
||||
return LP64_ONLY(jlong_type()) NOT_LP64(jint_type());
|
||||
}
|
||||
|
||||
// Compound types
|
||||
private:
|
||||
const llvm::PointerType* _itableOffsetEntry_type;
|
||||
const llvm::PointerType* _jniEnv_type;
|
||||
const llvm::PointerType* _jniHandleBlock_type;
|
||||
const llvm::PointerType* _klass_type;
|
||||
const llvm::PointerType* _methodOop_type;
|
||||
const llvm::ArrayType* _monitor_type;
|
||||
const llvm::PointerType* _oop_type;
|
||||
const llvm::PointerType* _thread_type;
|
||||
const llvm::PointerType* _zeroStack_type;
|
||||
const llvm::FunctionType* _entry_point_type;
|
||||
const llvm::FunctionType* _osr_entry_point_type;
|
||||
|
||||
public:
|
||||
const llvm::PointerType* itableOffsetEntry_type() const {
|
||||
return _itableOffsetEntry_type;
|
||||
}
|
||||
const llvm::PointerType* jniEnv_type() const {
|
||||
return _jniEnv_type;
|
||||
}
|
||||
const llvm::PointerType* jniHandleBlock_type() const {
|
||||
return _jniHandleBlock_type;
|
||||
}
|
||||
const llvm::PointerType* klass_type() const {
|
||||
return _klass_type;
|
||||
}
|
||||
const llvm::PointerType* methodOop_type() const {
|
||||
return _methodOop_type;
|
||||
}
|
||||
const llvm::ArrayType* monitor_type() const {
|
||||
return _monitor_type;
|
||||
}
|
||||
const llvm::PointerType* oop_type() const {
|
||||
return _oop_type;
|
||||
}
|
||||
const llvm::PointerType* thread_type() const {
|
||||
return _thread_type;
|
||||
}
|
||||
const llvm::PointerType* zeroStack_type() const {
|
||||
return _zeroStack_type;
|
||||
}
|
||||
const llvm::FunctionType* entry_point_type() const {
|
||||
return _entry_point_type;
|
||||
}
|
||||
const llvm::FunctionType* osr_entry_point_type() const {
|
||||
return _osr_entry_point_type;
|
||||
}
|
||||
|
||||
// Mappings
|
||||
private:
|
||||
const llvm::Type* _to_stackType[T_CONFLICT];
|
||||
const llvm::Type* _to_arrayType[T_CONFLICT];
|
||||
|
||||
private:
|
||||
const llvm::Type* map_type(const llvm::Type* const* table,
|
||||
BasicType type) const {
|
||||
assert(type >= 0 && type < T_CONFLICT, "unhandled type");
|
||||
const llvm::Type* result = table[type];
|
||||
assert(type != NULL, "unhandled type");
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
const llvm::Type* to_stackType(BasicType type) const {
|
||||
return map_type(_to_stackType, type);
|
||||
}
|
||||
const 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();
|
||||
};
|
||||
58
hotspot/src/share/vm/shark/sharkEntry.hpp
Normal file
58
hotspot/src/share/vm/shark/sharkEntry.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
188
hotspot/src/share/vm/shark/sharkFunction.cpp
Normal file
188
hotspot/src/share/vm/shark/sharkFunction.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkFunction.cpp.incl"
|
||||
|
||||
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());
|
||||
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();
|
||||
}
|
||||
111
hotspot/src/share/vm/shark/sharkFunction.hpp
Normal file
111
hotspot/src/share/vm/shark/sharkFunction.hpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
const 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();
|
||||
};
|
||||
749
hotspot/src/share/vm/shark/sharkInliner.cpp
Normal file
749
hotspot/src/share/vm/shark/sharkInliner.cpp
Normal file
@ -0,0 +1,749 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkInliner.cpp.incl"
|
||||
|
||||
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()) {
|
||||
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 (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;
|
||||
}
|
||||
32
hotspot/src/share/vm/shark/sharkInliner.hpp
Normal file
32
hotspot/src/share/vm/shark/sharkInliner.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class SharkInliner : public AllStatic {
|
||||
public:
|
||||
static bool attempt_inline(ciMethod* target, SharkState* state);
|
||||
|
||||
private:
|
||||
static bool may_be_inlinable(ciMethod* target);
|
||||
};
|
||||
277
hotspot/src/share/vm/shark/sharkIntrinsics.cpp
Normal file
277
hotspot/src/share/vm/shark/sharkIntrinsics.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkIntrinsics.cpp.incl"
|
||||
|
||||
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;
|
||||
|
||||
// sun.misc.Unsafe
|
||||
case vmIntrinsics::_compareAndSwapInt:
|
||||
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;
|
||||
|
||||
// sun.misc.Unsafe
|
||||
case vmIntrinsics::_compareAndSwapInt:
|
||||
do_Unsafe_compareAndSwapInt();
|
||||
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(), "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::oop_type(),
|
||||
"klass");
|
||||
|
||||
Value *klass_part = builder()->CreateAddressOfStructEntry(
|
||||
klass,
|
||||
in_ByteSize(klassOopDesc::klass_part_offset_in_bytes()),
|
||||
SharkType::klass_type(),
|
||||
"klass_part");
|
||||
|
||||
state()->push(
|
||||
SharkValue::create_jobject(
|
||||
builder()->CreateValueOfStructEntry(
|
||||
klass_part,
|
||||
in_ByteSize(Klass::java_mirror_offset_in_bytes()),
|
||||
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_compareAndSwapInt() {
|
||||
// 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()->CreateCmpxchgInt(x, addr, e);
|
||||
|
||||
// Push the result
|
||||
state()->push(
|
||||
SharkValue::create_jint(
|
||||
builder()->CreateIntCast(
|
||||
builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true),
|
||||
false));
|
||||
}
|
||||
54
hotspot/src/share/vm/shark/sharkIntrinsics.hpp
Normal file
54
hotspot/src/share/vm/shark/sharkIntrinsics.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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_compareAndSwapInt();
|
||||
};
|
||||
37
hotspot/src/share/vm/shark/sharkInvariants.cpp
Normal file
37
hotspot/src/share/vm/shark/sharkInvariants.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkInvariants.cpp.incl"
|
||||
|
||||
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;
|
||||
}
|
||||
167
hotspot/src/share/vm/shark/sharkInvariants.hpp
Normal file
167
hotspot/src/share/vm/shark/sharkInvariants.hpp
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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.
|
||||
private:
|
||||
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();
|
||||
}
|
||||
Dependencies* dependencies() const {
|
||||
return env()->dependencies();
|
||||
}
|
||||
SharkCodeBuffer* code_buffer() const {
|
||||
return builder()->code_buffer();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
};
|
||||
116
hotspot/src/share/vm/shark/sharkMemoryManager.cpp
Normal file
116
hotspot/src/share/vm/shark/sharkMemoryManager.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkMemoryManager.cpp.incl"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::setMemoryWritable() {
|
||||
mm()->setMemoryWritable();
|
||||
}
|
||||
|
||||
void SharkMemoryManager::setMemoryExecutable() {
|
||||
mm()->setMemoryExecutable();
|
||||
}
|
||||
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
|
||||
mm()->deallocateExceptionTable(ptr);
|
||||
}
|
||||
|
||||
void SharkMemoryManager::deallocateFunctionBody(void *ptr) {
|
||||
mm()->deallocateFunctionBody(ptr);
|
||||
}
|
||||
#else
|
||||
void SharkMemoryManager::deallocateMemForFunction(const Function* F) {
|
||||
return mm()->deallocateMemForFunction(F);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t* SharkMemoryManager::allocateGlobal(uintptr_t Size,
|
||||
unsigned int Alignment) {
|
||||
return mm()->allocateGlobal(Size, Alignment);
|
||||
}
|
||||
|
||||
#if SHARK_LLVM_VERSION < 27
|
||||
void* SharkMemoryManager::getDlsymTable() const {
|
||||
return mm()->getDlsymTable();
|
||||
}
|
||||
|
||||
void SharkMemoryManager::SetDlsymTable(void *ptr) {
|
||||
mm()->SetDlsymTable(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SharkMemoryManager::setPoisonMemory(bool poison) {
|
||||
mm()->setPoisonMemory(poison);
|
||||
}
|
||||
|
||||
unsigned char *SharkMemoryManager::allocateSpace(intptr_t Size,
|
||||
unsigned int Alignment) {
|
||||
return mm()->allocateSpace(Size, Alignment);
|
||||
}
|
||||
88
hotspot/src/share/vm/shark/sharkMemoryManager.hpp
Normal file
88
hotspot/src/share/vm/shark/sharkMemoryManager.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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);
|
||||
unsigned char* startExceptionTable(const llvm::Function* F,
|
||||
uintptr_t& ActualSize);
|
||||
void endExceptionTable(const llvm::Function* F,
|
||||
unsigned char* TableStart,
|
||||
unsigned char* TableEnd,
|
||||
unsigned char* FrameRegister);
|
||||
#if SHARK_LLVM_VERSION < 27
|
||||
void* getDlsymTable() const;
|
||||
void SetDlsymTable(void *ptr);
|
||||
#endif
|
||||
void setPoisonMemory(bool);
|
||||
uint8_t* allocateGlobal(uintptr_t, unsigned int);
|
||||
void setMemoryWritable();
|
||||
void setMemoryExecutable();
|
||||
#if SHARK_LLVM_VERSION >= 27
|
||||
void deallocateExceptionTable(void *ptr);
|
||||
void deallocateFunctionBody(void *ptr);
|
||||
#else
|
||||
void deallocateMemForFunction(const llvm::Function* F);
|
||||
#endif
|
||||
unsigned char *allocateSpace(intptr_t Size,
|
||||
unsigned int Alignment);
|
||||
};
|
||||
352
hotspot/src/share/vm/shark/sharkNativeWrapper.cpp
Normal file
352
hotspot/src/share/vm/shark/sharkNativeWrapper.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkNativeWrapper.cpp.incl"
|
||||
|
||||
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()));
|
||||
oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset()));
|
||||
|
||||
// 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<const Type*> param_types;
|
||||
std::vector<Value*> param_values;
|
||||
const 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()->klass_part()->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, "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:
|
||||
const 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();
|
||||
const 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, param_values.begin(), param_values.end());
|
||||
|
||||
// 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()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
|
||||
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);
|
||||
Value *unboxed_result = builder()->CreateLoad(result);
|
||||
builder()->CreateBr(merge);
|
||||
|
||||
builder()->SetInsertPoint(merge);
|
||||
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "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));
|
||||
}
|
||||
182
hotspot/src/share/vm/shark/sharkNativeWrapper.hpp
Normal file
182
hotspot/src/share/vm/shark/sharkNativeWrapper.hpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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");
|
||||
}
|
||||
};
|
||||
251
hotspot/src/share/vm/shark/sharkRuntime.cpp
Normal file
251
hotspot/src/share/vm/shark/sharkRuntime.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkRuntime.cpp.incl"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
JRT_ENTRY(int, SharkRuntime::find_exception_handler(JavaThread* thread,
|
||||
int* indexes,
|
||||
int num_indexes))
|
||||
constantPoolHandle pool(thread, method(thread)->constants());
|
||||
KlassHandle exc_klass(thread, ((oop) tos_at(thread, 0))->klass());
|
||||
|
||||
for (int i = 0; i < num_indexes; i++) {
|
||||
klassOop tmp = pool->klass_at(indexes[i], CHECK_0);
|
||||
KlassHandle chk_klass(thread, tmp);
|
||||
|
||||
if (exc_klass() == chk_klass())
|
||||
return i;
|
||||
|
||||
if (exc_klass()->klass_part()->is_subtype_of(chk_klass()))
|
||||
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))
|
||||
klassOop k_oop = method(thread)->constants()->klass_at(index, CHECK);
|
||||
instanceKlassHandle klass(THREAD, k_oop);
|
||||
|
||||
// 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))
|
||||
klassOop 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))
|
||||
klassOop 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(object->is_oop(), "should be");
|
||||
assert(object->klass()->klass_part()->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(klassOop check_klass, klassOop object_klass) {
|
||||
return object_klass->klass_part()->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);
|
||||
thread->reset_last_Java_frame();
|
||||
|
||||
// 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;
|
||||
}
|
||||
83
hotspot/src/share/vm/shark/sharkRuntime.hpp
Normal file
83
hotspot/src/share/vm/shark/sharkRuntime.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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 methodOop 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(klassOop check_klass, klassOop object_klass);
|
||||
static int uncommon_trap(JavaThread* thread, int trap_request);
|
||||
};
|
||||
263
hotspot/src/share/vm/shark/sharkStack.cpp
Normal file
263
hotspot/src/share/vm/shark/sharkStack.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkStack.cpp.incl"
|
||||
|
||||
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::methodOop_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(StackShadowPages * os::vm_page_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,
|
||||
const 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
|
||||
290
hotspot/src/share/vm/shark/sharkStack.hpp
Normal file
290
hotspot/src/share/vm/shark/sharkStack.hpp
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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,
|
||||
const 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;
|
||||
};
|
||||
389
hotspot/src/share/vm/shark/sharkState.cpp
Normal file
389
hotspot/src/share/vm/shark/sharkState.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkState.cpp.incl"
|
||||
|
||||
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::methodOop_type(), "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(), "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(), "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::methodOop_type(), "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), 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), 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");
|
||||
}
|
||||
188
hotspot/src/share/vm/shark/sharkState.hpp
Normal file
188
hotspot/src/share/vm/shark/sharkState.hpp
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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);
|
||||
};
|
||||
99
hotspot/src/share/vm/shark/sharkStateScanner.cpp
Normal file
99
hotspot/src/share/vm/shark/sharkStateScanner.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkStateScanner.cpp.incl"
|
||||
|
||||
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
|
||||
75
hotspot/src/share/vm/shark/sharkStateScanner.hpp
Normal file
75
hotspot/src/share/vm/shark/sharkStateScanner.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
};
|
||||
1995
hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
Normal file
1995
hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
Normal file
File diff suppressed because it is too large
Load Diff
430
hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
Normal file
430
hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
Normal file
@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
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, 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();
|
||||
};
|
||||
112
hotspot/src/share/vm/shark/sharkType.hpp
Normal file
112
hotspot/src/share/vm/shark/sharkType.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class SharkType : public AllStatic {
|
||||
private:
|
||||
static SharkContext& context() {
|
||||
return SharkContext::current();
|
||||
}
|
||||
|
||||
// Basic types
|
||||
public:
|
||||
static const llvm::Type* void_type() {
|
||||
return context().void_type();
|
||||
}
|
||||
static const llvm::IntegerType* bit_type() {
|
||||
return context().bit_type();
|
||||
}
|
||||
static const llvm::IntegerType* jbyte_type() {
|
||||
return context().jbyte_type();
|
||||
}
|
||||
static const llvm::IntegerType* jshort_type() {
|
||||
return context().jshort_type();
|
||||
}
|
||||
static const llvm::IntegerType* jint_type() {
|
||||
return context().jint_type();
|
||||
}
|
||||
static const llvm::IntegerType* jlong_type() {
|
||||
return context().jlong_type();
|
||||
}
|
||||
static const llvm::Type* jfloat_type() {
|
||||
return context().jfloat_type();
|
||||
}
|
||||
static const llvm::Type* jdouble_type() {
|
||||
return context().jdouble_type();
|
||||
}
|
||||
static const llvm::IntegerType* intptr_type() {
|
||||
return context().intptr_type();
|
||||
}
|
||||
|
||||
// Compound types
|
||||
public:
|
||||
static const llvm::PointerType* itableOffsetEntry_type() {
|
||||
return context().itableOffsetEntry_type();
|
||||
}
|
||||
static const llvm::PointerType* jniEnv_type() {
|
||||
return context().jniEnv_type();
|
||||
}
|
||||
static const llvm::PointerType* jniHandleBlock_type() {
|
||||
return context().jniHandleBlock_type();
|
||||
}
|
||||
static const llvm::PointerType* klass_type() {
|
||||
return context().klass_type();
|
||||
}
|
||||
static const llvm::PointerType* methodOop_type() {
|
||||
return context().methodOop_type();
|
||||
}
|
||||
static const llvm::ArrayType* monitor_type() {
|
||||
return context().monitor_type();
|
||||
}
|
||||
static const llvm::PointerType* oop_type() {
|
||||
return context().oop_type();
|
||||
}
|
||||
static const llvm::PointerType* thread_type() {
|
||||
return context().thread_type();
|
||||
}
|
||||
static const llvm::PointerType* zeroStack_type() {
|
||||
return context().zeroStack_type();
|
||||
}
|
||||
static const llvm::FunctionType* entry_point_type() {
|
||||
return context().entry_point_type();
|
||||
}
|
||||
static const llvm::FunctionType* osr_entry_point_type() {
|
||||
return context().osr_entry_point_type();
|
||||
}
|
||||
|
||||
// Mappings
|
||||
public:
|
||||
static const llvm::Type* to_stackType(BasicType type) {
|
||||
return context().to_stackType(type);
|
||||
}
|
||||
static const llvm::Type* to_stackType(ciType* type) {
|
||||
return to_stackType(type->basic_type());
|
||||
}
|
||||
static const llvm::Type* to_arrayType(BasicType type) {
|
||||
return context().to_arrayType(type);
|
||||
}
|
||||
static const llvm::Type* to_arrayType(ciType* type) {
|
||||
return to_arrayType(type->basic_type());
|
||||
}
|
||||
};
|
||||
260
hotspot/src/share/vm/shark/sharkValue.cpp
Normal file
260
hotspot/src/share/vm/shark/sharkValue.cpp
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_sharkValue.cpp.incl"
|
||||
|
||||
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()), 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;
|
||||
}
|
||||
332
hotspot/src/share/vm/shark/sharkValue.hpp
Normal file
332
hotspot/src/share/vm/shark/sharkValue.hpp
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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);
|
||||
}
|
||||
29
hotspot/src/share/vm/shark/shark_globals.cpp
Normal file
29
hotspot/src/share/vm/shark/shark_globals.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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 "incls/_precompiled.incl"
|
||||
#include "incls/_shark_globals.cpp.incl"
|
||||
|
||||
SHARK_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
|
||||
54
hotspot/src/share/vm/shark/shark_globals.hpp
Normal file
54
hotspot/src/share/vm/shark/shark_globals.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2007, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SHARK_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
\
|
||||
product(intx, MaxNodeLimit, 65000, \
|
||||
"Maximum number of nodes") \
|
||||
\
|
||||
/* inlining */ \
|
||||
product(intx, SharkMaxInlineSize, 32, \
|
||||
"Maximum bytecode size of methods to inline when using Shark") \
|
||||
\
|
||||
/* 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") \
|
||||
|
||||
SHARK_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -151,9 +151,11 @@
|
||||
#if defined(IA32) || defined(AMD64)
|
||||
#define X86
|
||||
#define X86_ONLY(code) code
|
||||
#define NOT_X86(code)
|
||||
#else
|
||||
#undef X86
|
||||
#define X86_ONLY(code)
|
||||
#define NOT_X86(code) code
|
||||
#endif
|
||||
|
||||
#ifdef IA32
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user