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:
Gary Benson 2010-08-11 05:51:21 -07:00 committed by Christian Thalinger
parent c9ac8cc788
commit d7310fb0f7
67 changed files with 12200 additions and 40 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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)

View File

@ -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 "";
}

View 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 );

View File

@ -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
}
// ------------------------------------------------------------------

View File

@ -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();

View File

@ -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) ");
}

View File

@ -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; }

View File

@ -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

View File

@ -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;

View File

@ -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) {

View 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

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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();
}

View File

@ -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}
};

View File

@ -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);

View File

@ -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")

View 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

View 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);
}
};

File diff suppressed because it is too large Load Diff

View 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();
};

View 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);
}

View 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;
};

View 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));
}

View 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);
};

View 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;
}
};

View 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;
}

View 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();
};

View 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;
}

View 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;
}
};

View 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;
}

View 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();
};

View 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;
}
};

View 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();
}

View 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();
};

View 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;
}

View 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);
};

View 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));
}

View 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();
};

View 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;
}

View 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();
}
};

View 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);
}

View 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);
};

View 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));
}

View 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");
}
};

View 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;
}

View 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);
};

View 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

View 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;
};

View 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");
}

View 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);
};

View 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

View 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;
};

File diff suppressed because it is too large Load Diff

View 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();
};

View 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());
}
};

View 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;
}

View 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);
}

View 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)

View 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)

View File

@ -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