Merge
This commit is contained in:
commit
70ccdb4c4a
@ -24,3 +24,4 @@ e8a2a4d187773a62f3309b0fa265c13425bc2258 jdk7-b46
|
||||
d7744e86dedc21a8ecf6bdb73eb191b8eaf5b0da jdk7-b47
|
||||
4ae9f4bfdb98f65bd957e3fe72471b320150b38e jdk7-b48
|
||||
aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49
|
||||
5111e13e44e542fe945b47ab154546daec36737d jdk7-b50
|
||||
|
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -24,3 +24,4 @@ ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42
|
||||
167ad0164301f318b069a947e1c9c07ed667748a jdk7-b47
|
||||
0be222241fd405e48915647facfaa176621b39b9 jdk7-b48
|
||||
d70978bc64bc7a04be7797ab0dcd9b7b1b3a6bff jdk7-b49
|
||||
0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50
|
||||
|
@ -112,8 +112,6 @@ ifndef TARGET_JAVA
|
||||
TARGET_JAVA = java
|
||||
endif
|
||||
|
||||
NO_PROPRIETARY_API_WARNINGS = -XDignore.symbol.file=true
|
||||
|
||||
SELF = $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
# for jdk, we generate the following:
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -191,14 +191,18 @@ $(JAVA_SOURCE_LIST) : source_list_prime resources $(FILES_class)
|
||||
# Make sure all newer sources are compiled (in a batch)
|
||||
classes : $(CLASSES_INIT) .delete.classlist .compile.classlist
|
||||
|
||||
# Use this javac option to force it to favor the sourcepath file classes
|
||||
# rather than any bootclasspath classes.
|
||||
JAVAC_PREFER_SOURCE = -Xprefer:source
|
||||
|
||||
.compile.classlist : $(JAVA_SOURCE_LIST)
|
||||
@$(MKDIR) -p $(CLASSDESTDIR)
|
||||
@if [ `$(CAT) $(JAVA_SOURCE_LIST) | $(WC) -l` -ge 1 ] ; then \
|
||||
$(ECHO) "# Java sources to be compiled: (listed in file $(JAVA_SOURCE_LIST))"; \
|
||||
$(CAT) $(JAVA_SOURCE_LIST); \
|
||||
$(ECHO) "# Running javac:"; \
|
||||
$(ECHO) $(JAVAC_CMD) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
||||
$(JAVAC_CMD) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
||||
$(ECHO) $(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
||||
$(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
||||
fi
|
||||
@$(java-vm-cleanup)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -128,9 +128,19 @@ ifeq ($(PLATFORM), windows)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
# This will cause problems if ALT_COMPILER_PATH is defined to ""
|
||||
# which is a directive to use the PATH.
|
||||
REBASE = $(COMPILER_PATH)../REBASE
|
||||
ifeq ($(CC_MAJORVER), 15)
|
||||
# This should be: CC_VER=15.00.21022.8 LINK_VER=9.00.21022.8
|
||||
REQUIRED_CC_VER = 15.00.21022.8
|
||||
REQUIRED_LINK_VER = 9.00.21022.8
|
||||
COMPILER_NAME=Windows SDK 6.1 Visual Studio 9
|
||||
COMPILER_VERSION=VS2008
|
||||
RC = $(MSSDK61)/bin/x64/rc
|
||||
REBASE = $(MSSDK61/bin/x64/rebase
|
||||
else
|
||||
# This will cause problems if ALT_COMPILER_PATH is defined to ""
|
||||
# which is a directive to use the PATH.
|
||||
REBASE = $(COMPILER_PATH)../REBASE
|
||||
endif
|
||||
ifndef COMPILER_PATH
|
||||
COMPILER_PATH := $(error COMPILER_PATH cannot be empty here)
|
||||
endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -104,6 +104,9 @@ ifeq ($(COMPILER_WARNINGS_FATAL), true)
|
||||
JAVACFLAGS += -Werror
|
||||
endif
|
||||
|
||||
NO_PROPRIETARY_API_WARNINGS = -XDignore.symbol.file=true
|
||||
JAVACFLAGS += $(NO_PROPRIETARY_API_WARNINGS)
|
||||
|
||||
# Add the source level (currently all source is 1.5, should this be 1.6?)
|
||||
LANGUAGE_VERSION = -source 1.5
|
||||
JAVACFLAGS += $(LANGUAGE_VERSION)
|
||||
@ -117,7 +120,7 @@ JAVACFLAGS += -classpath $(BOOTDIR)/lib/tools.jar
|
||||
JAVACFLAGS += $(OTHER_JAVACFLAGS)
|
||||
|
||||
# Needed for javah
|
||||
JAVAHFLAGS += -bootclasspath $(CLASSBINDIR)
|
||||
JAVAHFLAGS += -classpath $(CLASSBINDIR)
|
||||
|
||||
# Langtools
|
||||
ifdef LANGTOOLS_DIST
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -282,13 +282,27 @@ endif
|
||||
|
||||
# Compilers for 64bit are from SDK
|
||||
ifeq ($(ARCH_DATA_MODEL), 64)
|
||||
ifneq ($(_ms_sdk),)
|
||||
xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
|
||||
MSSDK61 :=$(call FullPath,$(xMSSDK61))
|
||||
xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
|
||||
_vs2008 :=$(call FullPath,$(xVS2008))
|
||||
ifneq ($(_vs2008),)
|
||||
ifeq ($(ARCH), ia64)
|
||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64
|
||||
_compiler_bin :=$(_vs2008)/VC/Bin/x86_ia64
|
||||
endif
|
||||
ifeq ($(ARCH), amd64)
|
||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64/x86/$(ARCH)
|
||||
_redist_sdk :=$(_ms_sdk)/redist/win64/AMD64
|
||||
_compiler_bin :=$(_vs2008)/VC/Bin/$(ARCH)
|
||||
_redist_sdk :=$(MSSDK61)/VC/redist
|
||||
endif
|
||||
else
|
||||
ifneq ($(_ms_sdk),)
|
||||
ifeq ($(ARCH), ia64)
|
||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64
|
||||
endif
|
||||
ifeq ($(ARCH), amd64)
|
||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64/x86/$(ARCH)
|
||||
_redist_sdk :=$(_ms_sdk)/redist/win64/AMD64
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!echo "This is not a shell script"
|
||||
#############################################################################
|
||||
#
|
||||
# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* 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,7 +23,7 @@
|
||||
// have any questions.
|
||||
//
|
||||
|
||||
#include "afxres.h"
|
||||
#include "windows.h"
|
||||
|
||||
// Need 2 defines so macro argument to XSTR will get expanded before quoting.
|
||||
#define XSTR(x) STR(x)
|
||||
|
@ -24,3 +24,4 @@ fc6a5ae3fef5ebacfa896dbb3ae37715e388e282 jdk7-b43
|
||||
fcb923bad68e2b10380a030ea83a723f4dc3d4d6 jdk7-b47
|
||||
bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48
|
||||
8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49
|
||||
dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008
|
||||
|
||||
HS_MAJOR_VER=15
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=02
|
||||
HS_BUILD_NUMBER=03
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=7
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# 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,8 +61,8 @@ CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
||||
CPPFLAGS += -DASSERT
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
# Suppress warnings (for now)
|
||||
CFLAGS_WARN = -w
|
||||
# Compiler warnings are treated as errors
|
||||
CFLAGS_WARN = -Werror
|
||||
CFLAGS += $(CFLAGS_WARN)
|
||||
|
||||
OBJECTNAMES = \
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -131,6 +131,14 @@ endif
|
||||
# Enable linker optimization
|
||||
LFLAGS += -Xlinker -O1
|
||||
|
||||
# If this is a --hash-style=gnu system, use --hash-style=both
|
||||
# The gnu .hash section won't work on some Linux systems like SuSE 10.
|
||||
_HAS_HASH_STYLE_GNU:=$(shell $(CC) -dumpspecs | grep -- '--hash-style=gnu')
|
||||
ifneq ($(_HAS_HASH_STYLE_GNU),)
|
||||
LDFLAGS_HASH_STYLE = -Wl,--hash-style=both
|
||||
endif
|
||||
LFLAGS += $(LDFLAGS_HASH_STYLE)
|
||||
|
||||
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
|
||||
MAPFLAG = -Xlinker --version-script=FILENAME
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -67,6 +67,8 @@ ifndef USE_GCC
|
||||
endif
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
# Compiler warnings are treated as errors
|
||||
CFLAGS_WARN = +w -errwarn
|
||||
CFLAGS += $(CFLAGS_WARN)
|
||||
|
||||
ifeq ("${Platform_compiler}", "sparcWorks")
|
||||
|
@ -2615,6 +2615,158 @@ void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Regi
|
||||
}
|
||||
}
|
||||
|
||||
RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
|
||||
Register tmp,
|
||||
int offset) {
|
||||
intptr_t value = *delayed_value_addr;
|
||||
if (value != 0)
|
||||
return RegisterConstant(value + offset);
|
||||
|
||||
// load indirectly to solve generation ordering problem
|
||||
Address a(tmp, (address) delayed_value_addr);
|
||||
load_ptr_contents(a, tmp);
|
||||
|
||||
#ifdef ASSERT
|
||||
tst(tmp);
|
||||
breakpoint_trap(zero, xcc);
|
||||
#endif
|
||||
|
||||
if (offset != 0)
|
||||
add(tmp, offset, tmp);
|
||||
|
||||
return RegisterConstant(tmp);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
|
||||
assert(dest.register_or_noreg() != G0, "lost side effect");
|
||||
if ((src.is_constant() && src.as_constant() == 0) ||
|
||||
(src.is_register() && src.as_register() == G0)) {
|
||||
// do nothing
|
||||
} else if (dest.is_register()) {
|
||||
add(dest.as_register(), ensure_rs2(src, temp), dest.as_register());
|
||||
} else if (src.is_constant()) {
|
||||
intptr_t res = dest.as_constant() + src.as_constant();
|
||||
dest = RegisterConstant(res); // side effect seen by caller
|
||||
} else {
|
||||
assert(temp != noreg, "cannot handle constant += register");
|
||||
add(src.as_register(), ensure_rs2(dest, temp), temp);
|
||||
dest = RegisterConstant(temp); // side effect seen by caller
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
|
||||
assert(dest.register_or_noreg() != G0, "lost side effect");
|
||||
if (!is_simm13(src.constant_or_zero()))
|
||||
src = (src.as_constant() & 0xFF);
|
||||
if ((src.is_constant() && src.as_constant() == 0) ||
|
||||
(src.is_register() && src.as_register() == G0)) {
|
||||
// do nothing
|
||||
} else if (dest.is_register()) {
|
||||
sll_ptr(dest.as_register(), src, dest.as_register());
|
||||
} else if (src.is_constant()) {
|
||||
intptr_t res = dest.as_constant() << src.as_constant();
|
||||
dest = RegisterConstant(res); // side effect seen by caller
|
||||
} else {
|
||||
assert(temp != noreg, "cannot handle constant <<= register");
|
||||
set(dest.as_constant(), temp);
|
||||
sll_ptr(temp, src, temp);
|
||||
dest = RegisterConstant(temp); // side effect seen by caller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Look up the method for a megamorphic invokeinterface call.
|
||||
// The target method is determined by <intf_klass, itable_index>.
|
||||
// The receiver klass is in recv_klass.
|
||||
// On success, the result will be in method_result, and execution falls through.
|
||||
// On failure, execution transfers to the given label.
|
||||
void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||
Register intf_klass,
|
||||
RegisterConstant itable_index,
|
||||
Register method_result,
|
||||
Register scan_temp,
|
||||
Register sethi_temp,
|
||||
Label& L_no_such_interface) {
|
||||
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
|
||||
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
|
||||
"caller must use same register for non-constant itable index as for method");
|
||||
|
||||
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
||||
int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
int scan_step = itableOffsetEntry::size() * wordSize;
|
||||
int vte_size = vtableEntry::size() * wordSize;
|
||||
|
||||
lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp);
|
||||
// %%% We should store the aligned, prescaled offset in the klassoop.
|
||||
// Then the next several instructions would fold away.
|
||||
|
||||
int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0);
|
||||
int itb_offset = vtable_base;
|
||||
if (round_to_unit != 0) {
|
||||
// hoist first instruction of round_to(scan_temp, BytesPerLong):
|
||||
itb_offset += round_to_unit - wordSize;
|
||||
}
|
||||
int itb_scale = exact_log2(vtableEntry::size() * wordSize);
|
||||
sll(scan_temp, itb_scale, scan_temp);
|
||||
add(scan_temp, itb_offset, scan_temp);
|
||||
if (round_to_unit != 0) {
|
||||
// Round up to align_object_offset boundary
|
||||
// see code for instanceKlass::start_of_itable!
|
||||
// Was: round_to(scan_temp, BytesPerLong);
|
||||
// Hoisted: add(scan_temp, BytesPerLong-1, scan_temp);
|
||||
and3(scan_temp, -round_to_unit, scan_temp);
|
||||
}
|
||||
add(recv_klass, scan_temp, scan_temp);
|
||||
|
||||
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
||||
RegisterConstant itable_offset = itable_index;
|
||||
regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
|
||||
regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes());
|
||||
add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass);
|
||||
|
||||
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
|
||||
// if (scan->interface() == intf) {
|
||||
// result = (klass + scan->offset() + itable_index);
|
||||
// }
|
||||
// }
|
||||
Label search, found_method;
|
||||
|
||||
for (int peel = 1; peel >= 0; peel--) {
|
||||
// %%%% Could load both offset and interface in one ldx, if they were
|
||||
// in the opposite order. This would save a load.
|
||||
ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result);
|
||||
|
||||
// Check that this entry is non-null. A null entry means that
|
||||
// the receiver class doesn't implement the interface, and wasn't the
|
||||
// same as when the caller was compiled.
|
||||
bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface);
|
||||
delayed()->cmp(method_result, intf_klass);
|
||||
|
||||
if (peel) {
|
||||
brx(Assembler::equal, false, Assembler::pt, found_method);
|
||||
} else {
|
||||
brx(Assembler::notEqual, false, Assembler::pn, search);
|
||||
// (invert the test to fall through to found_method...)
|
||||
}
|
||||
delayed()->add(scan_temp, scan_step, scan_temp);
|
||||
|
||||
if (!peel) break;
|
||||
|
||||
bind(search);
|
||||
}
|
||||
|
||||
bind(found_method);
|
||||
|
||||
// Got a hit.
|
||||
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
|
||||
// scan_temp[-scan_step] points to the vtable offset we need
|
||||
ito_offset -= scan_step;
|
||||
lduw(scan_temp, ito_offset, scan_temp);
|
||||
ld_ptr(recv_klass, scan_temp, method_result);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||
Register temp_reg,
|
||||
Label& done, Label* slow_case,
|
||||
@ -4057,6 +4209,24 @@ void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_v
|
||||
card_table_write(bs->byte_map_base, tmp, store_addr);
|
||||
}
|
||||
|
||||
// Loading values by size and signed-ness
|
||||
void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d,
|
||||
int size_in_bytes, bool is_signed) {
|
||||
switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
|
||||
case ~8: // fall through:
|
||||
case 8: ld_long( s1, s2, d ); break;
|
||||
case ~4: ldsw( s1, s2, d ); break;
|
||||
case 4: lduw( s1, s2, d ); break;
|
||||
case ~2: ldsh( s1, s2, d ); break;
|
||||
case 2: lduh( s1, s2, d ); break;
|
||||
case ~1: ldsb( s1, s2, d ); break;
|
||||
case 1: ldub( s1, s2, d ); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MacroAssembler::load_klass(Register src_oop, Register klass) {
|
||||
// The number of bytes in this code is used by
|
||||
// MachCallDynamicJavaNode::ret_addr_offset()
|
||||
|
@ -384,6 +384,12 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
inline bool is_simm13(int offset = 0); // check disp+offset for overflow
|
||||
|
||||
Address plus_disp(int disp) const { // bump disp by a small amount
|
||||
Address a = (*this);
|
||||
a._disp += disp;
|
||||
return a;
|
||||
}
|
||||
|
||||
Address split_disp() const { // deal with disp overflow
|
||||
Address a = (*this);
|
||||
int hi_disp = _disp & ~0x3ff;
|
||||
@ -1082,6 +1088,7 @@ public:
|
||||
inline void add( Register s1, Register s2, Register d );
|
||||
inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
|
||||
inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec);
|
||||
inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0);
|
||||
inline void add( const Address& a, Register d, int offset = 0);
|
||||
|
||||
void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
@ -1298,6 +1305,16 @@ public:
|
||||
inline void ld( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldd( const Address& a, Register d, int offset = 0 );
|
||||
|
||||
inline void ldub( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ldsb( Register s1, RegisterConstant s2, Register d );
|
||||
inline void lduh( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ldsh( Register s1, RegisterConstant s2, Register d );
|
||||
inline void lduw( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ldsw( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ldx( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ld( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ldd( Register s1, RegisterConstant s2, Register d );
|
||||
|
||||
// pp 177
|
||||
|
||||
void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
@ -1518,6 +1535,13 @@ public:
|
||||
inline void st( Register d, const Address& a, int offset = 0 );
|
||||
inline void std( Register d, const Address& a, int offset = 0 );
|
||||
|
||||
inline void stb( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void sth( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void stw( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void stx( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void std( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void st( Register d, Register s1, RegisterConstant s2 );
|
||||
|
||||
// pp 177
|
||||
|
||||
void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
@ -1835,6 +1859,7 @@ class MacroAssembler: public Assembler {
|
||||
// Functions for isolating 64 bit shifts for LP64
|
||||
inline void sll_ptr( Register s1, Register s2, Register d );
|
||||
inline void sll_ptr( Register s1, int imm6a, Register d );
|
||||
inline void sll_ptr( Register s1, RegisterConstant s2, Register d );
|
||||
inline void srl_ptr( Register s1, Register s2, Register d );
|
||||
inline void srl_ptr( Register s1, int imm6a, Register d );
|
||||
|
||||
@ -1940,20 +1965,47 @@ class MacroAssembler: public Assembler {
|
||||
// st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
|
||||
inline void ld_ptr( Register s1, Register s2, Register d );
|
||||
inline void ld_ptr( Register s1, int simm13a, Register d);
|
||||
inline void ld_ptr( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ld_ptr( const Address& a, Register d, int offset = 0 );
|
||||
inline void st_ptr( Register d, Register s1, Register s2 );
|
||||
inline void st_ptr( Register d, Register s1, int simm13a);
|
||||
inline void st_ptr( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void st_ptr( Register d, const Address& a, int offset = 0 );
|
||||
|
||||
// ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
|
||||
// st_long will perform st for 32 bit VM's and stx for 64 bit VM's
|
||||
inline void ld_long( Register s1, Register s2, Register d );
|
||||
inline void ld_long( Register s1, int simm13a, Register d );
|
||||
inline void ld_long( Register s1, RegisterConstant s2, Register d );
|
||||
inline void ld_long( const Address& a, Register d, int offset = 0 );
|
||||
inline void st_long( Register d, Register s1, Register s2 );
|
||||
inline void st_long( Register d, Register s1, int simm13a );
|
||||
inline void st_long( Register d, Register s1, RegisterConstant s2 );
|
||||
inline void st_long( Register d, const Address& a, int offset = 0 );
|
||||
|
||||
// Loading values by size and signed-ness
|
||||
void load_sized_value(Register s1, RegisterConstant s2, Register d,
|
||||
int size_in_bytes, bool is_signed);
|
||||
|
||||
// Helpers for address formation.
|
||||
// They update the dest in place, whether it is a register or constant.
|
||||
// They emit no code at all if src is a constant zero.
|
||||
// If dest is a constant and src is a register, the temp argument
|
||||
// is required, and becomes the result.
|
||||
// If dest is a register and src is a non-simm13 constant,
|
||||
// the temp argument is required, and is used to materialize the constant.
|
||||
void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src,
|
||||
Register temp = noreg );
|
||||
void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src,
|
||||
Register temp = noreg );
|
||||
RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) {
|
||||
guarantee(sethi_temp != noreg, "constant offset overflow");
|
||||
if (is_simm13(rs2.constant_or_zero()))
|
||||
return rs2; // register or short constant
|
||||
set(rs2.as_constant(), sethi_temp);
|
||||
return sethi_temp;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
public:
|
||||
@ -2267,6 +2319,14 @@ class MacroAssembler: public Assembler {
|
||||
);
|
||||
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
|
||||
|
||||
// interface method calling
|
||||
void lookup_interface_method(Register recv_klass,
|
||||
Register intf_klass,
|
||||
RegisterConstant itable_index,
|
||||
Register method_result,
|
||||
Register temp_reg, Register temp2_reg,
|
||||
Label& no_such_interface);
|
||||
|
||||
// Stack overflow checking
|
||||
|
||||
// Note: this clobbers G3_scratch
|
||||
@ -2281,6 +2341,8 @@ class MacroAssembler: public Assembler {
|
||||
// stack overflow + shadow pages. Clobbers tsp and scratch registers.
|
||||
void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
|
||||
|
||||
virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset);
|
||||
|
||||
void verify_tlab();
|
||||
|
||||
Condition negate_condition(Condition cond);
|
||||
|
@ -143,6 +143,49 @@ inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2
|
||||
inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
|
||||
#endif
|
||||
|
||||
inline void Assembler::ldub( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsb(s1, s2.as_register(), d);
|
||||
else ldsb(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ldsb( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsb(s1, s2.as_register(), d);
|
||||
else ldsb(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::lduh( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsh(s1, s2.as_register(), d);
|
||||
else ldsh(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ldsh( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsh(s1, s2.as_register(), d);
|
||||
else ldsh(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsw(s1, s2.as_register(), d);
|
||||
else ldsw(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsw(s1, s2.as_register(), d);
|
||||
else ldsw(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldx(s1, s2.as_register(), d);
|
||||
else ldx(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ld(s1, s2.as_register(), d);
|
||||
else ld(s1, s2.as_constant(), d);
|
||||
}
|
||||
inline void Assembler::ldd( Register s1, RegisterConstant s2, Register d) {
|
||||
if (s2.is_register()) ldd(s1, s2.as_register(), d);
|
||||
else ldd(s1, s2.as_constant(), d);
|
||||
}
|
||||
|
||||
// form effective addresses this way:
|
||||
inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) {
|
||||
if (s2.is_register()) add(s1, s2.as_register(), d);
|
||||
else { add(s1, s2.as_constant() + offset, d); offset = 0; }
|
||||
if (offset != 0) add(d, offset, d);
|
||||
}
|
||||
|
||||
inline void Assembler::ld( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); }
|
||||
@ -200,6 +243,27 @@ inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); a
|
||||
inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); }
|
||||
inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
|
||||
|
||||
inline void Assembler::stb( Register d, Register s1, RegisterConstant s2) {
|
||||
if (s2.is_register()) stb(d, s1, s2.as_register());
|
||||
else stb(d, s1, s2.as_constant());
|
||||
}
|
||||
inline void Assembler::sth( Register d, Register s1, RegisterConstant s2) {
|
||||
if (s2.is_register()) sth(d, s1, s2.as_register());
|
||||
else sth(d, s1, s2.as_constant());
|
||||
}
|
||||
inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) {
|
||||
if (s2.is_register()) stx(d, s1, s2.as_register());
|
||||
else stx(d, s1, s2.as_constant());
|
||||
}
|
||||
inline void Assembler::std( Register d, Register s1, RegisterConstant s2) {
|
||||
if (s2.is_register()) std(d, s1, s2.as_register());
|
||||
else std(d, s1, s2.as_constant());
|
||||
}
|
||||
inline void Assembler::st( Register d, Register s1, RegisterConstant s2) {
|
||||
if (s2.is_register()) st(d, s1, s2.as_register());
|
||||
else st(d, s1, s2.as_constant());
|
||||
}
|
||||
|
||||
inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); }
|
||||
@ -244,6 +308,14 @@ inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( s1, s2, d);
|
||||
#else
|
||||
Assembler::ld( s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( a, d, offset );
|
||||
@ -268,6 +340,14 @@ inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, s1, s2);
|
||||
#else
|
||||
Assembler::st( d, s1, s2);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, const Address& a, int offset) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, a, offset);
|
||||
@ -293,6 +373,14 @@ inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx(s1, s2, d);
|
||||
#else
|
||||
Assembler::ldd(s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_long( const Address& a, Register d, int offset ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx(a, d, offset );
|
||||
@ -317,6 +405,14 @@ inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx(d, s1, s2);
|
||||
#else
|
||||
Assembler::std(d, s1, s2);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx(d, a, offset);
|
||||
@ -359,6 +455,11 @@ inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) {
|
||||
if (s2.is_register()) sll_ptr(s1, s2.as_register(), d);
|
||||
else sll_ptr(s1, s2.as_constant(), d);
|
||||
}
|
||||
|
||||
// Use the right branch for the platform
|
||||
|
||||
inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) {
|
||||
|
@ -2465,7 +2465,10 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
|
||||
// InterpreterRuntime::post_method_entry();
|
||||
// }
|
||||
// if (DTraceMethodProbes) {
|
||||
// SharedRuntime::dtrace_method_entry(method, reciever);
|
||||
// SharedRuntime::dtrace_method_entry(method, receiver);
|
||||
// }
|
||||
// if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
// SharedRuntime::rc_trace_method_entry(method, receiver);
|
||||
// }
|
||||
|
||||
void InterpreterMacroAssembler::notify_method_entry() {
|
||||
@ -2497,6 +2500,13 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
|
||||
G2_thread, Lmethod);
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
call_VM_leaf(noreg,
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
G2_thread, Lmethod);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -243,7 +243,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
// Regenerate the instruction sequence that performs the 64 bit
|
||||
// sethi. This only does the sethi. The disp field (bottom 10 bits)
|
||||
// must be handled seperately.
|
||||
// must be handled separately.
|
||||
static void set_data64_sethi(address instaddr, intptr_t x);
|
||||
|
||||
// combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st)
|
||||
|
@ -2161,6 +2161,18 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
__ restore();
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
// create inner frame
|
||||
__ save_frame(0);
|
||||
__ mov(G2_thread, L7_thread_cache);
|
||||
__ set_oop_constant(JNIHandles::make_local(method()), O1);
|
||||
__ call_VM_leaf(L7_thread_cache,
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
G2_thread, O1);
|
||||
__ restore();
|
||||
}
|
||||
|
||||
// We are in the jni frame unless saved_frame is true in which case
|
||||
// we are in one frame deeper (the "inner" frame). If we are in the
|
||||
// "inner" frames the args are in the Iregs and if the jni frame then
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -189,7 +189,7 @@ reg_def R_F31( SOC, SOC, Op_RegF, 31, F31->as_VMReg());
|
||||
// double fp register numbers. FloatRegisterImpl in register_sparc.hpp
|
||||
// wants 0-63, so we have to convert every time we want to use fp regs
|
||||
// with the macroassembler, using reg_to_DoubleFloatRegister_object().
|
||||
// 255 is a flag meaning 'dont go here'.
|
||||
// 255 is a flag meaning "don't go here".
|
||||
// I believe we can't handle callee-save doubles D32 and up until
|
||||
// the place in the sparc stack crawler that asserts on the 255 is
|
||||
// fixed up.
|
||||
@ -462,7 +462,7 @@ extern bool can_branch_register( Node *bol, Node *cmp );
|
||||
|
||||
// Macros to extract hi & lo halves from a long pair.
|
||||
// G0 is not part of any long pair, so assert on that.
|
||||
// Prevents accidently using G1 instead of G0.
|
||||
// Prevents accidentally using G1 instead of G0.
|
||||
#define LONG_HI_REG(x) (x)
|
||||
#define LONG_LO_REG(x) (x)
|
||||
|
||||
@ -1431,7 +1431,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
|
||||
|
||||
#ifndef _LP64
|
||||
// In the LP64 build, all registers can be moved as aligned/adjacent
|
||||
// pairs, so there's never any need to move the high bits seperately.
|
||||
// pairs, so there's never any need to move the high bits separately.
|
||||
// The 32-bit builds have to deal with the 32-bit ABI which can force
|
||||
// all sorts of silly alignment problems.
|
||||
|
||||
@ -1624,7 +1624,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Register temp_reg = G3;
|
||||
assert( G5_ic_reg != temp_reg, "conflicting registers" );
|
||||
|
||||
// Load klass from reciever
|
||||
// Load klass from receiver
|
||||
__ load_klass(O0, temp_reg);
|
||||
// Compare against expected klass
|
||||
__ cmp(temp_reg, G5_ic_reg);
|
||||
@ -4149,7 +4149,7 @@ operand cmpOp_commute() %{
|
||||
|
||||
//----------OPERAND CLASSES----------------------------------------------------
|
||||
// Operand Classes are groups of operands that are used to simplify
|
||||
// instruction definitions by not requiring the AD writer to specify seperate
|
||||
// instruction definitions by not requiring the AD writer to specify separate
|
||||
// instructions for every form of operand when the instruction accepts
|
||||
// multiple operand types with the same basic encoding and format. The classic
|
||||
// case of this is memory operands.
|
||||
@ -5286,55 +5286,91 @@ instruct loadB(iRegI dst, memory mem) %{
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDSB $mem,$dst" %}
|
||||
format %{ "LDSB $mem,$dst\t! byte" %}
|
||||
opcode(Assembler::ldsb_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Byte (8bit UNsigned) into an int reg
|
||||
instruct loadUB(iRegI dst, memory mem, immI_255 bytemask) %{
|
||||
match(Set dst (AndI (LoadB mem) bytemask));
|
||||
// Load Byte (8bit signed) into a Long Register
|
||||
instruct loadB2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadB mem)));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUB $mem,$dst" %}
|
||||
format %{ "LDSB $mem,$dst\t! byte -> long" %}
|
||||
opcode(Assembler::ldsb_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8bit UNsigned) into an int reg
|
||||
instruct loadUB(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUB mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUB $mem,$dst\t! ubyte" %}
|
||||
opcode(Assembler::ldub_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Byte (8bit UNsigned) into a Long Register
|
||||
instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadB mem)) bytemask));
|
||||
// Load Unsigned Byte (8bit UNsigned) into a Long Register
|
||||
instruct loadUB2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadUB mem)));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUB $mem,$dst" %}
|
||||
format %{ "LDUB $mem,$dst\t! ubyte -> long" %}
|
||||
opcode(Assembler::ldub_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
|
||||
instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask));
|
||||
// Load Short (16bit signed)
|
||||
instruct loadS(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadS mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUH $mem,$dst" %}
|
||||
opcode(Assembler::lduh_op3);
|
||||
format %{ "LDSH $mem,$dst\t! short" %}
|
||||
opcode(Assembler::ldsh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit unsigned)
|
||||
// Load Short (16bit signed) into a Long Register
|
||||
instruct loadS2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadS mem)));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDSH $mem,$dst\t! short -> long" %}
|
||||
opcode(Assembler::ldsh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned)
|
||||
instruct loadUS(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUS mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUH $mem,$dst" %}
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char" %}
|
||||
opcode(Assembler::lduh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
|
||||
instruct loadUS2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadUS mem)));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char -> long" %}
|
||||
opcode(Assembler::lduh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
@ -5344,9 +5380,33 @@ instruct loadUS(iRegI dst, memory mem) %{
|
||||
instruct loadI(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadI mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
size(4);
|
||||
|
||||
format %{ "LDUW $mem,$dst" %}
|
||||
size(4);
|
||||
format %{ "LDUW $mem,$dst\t! int" %}
|
||||
opcode(Assembler::lduw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into a Long Register
|
||||
instruct loadI2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadI mem)));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDSW $mem,$dst\t! int -> long" %}
|
||||
opcode(Assembler::ldsw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Integer into a Long Register
|
||||
instruct loadUI2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (LoadUI2L mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDUW $mem,$dst\t! uint -> long" %}
|
||||
opcode(Assembler::lduw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mem);
|
||||
@ -5356,6 +5416,7 @@ instruct loadI(iRegI dst, memory mem) %{
|
||||
instruct loadL(iRegL dst, memory mem ) %{
|
||||
match(Set dst (LoadL mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDX $mem,$dst\t! long" %}
|
||||
opcode(Assembler::ldx_op3);
|
||||
@ -5471,13 +5532,11 @@ instruct loadN(iRegN dst, memory mem) %{
|
||||
|
||||
format %{ "LDUW $mem,$dst\t! compressed ptr" %}
|
||||
ins_encode %{
|
||||
Register base = as_Register($mem$$base);
|
||||
Register index = as_Register($mem$$index);
|
||||
Register dst = $dst$$Register;
|
||||
Register index = $mem$$index$$Register;
|
||||
if (index != G0) {
|
||||
__ lduw(base, index, dst);
|
||||
__ lduw($mem$$base$$Register, index, $dst$$Register);
|
||||
} else {
|
||||
__ lduw(base, $mem$$disp, dst);
|
||||
__ lduw($mem$$base$$Register, $mem$$disp, $dst$$Register);
|
||||
}
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
@ -5521,18 +5580,6 @@ instruct loadNKlass(iRegN dst, memory mem) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed)
|
||||
instruct loadS(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadS mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDSH $mem,$dst" %}
|
||||
opcode(Assembler::ldsh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Double
|
||||
instruct loadD(regD dst, memory mem) %{
|
||||
match(Set dst (LoadD mem));
|
||||
@ -6847,7 +6894,7 @@ instruct mul_hi(iRegIsafe dst, iRegIsafe src1, iRegIsafe src2 ) %{
|
||||
ins_pipe(sdiv_reg_reg);
|
||||
%}
|
||||
|
||||
// Magic constant, reciprical of 10
|
||||
// Magic constant, reciprocal of 10
|
||||
instruct loadConI_x66666667(iRegIsafe dst) %{
|
||||
effect( DEF dst );
|
||||
|
||||
@ -6857,7 +6904,7 @@ instruct loadConI_x66666667(iRegIsafe dst) %{
|
||||
ins_pipe(ialu_hi_lo_reg);
|
||||
%}
|
||||
|
||||
// Register Shift Right Arithmatic Long by 32-63
|
||||
// Register Shift Right Arithmetic Long by 32-63
|
||||
instruct sra_31( iRegI dst, iRegI src ) %{
|
||||
effect( DEF dst, USE src );
|
||||
format %{ "SRA $src,31,$dst\t! Used in div-by-10" %}
|
||||
@ -9048,7 +9095,7 @@ instruct storeL_reversed(memory dst, iRegL src) %{
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
//
|
||||
// peepmatch ( root_instr_name [preceeding_instruction]* );
|
||||
// peepmatch ( root_instr_name [preceding_instruction]* );
|
||||
//
|
||||
// peepconstraint %{
|
||||
// (instruction_number.operand_name relational_op instruction_number.operand_name
|
||||
|
@ -1545,7 +1545,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
||||
|
||||
// Handle all the JSR stuff here, then exit.
|
||||
// It's much shorter and cleaner than intermingling with the
|
||||
// non-JSR normal-branch stuff occuring below.
|
||||
// non-JSR normal-branch stuff occurring below.
|
||||
if( is_jsr ) {
|
||||
// compute return address as bci in Otos_i
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), G3_scratch);
|
||||
@ -3079,7 +3079,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
Label ok;
|
||||
|
||||
// Check that entry is non-null. Null entries are probably a bytecode
|
||||
// problem. If the interface isn't implemented by the reciever class,
|
||||
// problem. If the interface isn't implemented by the receiver class,
|
||||
// the VM should throw IncompatibleClassChangeError. linkResolver checks
|
||||
// this too but that's only if the entry isn't already resolved, so we
|
||||
// need to check again.
|
||||
|
@ -106,6 +106,15 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
__ delayed()->nop();
|
||||
|
||||
masm->flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
vtable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
return s;
|
||||
}
|
||||
@ -113,9 +122,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
|
||||
// NOTE: %%%% if any change is made to this stub make sure that the function
|
||||
// pd_code_size_limit is changed to ensure the correct size for VtableStub
|
||||
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
const int sparc_code_length = VtableStub::pd_code_size_limit(false);
|
||||
VtableStub* s = new(sparc_code_length) VtableStub(false, vtable_index);
|
||||
VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index);
|
||||
ResourceMark rm;
|
||||
CodeBuffer cb(s->entry_point(), sparc_code_length);
|
||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||
@ -139,7 +148,6 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
// are passed in the %o registers. Instead, longs are passed in G1 and G4
|
||||
// and so those registers are not available here.
|
||||
__ save(SP,-frame::register_save_words*wordSize,SP);
|
||||
Register I0_receiver = I0; // Location of receiver after save
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (CountCompiledCalls) {
|
||||
@ -151,63 +159,31 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
}
|
||||
#endif /* PRODUCT */
|
||||
|
||||
// load start of itable entries into L0 register
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
__ ld(Address(G3_klassOop, 0, instanceKlass::vtable_length_offset() * wordSize), L0);
|
||||
|
||||
// %%% Could store the aligned, prescaled offset in the klassoop.
|
||||
__ sll(L0, exact_log2(vtableEntry::size() * wordSize), L0);
|
||||
// see code for instanceKlass::start_of_itable!
|
||||
const int vtable_alignment = align_object_offset(1);
|
||||
assert(vtable_alignment == 1 || vtable_alignment == 2, "");
|
||||
const int odd_bit = vtableEntry::size() * wordSize;
|
||||
if (vtable_alignment == 2) {
|
||||
__ and3(L0, odd_bit, L1); // isolate the odd bit
|
||||
}
|
||||
__ add(G3_klassOop, L0, L0);
|
||||
if (vtable_alignment == 2) {
|
||||
__ add(L0, L1, L0); // double the odd bit, to align up
|
||||
}
|
||||
|
||||
// Loop over all itable entries until desired interfaceOop (G5_interface) found
|
||||
__ bind(search);
|
||||
|
||||
// %%%% Could load both offset and interface in one ldx, if they were
|
||||
// in the opposite order. This would save a load.
|
||||
__ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1);
|
||||
|
||||
// If the entry is NULL then we've reached the end of the table
|
||||
// without finding the expected interface, so throw an exception
|
||||
Label throw_icce;
|
||||
__ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce);
|
||||
__ delayed()->cmp(G5_interface, L1);
|
||||
__ brx(Assembler::notEqual, true, Assembler::pn, search);
|
||||
__ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0);
|
||||
|
||||
// entry found and L0 points to it, move offset of vtable for interface into L0
|
||||
__ ld(L0, base + itableOffsetEntry::offset_offset_in_bytes(), L0);
|
||||
|
||||
// Compute itableMethodEntry and get methodOop(G5_method) and entrypoint(L0) for compiler
|
||||
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
|
||||
__ add(G3_klassOop, L0, L1);
|
||||
__ ld_ptr(L1, method_offset, G5_method);
|
||||
Register L5_method = L5;
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
G3_klassOop, G5_interface, itable_index,
|
||||
// outputs: method, scan temp. reg
|
||||
L5_method, L2, L3,
|
||||
throw_icce);
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (DebugVtables) {
|
||||
Label L01;
|
||||
__ ld_ptr(L1, method_offset, G5_method);
|
||||
__ bpr(Assembler::rc_nz, false, Assembler::pt, G5_method, L01);
|
||||
__ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01);
|
||||
__ delayed()->nop();
|
||||
__ stop("methodOop is null");
|
||||
__ bind(L01);
|
||||
__ verify_oop(G5_method);
|
||||
__ verify_oop(L5_method);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the following load is through a NULL pointer, we'll take an OS
|
||||
// exception that should translate into an AbstractMethodError. We need the
|
||||
// window count to be correct at that time.
|
||||
__ restore(); // Restore registers BEFORE the AME point
|
||||
__ restore(L5_method, 0, G5_method);
|
||||
// Restore registers *before* the AME point.
|
||||
|
||||
address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract
|
||||
__ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
|
||||
@ -225,6 +201,12 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
|
||||
masm->flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
itable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
@ -243,8 +225,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||
(UseCompressedOops ? 2*BytesPerInstWord : 0);
|
||||
return basic + slop;
|
||||
} else {
|
||||
// save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore
|
||||
const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord +
|
||||
const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
|
||||
// shift;add for load_klass
|
||||
(UseCompressedOops ? 2*BytesPerInstWord : 0);
|
||||
return (basic + slop);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -129,13 +129,19 @@ Address::Address(address loc, RelocationHolder spec) {
|
||||
// Convert the raw encoding form into the form expected by the constructor for
|
||||
// Address. An index of 4 (rsp) corresponds to having no index, so convert
|
||||
// that to noreg for the Address constructor.
|
||||
Address Address::make_raw(int base, int index, int scale, int disp) {
|
||||
Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) {
|
||||
RelocationHolder rspec;
|
||||
if (disp_is_oop) {
|
||||
rspec = Relocation::spec_simple(relocInfo::oop_type);
|
||||
}
|
||||
bool valid_index = index != rsp->encoding();
|
||||
if (valid_index) {
|
||||
Address madr(as_Register(base), as_Register(index), (Address::ScaleFactor)scale, in_ByteSize(disp));
|
||||
madr._rspec = rspec;
|
||||
return madr;
|
||||
} else {
|
||||
Address madr(as_Register(base), noreg, Address::no_scale, in_ByteSize(disp));
|
||||
madr._rspec = rspec;
|
||||
return madr;
|
||||
}
|
||||
}
|
||||
@ -3892,6 +3898,21 @@ void Assembler::movq(Address dst, Register src) {
|
||||
emit_operand(src, dst);
|
||||
}
|
||||
|
||||
void Assembler::movsbq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
prefixq(src, dst);
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBE);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movsbq(Register dst, Register src) {
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBE);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::movslq(Register dst, int32_t imm32) {
|
||||
// dbx shows movslq(rcx, 3) as movq $0x0000000049000000,(%rbx)
|
||||
// and movslq(r8, 3); as movl $0x0000000048000000,(%rbx)
|
||||
@ -3925,6 +3946,51 @@ void Assembler::movslq(Register dst, Register src) {
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::movswq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
prefixq(src, dst);
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBF);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movswq(Register dst, Register src) {
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBF);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::movzbq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
prefixq(src, dst);
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xB6);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movzbq(Register dst, Register src) {
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xB6);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::movzwq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
prefixq(src, dst);
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xB7);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movzwq(Register dst, Register src) {
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xB7);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::negq(Register dst) {
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
emit_byte(0xF7);
|
||||
@ -6197,8 +6263,11 @@ int MacroAssembler::load_signed_byte(Register dst, Address src) {
|
||||
return off;
|
||||
}
|
||||
|
||||
// word => int32 which seems bad for 64bit
|
||||
int MacroAssembler::load_signed_word(Register dst, Address src) {
|
||||
// Note: load_signed_short used to be called load_signed_word.
|
||||
// Although the 'w' in x86 opcodes refers to the term "word" in the assembler
|
||||
// manual, which means 16 bits, that usage is found nowhere in HotSpot code.
|
||||
// The term "word" in HotSpot means a 32- or 64-bit machine word.
|
||||
int MacroAssembler::load_signed_short(Register dst, Address src) {
|
||||
int off;
|
||||
if (LP64_ONLY(true ||) VM_Version::is_P6()) {
|
||||
// This is dubious to me since it seems safe to do a signed 16 => 64 bit
|
||||
@ -6207,7 +6276,7 @@ int MacroAssembler::load_signed_word(Register dst, Address src) {
|
||||
off = offset();
|
||||
movswl(dst, src); // movsxw
|
||||
} else {
|
||||
off = load_unsigned_word(dst, src);
|
||||
off = load_unsigned_short(dst, src);
|
||||
shll(dst, 16);
|
||||
sarl(dst, 16);
|
||||
}
|
||||
@ -6229,7 +6298,8 @@ int MacroAssembler::load_unsigned_byte(Register dst, Address src) {
|
||||
return off;
|
||||
}
|
||||
|
||||
int MacroAssembler::load_unsigned_word(Register dst, Address src) {
|
||||
// Note: load_unsigned_short used to be called load_unsigned_word.
|
||||
int MacroAssembler::load_unsigned_short(Register dst, Address src) {
|
||||
// According to Intel Doc. AP-526, "Zero-Extension of Short", p.16,
|
||||
// and "3.9 Partial Register Penalties", p. 22).
|
||||
int off;
|
||||
@ -6244,6 +6314,28 @@ int MacroAssembler::load_unsigned_word(Register dst, Address src) {
|
||||
return off;
|
||||
}
|
||||
|
||||
void MacroAssembler::load_sized_value(Register dst, Address src,
|
||||
int size_in_bytes, bool is_signed) {
|
||||
switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
|
||||
#ifndef _LP64
|
||||
// For case 8, caller is responsible for manually loading
|
||||
// the second word into another register.
|
||||
case ~8: // fall through:
|
||||
case 8: movl( dst, src ); break;
|
||||
#else
|
||||
case ~8: // fall through:
|
||||
case 8: movq( dst, src ); break;
|
||||
#endif
|
||||
case ~4: // fall through:
|
||||
case 4: movl( dst, src ); break;
|
||||
case ~2: load_signed_short( dst, src ); break;
|
||||
case 2: load_unsigned_short( dst, src ); break;
|
||||
case ~1: load_signed_byte( dst, src ); break;
|
||||
case 1: load_unsigned_byte( dst, src ); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::mov32(AddressLiteral dst, Register src) {
|
||||
if (reachable(dst)) {
|
||||
movl(as_Address(dst), src);
|
||||
@ -6463,7 +6555,8 @@ void MacroAssembler::serialize_memory(Register thread, Register tmp) {
|
||||
Address index(noreg, tmp, Address::times_1);
|
||||
ExternalAddress page(os::get_memory_serialize_page());
|
||||
|
||||
movptr(ArrayAddress(page, index), tmp);
|
||||
// Size of store must match masking code above
|
||||
movl(as_Address(ArrayAddress(page, index)), tmp);
|
||||
}
|
||||
|
||||
// Calls to C land
|
||||
@ -7049,6 +7142,81 @@ void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) {
|
||||
}
|
||||
|
||||
|
||||
// Look up the method for a megamorphic invokeinterface call.
|
||||
// The target method is determined by <intf_klass, itable_index>.
|
||||
// The receiver klass is in recv_klass.
|
||||
// On success, the result will be in method_result, and execution falls through.
|
||||
// On failure, execution transfers to the given label.
|
||||
void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||
Register intf_klass,
|
||||
RegisterConstant itable_index,
|
||||
Register method_result,
|
||||
Register scan_temp,
|
||||
Label& L_no_such_interface) {
|
||||
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
|
||||
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
|
||||
"caller must use same register for non-constant itable index as for method");
|
||||
|
||||
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
||||
int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
int itentry_off = itableMethodEntry::method_offset_in_bytes();
|
||||
int scan_step = itableOffsetEntry::size() * wordSize;
|
||||
int vte_size = vtableEntry::size() * wordSize;
|
||||
Address::ScaleFactor times_vte_scale = Address::times_ptr;
|
||||
assert(vte_size == wordSize, "else adjust times_vte_scale");
|
||||
|
||||
movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
|
||||
|
||||
// %%% Could store the aligned, prescaled offset in the klassoop.
|
||||
lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
// see code for instanceKlass::start_of_itable!
|
||||
round_to(scan_temp, BytesPerLong);
|
||||
}
|
||||
|
||||
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
||||
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
|
||||
lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
|
||||
|
||||
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
|
||||
// if (scan->interface() == intf) {
|
||||
// result = (klass + scan->offset() + itable_index);
|
||||
// }
|
||||
// }
|
||||
Label search, found_method;
|
||||
|
||||
for (int peel = 1; peel >= 0; peel--) {
|
||||
movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
cmpptr(intf_klass, method_result);
|
||||
|
||||
if (peel) {
|
||||
jccb(Assembler::equal, found_method);
|
||||
} else {
|
||||
jccb(Assembler::notEqual, search);
|
||||
// (invert the test to fall through to found_method...)
|
||||
}
|
||||
|
||||
if (!peel) break;
|
||||
|
||||
bind(search);
|
||||
|
||||
// Check that the previous entry is non-null. A null entry means that
|
||||
// the receiver class doesn't implement the interface, and wasn't the
|
||||
// same as when the caller was compiled.
|
||||
testptr(method_result, method_result);
|
||||
jcc(Assembler::zero, L_no_such_interface);
|
||||
addptr(scan_temp, scan_step);
|
||||
}
|
||||
|
||||
bind(found_method);
|
||||
|
||||
// Got a hit.
|
||||
movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) {
|
||||
ucomisd(dst, as_Address(src));
|
||||
}
|
||||
@ -7094,6 +7262,31 @@ void MacroAssembler::verify_oop(Register reg, const char* s) {
|
||||
}
|
||||
|
||||
|
||||
RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
|
||||
Register tmp,
|
||||
int offset) {
|
||||
intptr_t value = *delayed_value_addr;
|
||||
if (value != 0)
|
||||
return RegisterConstant(value + offset);
|
||||
|
||||
// load indirectly to solve generation ordering problem
|
||||
movptr(tmp, ExternalAddress((address) delayed_value_addr));
|
||||
|
||||
#ifdef ASSERT
|
||||
Label L;
|
||||
testl(tmp, tmp);
|
||||
jccb(Assembler::notZero, L);
|
||||
hlt();
|
||||
bind(L);
|
||||
#endif
|
||||
|
||||
if (offset != 0)
|
||||
addptr(tmp, offset);
|
||||
|
||||
return RegisterConstant(tmp);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
|
||||
if (!VerifyOops) return;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -153,6 +153,21 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
times_8 = 3,
|
||||
times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4)
|
||||
};
|
||||
static ScaleFactor times(int size) {
|
||||
assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size");
|
||||
if (size == 8) return times_8;
|
||||
if (size == 4) return times_4;
|
||||
if (size == 2) return times_2;
|
||||
return times_1;
|
||||
}
|
||||
static int scale_size(ScaleFactor scale) {
|
||||
assert(scale != no_scale, "");
|
||||
assert(((1 << (int)times_1) == 1 &&
|
||||
(1 << (int)times_2) == 2 &&
|
||||
(1 << (int)times_4) == 4 &&
|
||||
(1 << (int)times_8) == 8), "");
|
||||
return (1 << (int)scale);
|
||||
}
|
||||
|
||||
private:
|
||||
Register _base;
|
||||
@ -197,6 +212,22 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
"inconsistent address");
|
||||
}
|
||||
|
||||
Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0)
|
||||
: _base (base),
|
||||
_index(index.register_or_noreg()),
|
||||
_scale(scale),
|
||||
_disp (disp + (index.constant_or_zero() * scale_size(scale))) {
|
||||
if (!index.is_register()) scale = Address::no_scale;
|
||||
assert(!_index->is_valid() == (scale == Address::no_scale),
|
||||
"inconsistent address");
|
||||
}
|
||||
|
||||
Address plus_disp(int disp) const {
|
||||
Address a = (*this);
|
||||
a._disp += disp;
|
||||
return a;
|
||||
}
|
||||
|
||||
// The following two overloads are used in connection with the
|
||||
// ByteSize type (see sizes.hpp). They simplify the use of
|
||||
// ByteSize'd arguments in assembly code. Note that their equivalent
|
||||
@ -224,6 +255,17 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
assert(!index->is_valid() == (scale == Address::no_scale),
|
||||
"inconsistent address");
|
||||
}
|
||||
|
||||
Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp)
|
||||
: _base (base),
|
||||
_index(index.register_or_noreg()),
|
||||
_scale(scale),
|
||||
_disp (in_bytes(disp) + (index.constant_or_zero() * scale_size(scale))) {
|
||||
if (!index.is_register()) scale = Address::no_scale;
|
||||
assert(!_index->is_valid() == (scale == Address::no_scale),
|
||||
"inconsistent address");
|
||||
}
|
||||
|
||||
#endif // ASSERT
|
||||
|
||||
// accessors
|
||||
@ -236,11 +278,10 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
// Convert the raw encoding form into the form expected by the constructor for
|
||||
// Address. An index of 4 (rsp) corresponds to having no index, so convert
|
||||
// that to noreg for the Address constructor.
|
||||
static Address make_raw(int base, int index, int scale, int disp);
|
||||
static Address make_raw(int base, int index, int scale, int disp, bool disp_is_oop);
|
||||
|
||||
static Address make_array(ArrayAddress);
|
||||
|
||||
|
||||
private:
|
||||
bool base_needs_rex() const {
|
||||
return _base != noreg && _base->encoding() >= 8;
|
||||
@ -1097,6 +1138,9 @@ private:
|
||||
void movsbl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void movsbq(Register dst, Address src);
|
||||
void movsbq(Register dst, Register src);
|
||||
|
||||
// Move signed 32bit immediate to 64bit extending sign
|
||||
void movslq(Address dst, int32_t imm64);
|
||||
void movslq(Register dst, int32_t imm64);
|
||||
@ -1109,6 +1153,11 @@ private:
|
||||
void movswl(Register dst, Address src);
|
||||
void movswl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void movswq(Register dst, Address src);
|
||||
void movswq(Register dst, Register src);
|
||||
#endif
|
||||
|
||||
void movw(Address dst, int imm16);
|
||||
void movw(Register dst, Address src);
|
||||
void movw(Address dst, Register src);
|
||||
@ -1116,9 +1165,19 @@ private:
|
||||
void movzbl(Register dst, Address src);
|
||||
void movzbl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void movzbq(Register dst, Address src);
|
||||
void movzbq(Register dst, Register src);
|
||||
#endif
|
||||
|
||||
void movzwl(Register dst, Address src);
|
||||
void movzwl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void movzwq(Register dst, Address src);
|
||||
void movzwq(Register dst, Register src);
|
||||
#endif
|
||||
|
||||
void mull(Address src);
|
||||
void mull(Register src);
|
||||
|
||||
@ -1393,17 +1452,20 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
// The following 4 methods return the offset of the appropriate move instruction
|
||||
|
||||
// Support for fast byte/word loading with zero extension (depending on particular CPU)
|
||||
// Support for fast byte/short loading with zero extension (depending on particular CPU)
|
||||
int load_unsigned_byte(Register dst, Address src);
|
||||
int load_unsigned_word(Register dst, Address src);
|
||||
int load_unsigned_short(Register dst, Address src);
|
||||
|
||||
// Support for fast byte/word loading with sign extension (depending on particular CPU)
|
||||
// Support for fast byte/short loading with sign extension (depending on particular CPU)
|
||||
int load_signed_byte(Register dst, Address src);
|
||||
int load_signed_word(Register dst, Address src);
|
||||
int load_signed_short(Register dst, Address src);
|
||||
|
||||
// Support for sign-extension (hi:lo = extend_sign(lo))
|
||||
void extend_sign(Register hi, Register lo);
|
||||
|
||||
// Loading values by size and signed-ness
|
||||
void load_sized_value(Register dst, Address src, int size_in_bytes, bool is_signed);
|
||||
|
||||
// Support for inc/dec with optimal instruction selection depending on value
|
||||
|
||||
void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; }
|
||||
@ -1721,6 +1783,14 @@ class MacroAssembler: public Assembler {
|
||||
);
|
||||
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
|
||||
|
||||
// interface method calling
|
||||
void lookup_interface_method(Register recv_klass,
|
||||
Register intf_klass,
|
||||
RegisterConstant itable_index,
|
||||
Register method_result,
|
||||
Register scan_temp,
|
||||
Label& no_such_interface);
|
||||
|
||||
//----
|
||||
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
|
||||
|
||||
@ -1763,6 +1833,10 @@ class MacroAssembler: public Assembler {
|
||||
// stack overflow + shadow pages. Also, clobbers tmp
|
||||
void bang_stack_size(Register size, Register tmp);
|
||||
|
||||
virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr,
|
||||
Register tmp,
|
||||
int offset);
|
||||
|
||||
// Support for serializing memory accesses between threads
|
||||
void serialize_memory(Register thread, Register tmp);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -554,8 +554,8 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
|
||||
__ jcc (Assembler::zero, noLoop);
|
||||
|
||||
// compare first characters
|
||||
__ load_unsigned_word(rcx, Address(rdi, 0));
|
||||
__ load_unsigned_word(rbx, Address(rsi, 0));
|
||||
__ load_unsigned_short(rcx, Address(rdi, 0));
|
||||
__ load_unsigned_short(rbx, Address(rsi, 0));
|
||||
__ subl(rcx, rbx);
|
||||
__ jcc(Assembler::notZero, haveResult);
|
||||
// starting loop
|
||||
@ -574,8 +574,8 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
|
||||
Label loop;
|
||||
__ align(wordSize);
|
||||
__ bind(loop);
|
||||
__ load_unsigned_word(rcx, Address(rdi, rax, Address::times_2, 0));
|
||||
__ load_unsigned_word(rbx, Address(rsi, rax, Address::times_2, 0));
|
||||
__ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0));
|
||||
__ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0));
|
||||
__ subl(rcx, rbx);
|
||||
__ jcc(Assembler::notZero, haveResult);
|
||||
__ increment(rax);
|
||||
|
@ -501,7 +501,7 @@ void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) {
|
||||
LIRItem right(x->y(), this);
|
||||
|
||||
left.load_item();
|
||||
// dont load constants to save register
|
||||
// don't load constants to save register
|
||||
right.load_nonconstant();
|
||||
rlock_result(x);
|
||||
arithmetic_op_long(x->op(), x->operand(), left.result(), right.result(), NULL);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -513,7 +513,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
||||
// compute full expression stack limit
|
||||
|
||||
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
|
||||
__ load_unsigned_word(rdx, size_of_stack); // get size of expression stack in words
|
||||
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
|
||||
__ negptr(rdx); // so we can subtract in next step
|
||||
// Allocate expression stack
|
||||
__ lea(rsp, Address(rsp, rdx, Address::times_ptr));
|
||||
@ -523,7 +523,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
||||
#ifdef _LP64
|
||||
// Make sure stack is properly aligned and sized for the abi
|
||||
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
||||
__ andptr(rsp, -16); // must be 16 byte boundry (see amd64 ABI)
|
||||
__ andptr(rsp, -16); // must be 16 byte boundary (see amd64 ABI)
|
||||
#endif // _LP64
|
||||
|
||||
|
||||
@ -659,7 +659,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
||||
// Always give one monitor to allow us to start interp if sync method.
|
||||
// Any additional monitors need a check when moving the expression stack
|
||||
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
|
||||
__ load_unsigned_word(rax, size_of_stack); // get size of expression stack in words
|
||||
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
|
||||
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor));
|
||||
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
|
||||
|
||||
@ -863,13 +863,13 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
__ bind(notByte);
|
||||
__ cmpl(rdx, stos);
|
||||
__ jcc(Assembler::notEqual, notShort);
|
||||
__ load_signed_word(rax, field_address);
|
||||
__ load_signed_short(rax, field_address);
|
||||
__ jmp(xreturn_path);
|
||||
|
||||
__ bind(notShort);
|
||||
__ cmpl(rdx, ctos);
|
||||
__ jcc(Assembler::notEqual, notChar);
|
||||
__ load_unsigned_word(rax, field_address);
|
||||
__ load_unsigned_short(rax, field_address);
|
||||
__ jmp(xreturn_path);
|
||||
|
||||
__ bind(notChar);
|
||||
@ -937,7 +937,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
const Register locals = rdi;
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// rbx: methodOop
|
||||
// rcx: size of parameters
|
||||
@ -970,7 +970,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
#ifdef _LP64
|
||||
// duplicate the alignment rsp got after setting stack_base
|
||||
__ subptr(rax, frame::arg_reg_save_area_bytes); // windows
|
||||
__ andptr(rax, -16); // must be 16 byte boundry (see amd64 ABI)
|
||||
__ andptr(rax, -16); // must be 16 byte boundary (see amd64 ABI)
|
||||
#endif // _LP64
|
||||
__ cmpptr(rax, rsp);
|
||||
__ jcc(Assembler::equal, L);
|
||||
@ -1062,12 +1062,12 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// allocate space for parameters
|
||||
__ movptr(method, STATE(_method));
|
||||
__ verify_oop(method);
|
||||
__ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset()));
|
||||
__ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset()));
|
||||
__ shll(t, 2);
|
||||
#ifdef _LP64
|
||||
__ subptr(rsp, t);
|
||||
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
||||
__ andptr(rsp, -16); // must be 16 byte boundry (see amd64 ABI)
|
||||
__ andptr(rsp, -16); // must be 16 byte boundary (see amd64 ABI)
|
||||
#else
|
||||
__ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror
|
||||
__ subptr(rsp, t);
|
||||
@ -1659,11 +1659,11 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock));
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// rbx: methodOop
|
||||
// rcx: size of parameters
|
||||
__ load_unsigned_word(rdx, size_of_locals); // get size of locals in words
|
||||
__ load_unsigned_short(rdx, size_of_locals); // get size of locals in words
|
||||
|
||||
__ subptr(rdx, rcx); // rdx = no. of additional locals
|
||||
|
||||
@ -1949,7 +1949,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
__ movptr(rbx, STATE(_result._to_call._callee));
|
||||
|
||||
// callee left args on top of expression stack, remove them
|
||||
__ load_unsigned_word(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset()));
|
||||
__ load_unsigned_short(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset()));
|
||||
__ lea(rsp, Address(rsp, rcx, Address::times_ptr));
|
||||
|
||||
__ movl(rcx, Address(rbx, methodOopDesc::result_index_offset()));
|
||||
@ -2119,7 +2119,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// Make it look like call_stub calling conventions
|
||||
|
||||
// Get (potential) receiver
|
||||
__ load_unsigned_word(rcx, size_of_parameters); // get size of parameters in words
|
||||
__ load_unsigned_short(rcx, size_of_parameters); // get size of parameters in words
|
||||
|
||||
ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation));
|
||||
__ pushptr(recursive.addr()); // make it look good in the debugger
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -192,7 +192,7 @@ void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, i
|
||||
void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
assert(cache != index, "must use different registers");
|
||||
load_unsigned_word(index, Address(rsi, bcp_offset));
|
||||
load_unsigned_short(index, Address(rsi, bcp_offset));
|
||||
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
|
||||
shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index
|
||||
@ -202,7 +202,7 @@ void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Regis
|
||||
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
assert(cache != tmp, "must use different register");
|
||||
load_unsigned_word(tmp, Address(rsi, bcp_offset));
|
||||
load_unsigned_short(tmp, Address(rsi, bcp_offset));
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
|
||||
// convert from field index to ConstantPoolCacheEntry index
|
||||
// and from word offset to byte offset
|
||||
@ -1031,7 +1031,7 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
|
||||
|
||||
// If the mdp is valid, it will point to a DataLayout header which is
|
||||
// consistent with the bcp. The converse is highly probable also.
|
||||
load_unsigned_word(rdx, Address(rcx, in_bytes(DataLayout::bci_offset())));
|
||||
load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset())));
|
||||
addptr(rdx, Address(rbx, methodOopDesc::const_offset()));
|
||||
lea(rdx, Address(rdx, constMethodOopDesc::codes_offset()));
|
||||
cmpptr(rdx, rsi);
|
||||
@ -1512,6 +1512,15 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||
call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), rcx, rbx);
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
get_thread(rcx);
|
||||
get_method(rbx);
|
||||
call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
rcx, rbx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -190,7 +190,7 @@ void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
|
||||
int bcp_offset) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
assert(cache != index, "must use different registers");
|
||||
load_unsigned_word(index, Address(r13, bcp_offset));
|
||||
load_unsigned_short(index, Address(r13, bcp_offset));
|
||||
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
|
||||
// convert from field index to ConstantPoolCacheEntry index
|
||||
@ -203,7 +203,7 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
|
||||
int bcp_offset) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
assert(cache != tmp, "must use different register");
|
||||
load_unsigned_word(tmp, Address(r13, bcp_offset));
|
||||
load_unsigned_short(tmp, Address(r13, bcp_offset));
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
|
||||
// convert from field index to ConstantPoolCacheEntry index
|
||||
// and from word offset to byte offset
|
||||
@ -1063,8 +1063,8 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
|
||||
|
||||
// If the mdp is valid, it will point to a DataLayout header which is
|
||||
// consistent with the bcp. The converse is highly probable also.
|
||||
load_unsigned_word(c_rarg2,
|
||||
Address(c_rarg3, in_bytes(DataLayout::bci_offset())));
|
||||
load_unsigned_short(c_rarg2,
|
||||
Address(c_rarg3, in_bytes(DataLayout::bci_offset())));
|
||||
addptr(c_rarg2, Address(rbx, methodOopDesc::const_offset()));
|
||||
lea(c_rarg2, Address(c_rarg2, constMethodOopDesc::codes_offset()));
|
||||
cmpptr(c_rarg2, r13);
|
||||
@ -1593,6 +1593,14 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
|
||||
r15_thread, c_rarg1);
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
get_method(c_rarg1);
|
||||
call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
r15_thread, c_rarg1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1534,6 +1534,13 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
thread, rax);
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
__ movoop(rax, JNIHandles::make_local(method()));
|
||||
__ call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
thread, rax);
|
||||
}
|
||||
|
||||
// These are register definitions we need for locking/unlocking
|
||||
const Register swap_reg = rax; // Must use rax, for cmpxchg instruction
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1350,7 +1350,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
{
|
||||
Label L;
|
||||
__ mov(rax, rsp);
|
||||
__ andptr(rax, -16); // must be 16 byte boundry (see amd64 ABI)
|
||||
__ andptr(rax, -16); // must be 16 byte boundary (see amd64 ABI)
|
||||
__ cmpptr(rax, rsp);
|
||||
__ jcc(Assembler::equal, L);
|
||||
__ stop("improperly aligned stack");
|
||||
@ -1508,6 +1508,17 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
restore_args(masm, total_c_args, c_arg, out_regs);
|
||||
}
|
||||
|
||||
// RedefineClasses() tracing support for obsolete method entry
|
||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
||||
// protect the args we've loaded
|
||||
save_args(masm, total_c_args, c_arg, out_regs);
|
||||
__ movoop(c_rarg1, JNIHandles::make_local(method()));
|
||||
__ call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||
r15_thread, c_rarg1);
|
||||
restore_args(masm, total_c_args, c_arg, out_regs);
|
||||
}
|
||||
|
||||
// Lock a synchronized method
|
||||
|
||||
// Register definitions used by locking and unlocking
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -662,13 +662,13 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
__ bind(notByte);
|
||||
__ cmpl(rdx, stos);
|
||||
__ jcc(Assembler::notEqual, notShort);
|
||||
__ load_signed_word(rax, field_address);
|
||||
__ load_signed_short(rax, field_address);
|
||||
__ jmp(xreturn_path);
|
||||
|
||||
__ bind(notShort);
|
||||
__ cmpl(rdx, ctos);
|
||||
__ jcc(Assembler::notEqual, notChar);
|
||||
__ load_unsigned_word(rax, field_address);
|
||||
__ load_unsigned_short(rax, field_address);
|
||||
__ jmp(xreturn_path);
|
||||
|
||||
__ bind(notChar);
|
||||
@ -723,7 +723,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
const Address access_flags (rbx, methodOopDesc::access_flags_offset());
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// native calls don't need the stack size check since they have no expression stack
|
||||
// and the arguments are already on the stack and we only add a handful of words
|
||||
@ -838,7 +838,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// allocate space for parameters
|
||||
__ get_method(method);
|
||||
__ verify_oop(method);
|
||||
__ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset()));
|
||||
__ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset()));
|
||||
__ shlptr(t, Interpreter::logStackElementSize());
|
||||
__ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror
|
||||
__ subptr(rsp, t);
|
||||
@ -1155,14 +1155,14 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
const Address access_flags (rbx, methodOopDesc::access_flags_offset());
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// rbx,: methodOop
|
||||
// rcx: size of parameters
|
||||
|
||||
// rsi: sender_sp (could differ from sp+wordSize if we were called via c2i )
|
||||
|
||||
__ load_unsigned_word(rdx, size_of_locals); // get size of locals in words
|
||||
__ load_unsigned_short(rdx, size_of_locals); // get size of locals in words
|
||||
__ subl(rdx, rcx); // rdx = no. of additional locals
|
||||
|
||||
// see if we've got enough room on the stack for locals plus overhead.
|
||||
@ -1558,7 +1558,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||
// Compute size of arguments for saving when returning to deoptimized caller
|
||||
__ get_method(rax);
|
||||
__ verify_oop(rax);
|
||||
__ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset())));
|
||||
__ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset())));
|
||||
__ shlptr(rax, Interpreter::logStackElementSize());
|
||||
__ restore_locals();
|
||||
__ subptr(rdi, rax);
|
||||
|
@ -650,7 +650,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
__ cmpl(rdx, stos);
|
||||
__ jcc(Assembler::notEqual, notShort);
|
||||
// stos
|
||||
__ load_signed_word(rax, field_address);
|
||||
__ load_signed_short(rax, field_address);
|
||||
__ jmp(xreturn_path);
|
||||
|
||||
__ bind(notShort);
|
||||
@ -662,7 +662,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
__ bind(okay);
|
||||
#endif
|
||||
// ctos
|
||||
__ load_unsigned_word(rax, field_address);
|
||||
__ load_unsigned_short(rax, field_address);
|
||||
|
||||
__ bind(xreturn_path);
|
||||
|
||||
@ -702,7 +702,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
const Address access_flags (rbx, methodOopDesc::access_flags_offset());
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// native calls don't need the stack size check since they have no
|
||||
// expression stack and the arguments are already on the stack and
|
||||
@ -819,14 +819,14 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// allocate space for parameters
|
||||
__ get_method(method);
|
||||
__ verify_oop(method);
|
||||
__ load_unsigned_word(t,
|
||||
Address(method,
|
||||
methodOopDesc::size_of_parameters_offset()));
|
||||
__ load_unsigned_short(t,
|
||||
Address(method,
|
||||
methodOopDesc::size_of_parameters_offset()));
|
||||
__ shll(t, Interpreter::logStackElementSize());
|
||||
|
||||
__ subptr(rsp, t);
|
||||
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
||||
__ andptr(rsp, -16); // must be 16 byte boundry (see amd64 ABI)
|
||||
__ andptr(rsp, -16); // must be 16 byte boundary (see amd64 ABI)
|
||||
|
||||
// get signature handler
|
||||
{
|
||||
@ -1165,13 +1165,13 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
const Address access_flags(rbx, methodOopDesc::access_flags_offset());
|
||||
|
||||
// get parameter size (always needed)
|
||||
__ load_unsigned_word(rcx, size_of_parameters);
|
||||
__ load_unsigned_short(rcx, size_of_parameters);
|
||||
|
||||
// rbx: methodOop
|
||||
// rcx: size of parameters
|
||||
// r13: sender_sp (could differ from sp+wordSize if we were called via c2i )
|
||||
|
||||
__ load_unsigned_word(rdx, size_of_locals); // get size of locals in words
|
||||
__ load_unsigned_short(rdx, size_of_locals); // get size of locals in words
|
||||
__ subl(rdx, rcx); // rdx = no. of additional locals
|
||||
|
||||
// YYY
|
||||
@ -1583,7 +1583,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||
// Compute size of arguments for saving when returning to
|
||||
// deoptimized caller
|
||||
__ get_method(rax);
|
||||
__ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc::
|
||||
__ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::
|
||||
size_of_parameters_offset())));
|
||||
__ shll(rax, Interpreter::logStackElementSize());
|
||||
__ restore_locals(); // XXX do we need this?
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -296,7 +296,7 @@ void TemplateTable::bipush() {
|
||||
|
||||
void TemplateTable::sipush() {
|
||||
transition(vtos, itos);
|
||||
__ load_unsigned_word(rax, at_bcp(1));
|
||||
__ load_unsigned_short(rax, at_bcp(1));
|
||||
__ bswapl(rax);
|
||||
__ sarl(rax, 16);
|
||||
}
|
||||
@ -662,7 +662,7 @@ void TemplateTable::caload() {
|
||||
index_check(rdx, rax); // kills rbx,
|
||||
// rax,: index
|
||||
// can do better code for P5 - may want to improve this at some point
|
||||
__ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ mov(rax, rbx);
|
||||
}
|
||||
|
||||
@ -677,7 +677,7 @@ void TemplateTable::fast_icaload() {
|
||||
// rdx: array
|
||||
index_check(rdx, rax);
|
||||
// rax,: index
|
||||
__ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ mov(rax, rbx);
|
||||
}
|
||||
|
||||
@ -687,7 +687,7 @@ void TemplateTable::saload() {
|
||||
index_check(rdx, rax); // kills rbx,
|
||||
// rax,: index
|
||||
// can do better code for P5 - may want to improve this at some point
|
||||
__ load_signed_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
|
||||
__ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
|
||||
__ mov(rax, rbx);
|
||||
}
|
||||
|
||||
@ -1586,7 +1586,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
||||
|
||||
// Handle all the JSR stuff here, then exit.
|
||||
// It's much shorter and cleaner than intermingling with the
|
||||
// non-JSR normal-branch stuff occuring below.
|
||||
// non-JSR normal-branch stuff occurring below.
|
||||
if (is_jsr) {
|
||||
// Pre-load the next target bytecode into EBX
|
||||
__ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0));
|
||||
@ -2310,7 +2310,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
__ cmpl(flags, ctos );
|
||||
__ jcc(Assembler::notEqual, notChar);
|
||||
|
||||
__ load_unsigned_word(rax, lo );
|
||||
__ load_unsigned_short(rax, lo );
|
||||
__ push(ctos);
|
||||
if (!is_static) {
|
||||
patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx);
|
||||
@ -2322,7 +2322,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
__ cmpl(flags, stos );
|
||||
__ jcc(Assembler::notEqual, notShort);
|
||||
|
||||
__ load_signed_word(rax, lo );
|
||||
__ load_signed_short(rax, lo );
|
||||
__ push(stos);
|
||||
if (!is_static) {
|
||||
patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx);
|
||||
@ -2830,8 +2830,8 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||
// access field
|
||||
switch (bytecode()) {
|
||||
case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break;
|
||||
case Bytecodes::_fast_sgetfield: __ load_signed_word(rax, lo ); break;
|
||||
case Bytecodes::_fast_cgetfield: __ load_unsigned_word(rax, lo ); break;
|
||||
case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo ); break;
|
||||
case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo ); break;
|
||||
case Bytecodes::_fast_igetfield: __ movl(rax, lo); break;
|
||||
case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break;
|
||||
case Bytecodes::_fast_fgetfield: __ fld_s(lo); break;
|
||||
@ -3055,35 +3055,44 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
// profile this call
|
||||
__ profile_virtual_call(rdx, rsi, rdi);
|
||||
|
||||
__ mov(rdi, rdx); // Save klassOop in rdi
|
||||
Label no_such_interface, no_such_method;
|
||||
|
||||
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
|
||||
__ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
|
||||
__ lea(rdx, Address(rdx, rsi, Address::times_4, base));
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
__ round_to(rdx, BytesPerLong);
|
||||
}
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
rdx, rax, rbx,
|
||||
// outputs: method, scan temp. reg
|
||||
rbx, rsi,
|
||||
no_such_interface);
|
||||
|
||||
Label entry, search, interface_ok;
|
||||
// rbx,: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a throw_abstract_method_error
|
||||
// interpreter entry point and a conditional jump to it in case of a null
|
||||
// method.
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::zero, no_such_method);
|
||||
|
||||
__ jmpb(entry);
|
||||
__ bind(search);
|
||||
__ addptr(rdx, itableOffsetEntry::size() * wordSize);
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx,: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ bind(entry);
|
||||
// exception handling code follows...
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
|
||||
// Check that the entry is non-null. A null entry means that the receiver
|
||||
// class doesn't implement the interface, and wasn't the same as the
|
||||
// receiver class checked when the interface was resolved.
|
||||
__ push(rdx);
|
||||
__ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ testptr(rdx, rdx);
|
||||
__ jcc(Assembler::notZero, interface_ok);
|
||||
__ bind(no_such_method);
|
||||
// throw exception
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ bind(no_such_interface);
|
||||
// throw exception
|
||||
__ pop(rdx); // pop saved register first.
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
@ -3091,42 +3100,6 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(interface_ok);
|
||||
|
||||
__ pop(rdx);
|
||||
|
||||
__ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ jcc(Assembler::notEqual, search);
|
||||
|
||||
__ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
__ addptr(rdx, rdi); // Add offset to klassOop
|
||||
assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
|
||||
__ movptr(rbx, Address(rdx, rbx, Address::times_ptr));
|
||||
// rbx,: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a throw_abstract_method_error
|
||||
// interpreter entry point and a conditional jump to it in case of a null
|
||||
// method.
|
||||
{ Label L;
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::notZero, L);
|
||||
// throw exception
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(L);
|
||||
}
|
||||
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx,: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
@ -307,7 +307,7 @@ void TemplateTable::bipush() {
|
||||
|
||||
void TemplateTable::sipush() {
|
||||
transition(vtos, itos);
|
||||
__ load_unsigned_word(rax, at_bcp(1));
|
||||
__ load_unsigned_short(rax, at_bcp(1));
|
||||
__ bswapl(rax);
|
||||
__ sarl(rax, 16);
|
||||
}
|
||||
@ -645,10 +645,10 @@ void TemplateTable::caload() {
|
||||
// eax: index
|
||||
// rdx: array
|
||||
index_check(rdx, rax); // kills rbx
|
||||
__ load_unsigned_word(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ load_unsigned_short(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
}
|
||||
|
||||
// iload followed by caload frequent pair
|
||||
@ -663,10 +663,10 @@ void TemplateTable::fast_icaload() {
|
||||
// rdx: array
|
||||
__ pop_ptr(rdx);
|
||||
index_check(rdx, rax); // kills rbx
|
||||
__ load_unsigned_word(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
__ load_unsigned_short(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
}
|
||||
|
||||
void TemplateTable::saload() {
|
||||
@ -675,10 +675,10 @@ void TemplateTable::saload() {
|
||||
// eax: index
|
||||
// rdx: array
|
||||
index_check(rdx, rax); // kills rbx
|
||||
__ load_signed_word(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_SHORT)));
|
||||
__ load_signed_short(rax,
|
||||
Address(rdx, rax,
|
||||
Address::times_2,
|
||||
arrayOopDesc::base_offset_in_bytes(T_SHORT)));
|
||||
}
|
||||
|
||||
void TemplateTable::iload(int n) {
|
||||
@ -1559,7 +1559,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
||||
|
||||
// Handle all the JSR stuff here, then exit.
|
||||
// It's much shorter and cleaner than intermingling with the non-JSR
|
||||
// normal-branch stuff occuring below.
|
||||
// normal-branch stuff occurring below.
|
||||
if (is_jsr) {
|
||||
// Pre-load the next target bytecode into rbx
|
||||
__ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0));
|
||||
@ -2276,7 +2276,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
__ cmpl(flags, ctos);
|
||||
__ jcc(Assembler::notEqual, notChar);
|
||||
// ctos
|
||||
__ load_unsigned_word(rax, field);
|
||||
__ load_unsigned_short(rax, field);
|
||||
__ push(ctos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
@ -2288,7 +2288,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
__ cmpl(flags, stos);
|
||||
__ jcc(Assembler::notEqual, notShort);
|
||||
// stos
|
||||
__ load_signed_word(rax, field);
|
||||
__ load_signed_short(rax, field);
|
||||
__ push(stos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
@ -2751,10 +2751,10 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||
__ movsbl(rax, field);
|
||||
break;
|
||||
case Bytecodes::_fast_sgetfield:
|
||||
__ load_signed_word(rax, field);
|
||||
__ load_signed_short(rax, field);
|
||||
break;
|
||||
case Bytecodes::_fast_cgetfield:
|
||||
__ load_unsigned_word(rax, field);
|
||||
__ load_unsigned_short(rax, field);
|
||||
break;
|
||||
case Bytecodes::_fast_fgetfield:
|
||||
__ movflt(xmm0, field);
|
||||
@ -3010,97 +3010,55 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
// profile this call
|
||||
__ profile_virtual_call(rdx, r13, r14);
|
||||
|
||||
__ mov(r14, rdx); // Save klassOop in r14
|
||||
Label no_such_interface, no_such_method;
|
||||
|
||||
// Compute start of first itableOffsetEntry (which is at the end of
|
||||
// the vtable)
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
// Get length of vtable
|
||||
assert(vtableEntry::size() * wordSize == 8,
|
||||
"adjust the scaling in the code below");
|
||||
__ movl(r13, Address(rdx,
|
||||
instanceKlass::vtable_length_offset() * wordSize));
|
||||
__ lea(rdx, Address(rdx, r13, Address::times_8, base));
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
rdx, rax, rbx,
|
||||
// outputs: method, scan temp. reg
|
||||
rbx, r13,
|
||||
no_such_interface);
|
||||
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
__ round_to(rdx, BytesPerLong);
|
||||
}
|
||||
// rbx,: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a throw_abstract_method_error
|
||||
// interpreter entry point and a conditional jump to it in case of a null
|
||||
// method.
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::zero, no_such_method);
|
||||
|
||||
Label entry, search, interface_ok;
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx,: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ jmpb(entry);
|
||||
__ bind(search);
|
||||
__ addptr(rdx, itableOffsetEntry::size() * wordSize);
|
||||
// exception handling code follows...
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
|
||||
__ bind(entry);
|
||||
|
||||
// Check that the entry is non-null. A null entry means that the
|
||||
// receiver class doesn't implement the interface, and wasn't the
|
||||
// same as the receiver class checked when the interface was
|
||||
// resolved.
|
||||
__ push(rdx);
|
||||
__ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ testptr(rdx, rdx);
|
||||
__ jcc(Assembler::notZero, interface_ok);
|
||||
__ bind(no_such_method);
|
||||
// throw exception
|
||||
__ pop(rdx); // pop saved register first.
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // r13 must be correct for exception handler (was
|
||||
// destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well
|
||||
// (was destroyed)
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // r13 must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ bind(no_such_interface);
|
||||
// throw exception
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // r13 must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(interface_ok);
|
||||
|
||||
__ pop(rdx);
|
||||
|
||||
__ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ jcc(Assembler::notEqual, search);
|
||||
|
||||
__ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
|
||||
__ addptr(rdx, r14); // Add offset to klassOop
|
||||
assert(itableMethodEntry::size() * wordSize == 8,
|
||||
"adjust the scaling in the code below");
|
||||
__ movptr(rbx, Address(rdx, rbx, Address::times_8));
|
||||
// rbx: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a
|
||||
// throw_abstract_method_error interpreter entry point and a
|
||||
// conditional jump to it in case of a null method.
|
||||
{
|
||||
Label L;
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::notZero, L);
|
||||
// throw exception
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // r13 must be correct for exception handler
|
||||
// (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as
|
||||
// well (was destroyed)
|
||||
__ call_VM(noreg,
|
||||
CAST_FROM_FN_PTR(address,
|
||||
InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(L);
|
||||
}
|
||||
|
||||
__ movptr(rcx, Address(rbx, methodOopDesc::interpreter_entry_offset()));
|
||||
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allocation
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* 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,7 +23,7 @@
|
||||
*/
|
||||
|
||||
# include "incls/_precompiled.incl"
|
||||
# include "incls/_vm_version_x86_32.cpp.incl"
|
||||
# include "incls/_vm_version_x86.cpp.incl"
|
||||
|
||||
|
||||
int VM_Version::_cpu;
|
||||
@ -67,8 +67,14 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
|
||||
//
|
||||
// LP64: rcx and rdx are first and second argument registers on windows
|
||||
|
||||
__ push(rbp);
|
||||
#ifdef _LP64
|
||||
__ mov(rbp, c_rarg0); // cpuid_info address
|
||||
#else
|
||||
__ movptr(rbp, Address(rsp, 8)); // cpuid_info address
|
||||
#endif
|
||||
__ push(rbx);
|
||||
__ push(rsi);
|
||||
__ pushf(); // preserve rbx, and flags
|
||||
@ -110,12 +116,12 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
__ jmp(done);
|
||||
|
||||
//
|
||||
// at this point, we have a chip which supports the "cpuid" instruction
|
||||
// At this point, we have a chip which supports the "cpuid" instruction
|
||||
//
|
||||
__ bind(detect_586);
|
||||
__ xorptr(rax, rax);
|
||||
__ xorl(rax, rax);
|
||||
__ cpuid();
|
||||
__ orptr(rax, rax);
|
||||
__ orl(rax, rax);
|
||||
__ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input
|
||||
// value of at least 1, we give up and
|
||||
// assume a 486
|
||||
@ -131,12 +137,12 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
// cpuid(0x4) Deterministic cache params
|
||||
//
|
||||
__ movl(rax, 4); // and rcx already set to 0x0
|
||||
__ xorl(rcx, rcx);
|
||||
__ movl(rax, 4);
|
||||
__ xorl(rcx, rcx); // L1 cache
|
||||
__ cpuid();
|
||||
__ push(rax);
|
||||
__ andl(rax, 0x1f); // Determine if valid cache parameters used
|
||||
__ orl(rax, rax); // rax,[4:0] == 0 indicates invalid cache
|
||||
__ orl(rax, rax); // eax[4:0] == 0 indicates invalid cache
|
||||
__ pop(rax);
|
||||
__ jccb(Assembler::equal, std_cpuid1);
|
||||
|
||||
@ -225,6 +231,7 @@ void VM_Version::get_processor_features() {
|
||||
_stepping = 0;
|
||||
_cpuFeatures = 0;
|
||||
_logical_processors_per_package = 1;
|
||||
|
||||
if (!Use486InstrsOnly) {
|
||||
// Get raw processor info
|
||||
getPsrInfo_stub(&_cpuid_info);
|
||||
@ -232,6 +239,7 @@ void VM_Version::get_processor_features() {
|
||||
_cpu = extended_cpu_family();
|
||||
_model = extended_cpu_model();
|
||||
_stepping = cpu_stepping();
|
||||
|
||||
if (cpu_family() > 4) { // it supports CPUID
|
||||
_cpuFeatures = feature_flags();
|
||||
// Logical processors are only available on P4s and above,
|
||||
@ -239,21 +247,34 @@ void VM_Version::get_processor_features() {
|
||||
_logical_processors_per_package = logical_processor_count();
|
||||
}
|
||||
}
|
||||
|
||||
_supports_cx8 = supports_cmpxchg8();
|
||||
// if the OS doesn't support SSE, we can't use this feature even if the HW does
|
||||
if( !os::supports_sse())
|
||||
|
||||
#ifdef _LP64
|
||||
// OS should support SSE for x64 and hardware should support at least SSE2.
|
||||
if (!VM_Version::supports_sse2()) {
|
||||
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the OS doesn't support SSE, we can't use this feature even if the HW does
|
||||
if (!os::supports_sse())
|
||||
_cpuFeatures &= ~(CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SSSE3|CPU_SSE4A|CPU_SSE4_1|CPU_SSE4_2);
|
||||
|
||||
if (UseSSE < 4) {
|
||||
_cpuFeatures &= ~CPU_SSE4_1;
|
||||
_cpuFeatures &= ~CPU_SSE4_2;
|
||||
}
|
||||
|
||||
if (UseSSE < 3) {
|
||||
_cpuFeatures &= ~CPU_SSE3;
|
||||
_cpuFeatures &= ~CPU_SSSE3;
|
||||
_cpuFeatures &= ~CPU_SSE4A;
|
||||
}
|
||||
|
||||
if (UseSSE < 2)
|
||||
_cpuFeatures &= ~CPU_SSE2;
|
||||
|
||||
if (UseSSE < 1)
|
||||
_cpuFeatures &= ~CPU_SSE;
|
||||
|
||||
@ -418,10 +439,21 @@ void VM_Version::get_processor_features() {
|
||||
|
||||
if( AllocatePrefetchStyle == 2 && is_intel() &&
|
||||
cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
|
||||
#ifdef _LP64
|
||||
AllocatePrefetchDistance = 384;
|
||||
#else
|
||||
AllocatePrefetchDistance = 320;
|
||||
#endif
|
||||
}
|
||||
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
|
||||
|
||||
#ifdef _LP64
|
||||
// Prefetch settings
|
||||
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
|
||||
PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
|
||||
PrefetchFieldsAhead = prefetch_fields_ahead();
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
tty->print_cr("Logical CPUs per core: %u",
|
||||
@ -450,6 +482,16 @@ void VM_Version::get_processor_features() {
|
||||
tty->print_cr(" %d, one line", AllocatePrefetchDistance);
|
||||
}
|
||||
}
|
||||
|
||||
if (PrefetchCopyIntervalInBytes > 0) {
|
||||
tty->print_cr("PrefetchCopyIntervalInBytes %d", PrefetchCopyIntervalInBytes);
|
||||
}
|
||||
if (PrefetchScanIntervalInBytes > 0) {
|
||||
tty->print_cr("PrefetchScanIntervalInBytes %d", PrefetchScanIntervalInBytes);
|
||||
}
|
||||
if (PrefetchFieldsAhead > 0) {
|
||||
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
||||
}
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -112,20 +112,6 @@ public:
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid1Edx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t : 22,
|
||||
mmx_amd : 1,
|
||||
mmx : 1,
|
||||
fxsr : 1,
|
||||
: 4,
|
||||
long_mode : 1,
|
||||
tdnow2 : 1,
|
||||
tdnow : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid1Ecx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
@ -140,6 +126,20 @@ public:
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid1Edx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t : 22,
|
||||
mmx_amd : 1,
|
||||
mmx : 1,
|
||||
fxsr : 1,
|
||||
: 4,
|
||||
long_mode : 1,
|
||||
tdnow2 : 1,
|
||||
tdnow : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid5Ex {
|
||||
uint32_t value;
|
||||
struct {
|
||||
@ -167,17 +167,17 @@ protected:
|
||||
static const char* _features_str;
|
||||
|
||||
enum {
|
||||
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
|
||||
CPU_CMOV = (1 << 1),
|
||||
CPU_FXSR = (1 << 2),
|
||||
CPU_HT = (1 << 3),
|
||||
CPU_MMX = (1 << 4),
|
||||
CPU_3DNOW= (1 << 5),
|
||||
CPU_SSE = (1 << 6),
|
||||
CPU_SSE2 = (1 << 7),
|
||||
CPU_SSE3 = (1 << 8),
|
||||
CPU_SSSE3= (1 << 9),
|
||||
CPU_SSE4A= (1 <<10),
|
||||
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
|
||||
CPU_CMOV = (1 << 1),
|
||||
CPU_FXSR = (1 << 2),
|
||||
CPU_HT = (1 << 3),
|
||||
CPU_MMX = (1 << 4),
|
||||
CPU_3DNOW = (1 << 5), // 3DNow comes from cpuid 0x80000001 (EDX)
|
||||
CPU_SSE = (1 << 6),
|
||||
CPU_SSE2 = (1 << 7),
|
||||
CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
|
||||
CPU_SSSE3 = (1 << 9),
|
||||
CPU_SSE4A = (1 << 10),
|
||||
CPU_SSE4_1 = (1 << 11),
|
||||
CPU_SSE4_2 = (1 << 12)
|
||||
} cpuFeatureFlags;
|
||||
@ -360,7 +360,7 @@ public:
|
||||
result = _cpuid_info.ext_cpuid5_ecx.bits.L1_line_size;
|
||||
}
|
||||
if (result < 32) // not defined ?
|
||||
result = 32; // 32 bytes by default for other x64
|
||||
result = 32; // 32 bytes by default on x86 and other x64
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -395,26 +395,36 @@ public:
|
||||
// This method should be called before allocate_prefetch_style().
|
||||
//
|
||||
// Hardware prefetching (distance/size in bytes):
|
||||
// Pentium 3 - 64 / 32
|
||||
// Pentium 4 - 256 / 128
|
||||
// Athlon - 64 / 32 ????
|
||||
// Opteron - 128 / 64 only when 2 sequential cache lines accessed
|
||||
// Core - 128 / 64
|
||||
//
|
||||
// Software prefetching (distance in bytes / instruction with best score):
|
||||
// Pentium 3 - 128 / prefetchnta
|
||||
// Pentium 4 - 512 / prefetchnta
|
||||
// Athlon - 128 / prefetchnta
|
||||
// Opteron - 256 / prefetchnta
|
||||
// Core - 256 / prefetchnta
|
||||
// It will be used only when AllocatePrefetchStyle > 0
|
||||
|
||||
intx count = AllocatePrefetchDistance;
|
||||
if (count < 0) { // default ?
|
||||
if (is_amd()) { // AMD
|
||||
count = 256; // Opteron
|
||||
} else { // Intel
|
||||
if (cpu_family() == 6) {
|
||||
count = 256;// Pentium M, Core, Core2
|
||||
} else {
|
||||
count = 512;// Pentium 4
|
||||
}
|
||||
if (count < 0) { // default ?
|
||||
if (is_amd()) { // AMD
|
||||
if (supports_sse2())
|
||||
count = 256; // Opteron
|
||||
else
|
||||
count = 128; // Athlon
|
||||
} else { // Intel
|
||||
if (supports_sse2())
|
||||
if (cpu_family() == 6) {
|
||||
count = 256; // Pentium M, Core, Core2
|
||||
} else {
|
||||
count = 512; // Pentium 4
|
||||
}
|
||||
else
|
||||
count = 128; // Pentium 3 (and all other old CPUs)
|
||||
}
|
||||
}
|
||||
return count;
|
@ -1,439 +0,0 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
class VM_Version: public Abstract_VM_Version {
|
||||
public:
|
||||
// cpuid result register layouts. These are all unions of a uint32_t
|
||||
// (in case anyone wants access to the register as a whole) and a bitfield.
|
||||
|
||||
union StdCpuid1Eax {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t stepping : 4,
|
||||
model : 4,
|
||||
family : 4,
|
||||
proc_type : 2,
|
||||
: 2,
|
||||
ext_model : 4,
|
||||
ext_family : 8,
|
||||
: 4;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union StdCpuid1Ebx { // example, unused
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t brand_id : 8,
|
||||
clflush_size : 8,
|
||||
threads_per_cpu : 8,
|
||||
apic_id : 8;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union StdCpuid1Ecx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t sse3 : 1,
|
||||
: 2,
|
||||
monitor : 1,
|
||||
: 1,
|
||||
vmx : 1,
|
||||
: 1,
|
||||
est : 1,
|
||||
: 1,
|
||||
ssse3 : 1,
|
||||
cid : 1,
|
||||
: 2,
|
||||
cmpxchg16: 1,
|
||||
: 4,
|
||||
dca : 1,
|
||||
sse4_1 : 1,
|
||||
sse4_2 : 1,
|
||||
: 11;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union StdCpuid1Edx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t : 4,
|
||||
tsc : 1,
|
||||
: 3,
|
||||
cmpxchg8 : 1,
|
||||
: 6,
|
||||
cmov : 1,
|
||||
: 7,
|
||||
mmx : 1,
|
||||
fxsr : 1,
|
||||
sse : 1,
|
||||
sse2 : 1,
|
||||
: 1,
|
||||
ht : 1,
|
||||
: 3;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union DcpCpuid4Eax {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t cache_type : 5,
|
||||
: 21,
|
||||
cores_per_cpu : 6;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union DcpCpuid4Ebx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t L1_line_size : 12,
|
||||
partitions : 10,
|
||||
associativity : 10;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid1Ecx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t LahfSahf : 1,
|
||||
CmpLegacy : 1,
|
||||
: 4,
|
||||
abm : 1,
|
||||
sse4a : 1,
|
||||
misalignsse : 1,
|
||||
prefetchw : 1,
|
||||
: 22;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid1Edx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t : 22,
|
||||
mmx_amd : 1,
|
||||
mmx : 1,
|
||||
fxsr : 1,
|
||||
: 4,
|
||||
long_mode : 1,
|
||||
tdnow2 : 1,
|
||||
tdnow : 1;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid5Ex {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t L1_line_size : 8,
|
||||
L1_tag_lines : 8,
|
||||
L1_assoc : 8,
|
||||
L1_size : 8;
|
||||
} bits;
|
||||
};
|
||||
|
||||
union ExtCpuid8Ecx {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t cores_per_cpu : 8,
|
||||
: 24;
|
||||
} bits;
|
||||
};
|
||||
|
||||
protected:
|
||||
static int _cpu;
|
||||
static int _model;
|
||||
static int _stepping;
|
||||
static int _cpuFeatures; // features returned by the "cpuid" instruction
|
||||
// 0 if this instruction is not available
|
||||
static const char* _features_str;
|
||||
|
||||
enum {
|
||||
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
|
||||
CPU_CMOV = (1 << 1),
|
||||
CPU_FXSR = (1 << 2),
|
||||
CPU_HT = (1 << 3),
|
||||
CPU_MMX = (1 << 4),
|
||||
CPU_3DNOW= (1 << 5), // 3DNow comes from cpuid 0x80000001 (EDX)
|
||||
CPU_SSE = (1 << 6),
|
||||
CPU_SSE2 = (1 << 7),
|
||||
CPU_SSE3 = (1 << 8), // sse3 comes from cpuid 1 (ECX)
|
||||
CPU_SSSE3= (1 << 9),
|
||||
CPU_SSE4A= (1 <<10),
|
||||
CPU_SSE4_1 = (1 << 11),
|
||||
CPU_SSE4_2 = (1 << 12)
|
||||
} cpuFeatureFlags;
|
||||
|
||||
// cpuid information block. All info derived from executing cpuid with
|
||||
// various function numbers is stored here. Intel and AMD info is
|
||||
// merged in this block: accessor methods disentangle it.
|
||||
//
|
||||
// The info block is laid out in subblocks of 4 dwords corresponding to
|
||||
// rax, rbx, rcx and rdx, whether or not they contain anything useful.
|
||||
struct CpuidInfo {
|
||||
// cpuid function 0
|
||||
uint32_t std_max_function;
|
||||
uint32_t std_vendor_name_0;
|
||||
uint32_t std_vendor_name_1;
|
||||
uint32_t std_vendor_name_2;
|
||||
|
||||
// cpuid function 1
|
||||
StdCpuid1Eax std_cpuid1_rax;
|
||||
StdCpuid1Ebx std_cpuid1_rbx;
|
||||
StdCpuid1Ecx std_cpuid1_rcx;
|
||||
StdCpuid1Edx std_cpuid1_rdx;
|
||||
|
||||
// cpuid function 4 (deterministic cache parameters)
|
||||
DcpCpuid4Eax dcp_cpuid4_rax;
|
||||
DcpCpuid4Ebx dcp_cpuid4_rbx;
|
||||
uint32_t dcp_cpuid4_rcx; // unused currently
|
||||
uint32_t dcp_cpuid4_rdx; // unused currently
|
||||
|
||||
// cpuid function 0x80000000 // example, unused
|
||||
uint32_t ext_max_function;
|
||||
uint32_t ext_vendor_name_0;
|
||||
uint32_t ext_vendor_name_1;
|
||||
uint32_t ext_vendor_name_2;
|
||||
|
||||
// cpuid function 0x80000001
|
||||
uint32_t ext_cpuid1_rax; // reserved
|
||||
uint32_t ext_cpuid1_rbx; // reserved
|
||||
ExtCpuid1Ecx ext_cpuid1_rcx;
|
||||
ExtCpuid1Edx ext_cpuid1_rdx;
|
||||
|
||||
// cpuid functions 0x80000002 thru 0x80000004: example, unused
|
||||
uint32_t proc_name_0, proc_name_1, proc_name_2, proc_name_3;
|
||||
uint32_t proc_name_4, proc_name_5, proc_name_6, proc_name_7;
|
||||
uint32_t proc_name_8, proc_name_9, proc_name_10,proc_name_11;
|
||||
|
||||
// cpuid function 0x80000005 //AMD L1, Intel reserved
|
||||
uint32_t ext_cpuid5_rax; // unused currently
|
||||
uint32_t ext_cpuid5_rbx; // reserved
|
||||
ExtCpuid5Ex ext_cpuid5_rcx; // L1 data cache info (AMD)
|
||||
ExtCpuid5Ex ext_cpuid5_rdx; // L1 instruction cache info (AMD)
|
||||
|
||||
// cpuid function 0x80000008
|
||||
uint32_t ext_cpuid8_rax; // unused currently
|
||||
uint32_t ext_cpuid8_rbx; // reserved
|
||||
ExtCpuid8Ecx ext_cpuid8_rcx;
|
||||
uint32_t ext_cpuid8_rdx; // reserved
|
||||
};
|
||||
|
||||
// The actual cpuid info block
|
||||
static CpuidInfo _cpuid_info;
|
||||
|
||||
// Extractors and predicates
|
||||
static uint32_t extended_cpu_family() {
|
||||
uint32_t result = _cpuid_info.std_cpuid1_rax.bits.family;
|
||||
result += _cpuid_info.std_cpuid1_rax.bits.ext_family;
|
||||
return result;
|
||||
}
|
||||
static uint32_t extended_cpu_model() {
|
||||
uint32_t result = _cpuid_info.std_cpuid1_rax.bits.model;
|
||||
result |= _cpuid_info.std_cpuid1_rax.bits.ext_model << 4;
|
||||
return result;
|
||||
}
|
||||
static uint32_t cpu_stepping() {
|
||||
uint32_t result = _cpuid_info.std_cpuid1_rax.bits.stepping;
|
||||
return result;
|
||||
}
|
||||
static uint logical_processor_count() {
|
||||
uint result = threads_per_core();
|
||||
return result;
|
||||
}
|
||||
static uint32_t feature_flags() {
|
||||
uint32_t result = 0;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.cmpxchg8 != 0)
|
||||
result |= CPU_CX8;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.cmov != 0)
|
||||
result |= CPU_CMOV;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.fxsr != 0 || is_amd() &&
|
||||
_cpuid_info.ext_cpuid1_rdx.bits.fxsr != 0)
|
||||
result |= CPU_FXSR;
|
||||
// HT flag is set for multi-core processors also.
|
||||
if (threads_per_core() > 1)
|
||||
result |= CPU_HT;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.mmx != 0 || is_amd() &&
|
||||
_cpuid_info.ext_cpuid1_rdx.bits.mmx != 0)
|
||||
result |= CPU_MMX;
|
||||
if (is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.tdnow != 0)
|
||||
result |= CPU_3DNOW;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.sse != 0)
|
||||
result |= CPU_SSE;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.sse2 != 0)
|
||||
result |= CPU_SSE2;
|
||||
if (_cpuid_info.std_cpuid1_rcx.bits.sse3 != 0)
|
||||
result |= CPU_SSE3;
|
||||
if (_cpuid_info.std_cpuid1_rcx.bits.ssse3 != 0)
|
||||
result |= CPU_SSSE3;
|
||||
if (is_amd() && _cpuid_info.ext_cpuid1_rcx.bits.sse4a != 0)
|
||||
result |= CPU_SSE4A;
|
||||
if (_cpuid_info.std_cpuid1_rcx.bits.sse4_1 != 0)
|
||||
result |= CPU_SSE4_1;
|
||||
if (_cpuid_info.std_cpuid1_rcx.bits.sse4_2 != 0)
|
||||
result |= CPU_SSE4_2;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void get_processor_features();
|
||||
|
||||
public:
|
||||
// Offsets for cpuid asm stub
|
||||
static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); }
|
||||
static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_rax); }
|
||||
static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_rax); }
|
||||
static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_rax); }
|
||||
static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_rax); }
|
||||
static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_rax); }
|
||||
|
||||
// Initialization
|
||||
static void initialize();
|
||||
|
||||
// Asserts
|
||||
static void assert_is_initialized() {
|
||||
assert(_cpuid_info.std_cpuid1_rax.bits.family != 0, "VM_Version not initialized");
|
||||
}
|
||||
|
||||
//
|
||||
// Processor family:
|
||||
// 3 - 386
|
||||
// 4 - 486
|
||||
// 5 - Pentium
|
||||
// 6 - PentiumPro, Pentium II, Celeron, Xeon, Pentium III, Athlon,
|
||||
// Pentium M, Core Solo, Core Duo, Core2 Duo
|
||||
// family 6 model: 9, 13, 14, 15
|
||||
// 0x0f - Pentium 4, Opteron
|
||||
//
|
||||
// Note: The cpu family should be used to select between
|
||||
// instruction sequences which are valid on all Intel
|
||||
// processors. Use the feature test functions below to
|
||||
// determine whether a particular instruction is supported.
|
||||
//
|
||||
static int cpu_family() { return _cpu;}
|
||||
static bool is_P6() { return cpu_family() >= 6; }
|
||||
|
||||
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
|
||||
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
|
||||
|
||||
static uint cores_per_cpu() {
|
||||
uint result = 1;
|
||||
if (is_intel()) {
|
||||
result = (_cpuid_info.dcp_cpuid4_rax.bits.cores_per_cpu + 1);
|
||||
} else if (is_amd()) {
|
||||
result = (_cpuid_info.ext_cpuid8_rcx.bits.cores_per_cpu + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint threads_per_core() {
|
||||
uint result = 1;
|
||||
if (_cpuid_info.std_cpuid1_rdx.bits.ht != 0) {
|
||||
result = _cpuid_info.std_cpuid1_rbx.bits.threads_per_cpu /
|
||||
cores_per_cpu();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static intx L1_data_cache_line_size() {
|
||||
intx result = 0;
|
||||
if (is_intel()) {
|
||||
result = (_cpuid_info.dcp_cpuid4_rbx.bits.L1_line_size + 1);
|
||||
} else if (is_amd()) {
|
||||
result = _cpuid_info.ext_cpuid5_rcx.bits.L1_line_size;
|
||||
}
|
||||
if (result < 32) // not defined ?
|
||||
result = 32; // 32 bytes by default on x86
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Feature identification
|
||||
//
|
||||
static bool supports_cpuid() { return _cpuFeatures != 0; }
|
||||
static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; }
|
||||
static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; }
|
||||
static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; }
|
||||
static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; }
|
||||
static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; }
|
||||
static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; }
|
||||
static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; }
|
||||
static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; }
|
||||
static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; }
|
||||
static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; }
|
||||
static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
|
||||
//
|
||||
// AMD features
|
||||
//
|
||||
static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; }
|
||||
static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.mmx_amd != 0; }
|
||||
static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.tdnow2 != 0; }
|
||||
static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; }
|
||||
|
||||
static bool supports_compare_and_exchange() { return true; }
|
||||
|
||||
static const char* cpu_features() { return _features_str; }
|
||||
|
||||
static intx allocate_prefetch_distance() {
|
||||
// This method should be called before allocate_prefetch_style().
|
||||
//
|
||||
// Hardware prefetching (distance/size in bytes):
|
||||
// Pentium 3 - 64 / 32
|
||||
// Pentium 4 - 256 / 128
|
||||
// Athlon - 64 / 32 ????
|
||||
// Opteron - 128 / 64 only when 2 sequential cache lines accessed
|
||||
// Core - 128 / 64
|
||||
//
|
||||
// Software prefetching (distance in bytes / instruction with best score):
|
||||
// Pentium 3 - 128 / prefetchnta
|
||||
// Pentium 4 - 512 / prefetchnta
|
||||
// Athlon - 128 / prefetchnta
|
||||
// Opteron - 256 / prefetchnta
|
||||
// Core - 256 / prefetchnta
|
||||
// It will be used only when AllocatePrefetchStyle > 0
|
||||
|
||||
intx count = AllocatePrefetchDistance;
|
||||
if (count < 0) { // default ?
|
||||
if (is_amd()) { // AMD
|
||||
if (supports_sse2())
|
||||
count = 256; // Opteron
|
||||
else
|
||||
count = 128; // Athlon
|
||||
} else { // Intel
|
||||
if (supports_sse2())
|
||||
if (cpu_family() == 6) {
|
||||
count = 256; // Pentium M, Core, Core2
|
||||
} else {
|
||||
count = 512; // Pentium 4
|
||||
}
|
||||
else
|
||||
count = 128; // Pentium 3 (and all other old CPUs)
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static intx allocate_prefetch_style() {
|
||||
assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive");
|
||||
// Return 0 if AllocatePrefetchDistance was not defined or
|
||||
// prefetch instruction is not supported.
|
||||
return (AllocatePrefetchDistance > 0 &&
|
||||
(supports_3dnow() || supports_sse())) ? AllocatePrefetchStyle : 0;
|
||||
}
|
||||
};
|
@ -1,419 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
# include "incls/_precompiled.incl"
|
||||
# include "incls/_vm_version_x86_64.cpp.incl"
|
||||
|
||||
int VM_Version::_cpu;
|
||||
int VM_Version::_model;
|
||||
int VM_Version::_stepping;
|
||||
int VM_Version::_cpuFeatures;
|
||||
const char* VM_Version::_features_str = "";
|
||||
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
|
||||
|
||||
static BufferBlob* stub_blob;
|
||||
static const int stub_size = 300;
|
||||
|
||||
extern "C" {
|
||||
typedef void (*getPsrInfo_stub_t)(void*);
|
||||
}
|
||||
static getPsrInfo_stub_t getPsrInfo_stub = NULL;
|
||||
|
||||
|
||||
class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
public:
|
||||
|
||||
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
|
||||
|
||||
address generate_getPsrInfo() {
|
||||
|
||||
Label std_cpuid1, ext_cpuid1, ext_cpuid5, done;
|
||||
|
||||
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
|
||||
# define __ _masm->
|
||||
|
||||
address start = __ pc();
|
||||
|
||||
//
|
||||
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
|
||||
//
|
||||
// rcx and rdx are first and second argument registers on windows
|
||||
|
||||
__ push(rbp);
|
||||
__ mov(rbp, c_rarg0); // cpuid_info address
|
||||
__ push(rbx);
|
||||
__ push(rsi);
|
||||
|
||||
//
|
||||
// we have a chip which supports the "cpuid" instruction
|
||||
//
|
||||
__ xorl(rax, rax);
|
||||
__ cpuid();
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
__ cmpl(rax, 3); // Is cpuid(0x4) supported?
|
||||
__ jccb(Assembler::belowEqual, std_cpuid1);
|
||||
|
||||
//
|
||||
// cpuid(0x4) Deterministic cache params
|
||||
//
|
||||
__ movl(rax, 4);
|
||||
__ xorl(rcx, rcx); // L1 cache
|
||||
__ cpuid();
|
||||
__ push(rax);
|
||||
__ andl(rax, 0x1f); // Determine if valid cache parameters used
|
||||
__ orl(rax, rax); // eax[4:0] == 0 indicates invalid cache
|
||||
__ pop(rax);
|
||||
__ jccb(Assembler::equal, std_cpuid1);
|
||||
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::dcp_cpuid4_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
//
|
||||
// Standard cpuid(0x1)
|
||||
//
|
||||
__ bind(std_cpuid1);
|
||||
__ movl(rax, 1);
|
||||
__ cpuid();
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
__ movl(rax, 0x80000000);
|
||||
__ cpuid();
|
||||
__ cmpl(rax, 0x80000000); // Is cpuid(0x80000001) supported?
|
||||
__ jcc(Assembler::belowEqual, done);
|
||||
__ cmpl(rax, 0x80000004); // Is cpuid(0x80000005) supported?
|
||||
__ jccb(Assembler::belowEqual, ext_cpuid1);
|
||||
__ cmpl(rax, 0x80000007); // Is cpuid(0x80000008) supported?
|
||||
__ jccb(Assembler::belowEqual, ext_cpuid5);
|
||||
//
|
||||
// Extended cpuid(0x80000008)
|
||||
//
|
||||
__ movl(rax, 0x80000008);
|
||||
__ cpuid();
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid8_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
//
|
||||
// Extended cpuid(0x80000005)
|
||||
//
|
||||
__ bind(ext_cpuid5);
|
||||
__ movl(rax, 0x80000005);
|
||||
__ cpuid();
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid5_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
//
|
||||
// Extended cpuid(0x80000001)
|
||||
//
|
||||
__ bind(ext_cpuid1);
|
||||
__ movl(rax, 0x80000001);
|
||||
__ cpuid();
|
||||
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid1_offset())));
|
||||
__ movl(Address(rsi, 0), rax);
|
||||
__ movl(Address(rsi, 4), rbx);
|
||||
__ movl(Address(rsi, 8), rcx);
|
||||
__ movl(Address(rsi,12), rdx);
|
||||
|
||||
//
|
||||
// return
|
||||
//
|
||||
__ bind(done);
|
||||
__ pop(rsi);
|
||||
__ pop(rbx);
|
||||
__ pop(rbp);
|
||||
__ ret(0);
|
||||
|
||||
# undef __
|
||||
|
||||
return start;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void VM_Version::get_processor_features() {
|
||||
|
||||
_logical_processors_per_package = 1;
|
||||
// Get raw processor info
|
||||
getPsrInfo_stub(&_cpuid_info);
|
||||
assert_is_initialized();
|
||||
_cpu = extended_cpu_family();
|
||||
_model = extended_cpu_model();
|
||||
_stepping = cpu_stepping();
|
||||
_cpuFeatures = feature_flags();
|
||||
// Logical processors are only available on P4s and above,
|
||||
// and only if hyperthreading is available.
|
||||
_logical_processors_per_package = logical_processor_count();
|
||||
_supports_cx8 = supports_cmpxchg8();
|
||||
// OS should support SSE for x64 and hardware should support at least SSE2.
|
||||
if (!VM_Version::supports_sse2()) {
|
||||
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
|
||||
}
|
||||
if (UseSSE < 4) {
|
||||
_cpuFeatures &= ~CPU_SSE4_1;
|
||||
_cpuFeatures &= ~CPU_SSE4_2;
|
||||
}
|
||||
if (UseSSE < 3) {
|
||||
_cpuFeatures &= ~CPU_SSE3;
|
||||
_cpuFeatures &= ~CPU_SSSE3;
|
||||
_cpuFeatures &= ~CPU_SSE4A;
|
||||
}
|
||||
if (UseSSE < 2)
|
||||
_cpuFeatures &= ~CPU_SSE2;
|
||||
if (UseSSE < 1)
|
||||
_cpuFeatures &= ~CPU_SSE;
|
||||
|
||||
if (logical_processors_per_package() == 1) {
|
||||
// HT processor could be installed on a system which doesn't support HT.
|
||||
_cpuFeatures &= ~CPU_HT;
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
cores_per_cpu(), threads_per_core(),
|
||||
cpu_family(), _model, _stepping,
|
||||
(supports_cmov() ? ", cmov" : ""),
|
||||
(supports_cmpxchg8() ? ", cx8" : ""),
|
||||
(supports_fxsr() ? ", fxsr" : ""),
|
||||
(supports_mmx() ? ", mmx" : ""),
|
||||
(supports_sse() ? ", sse" : ""),
|
||||
(supports_sse2() ? ", sse2" : ""),
|
||||
(supports_sse3() ? ", sse3" : ""),
|
||||
(supports_ssse3()? ", ssse3": ""),
|
||||
(supports_sse4_1() ? ", sse4.1" : ""),
|
||||
(supports_sse4_2() ? ", sse4.2" : ""),
|
||||
(supports_mmx_ext() ? ", mmxext" : ""),
|
||||
(supports_3dnow() ? ", 3dnow" : ""),
|
||||
(supports_3dnow2() ? ", 3dnowext" : ""),
|
||||
(supports_sse4a() ? ", sse4a": ""),
|
||||
(supports_ht() ? ", ht": ""));
|
||||
_features_str = strdup(buf);
|
||||
|
||||
// UseSSE is set to the smaller of what hardware supports and what
|
||||
// the command line requires. I.e., you cannot set UseSSE to 2 on
|
||||
// older Pentiums which do not support it.
|
||||
if( UseSSE > 4 ) UseSSE=4;
|
||||
if( UseSSE < 0 ) UseSSE=0;
|
||||
if( !supports_sse4_1() ) // Drop to 3 if no SSE4 support
|
||||
UseSSE = MIN2((intx)3,UseSSE);
|
||||
if( !supports_sse3() ) // Drop to 2 if no SSE3 support
|
||||
UseSSE = MIN2((intx)2,UseSSE);
|
||||
if( !supports_sse2() ) // Drop to 1 if no SSE2 support
|
||||
UseSSE = MIN2((intx)1,UseSSE);
|
||||
if( !supports_sse () ) // Drop to 0 if no SSE support
|
||||
UseSSE = 0;
|
||||
|
||||
// On new cpus instructions which update whole XMM register should be used
|
||||
// to prevent partial register stall due to dependencies on high half.
|
||||
//
|
||||
// UseXmmLoadAndClearUpper == true --> movsd(xmm, mem)
|
||||
// UseXmmLoadAndClearUpper == false --> movlpd(xmm, mem)
|
||||
// UseXmmRegToRegMoveAll == true --> movaps(xmm, xmm), movapd(xmm, xmm).
|
||||
// UseXmmRegToRegMoveAll == false --> movss(xmm, xmm), movsd(xmm, xmm).
|
||||
|
||||
if( is_amd() ) { // AMD cpus specific settings
|
||||
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
|
||||
// Use it on all AMD cpus starting from Opteron (don't need
|
||||
// a cpu check since only Opteron and new cpus support 64-bits mode).
|
||||
UseAddressNop = true;
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
||||
if( supports_sse4a() ) {
|
||||
UseXmmLoadAndClearUpper = true; // use movsd only on '10h' Opteron
|
||||
} else {
|
||||
UseXmmLoadAndClearUpper = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
||||
if( supports_sse4a() ) {
|
||||
UseXmmRegToRegMoveAll = true; // use movaps, movapd only on '10h'
|
||||
} else {
|
||||
UseXmmRegToRegMoveAll = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
|
||||
if( supports_sse4a() ) {
|
||||
UseXmmI2F = true;
|
||||
} else {
|
||||
UseXmmI2F = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
|
||||
if( supports_sse4a() ) {
|
||||
UseXmmI2D = true;
|
||||
} else {
|
||||
UseXmmI2D = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( is_intel() ) { // Intel cpus specific settings
|
||||
if( FLAG_IS_DEFAULT(UseStoreImmI16) ) {
|
||||
UseStoreImmI16 = false; // don't use it on Intel cpus
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
|
||||
// Use it on all Intel cpus starting from PentiumPro
|
||||
// (don't need a cpu check since only new cpus support 64-bits mode).
|
||||
UseAddressNop = true;
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
||||
UseXmmLoadAndClearUpper = true; // use movsd on all Intel cpus
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
||||
if( supports_sse3() ) {
|
||||
UseXmmRegToRegMoveAll = true; // use movaps, movapd on new Intel cpus
|
||||
} else {
|
||||
UseXmmRegToRegMoveAll = false;
|
||||
}
|
||||
}
|
||||
if( cpu_family() == 6 && supports_sse3() ) { // New Intel cpus
|
||||
#ifdef COMPILER2
|
||||
if( FLAG_IS_DEFAULT(MaxLoopPad) ) {
|
||||
// For new Intel cpus do the next optimization:
|
||||
// don't align the beginning of a loop if there are enough instructions
|
||||
// left (NumberOfLoopInstrToAlign defined in c2_globals.hpp)
|
||||
// in current fetch line (OptoLoopAlignment) or the padding
|
||||
// is big (> MaxLoopPad).
|
||||
// Set MaxLoopPad to 11 for new Intel cpus to reduce number of
|
||||
// generated NOP instructions. 11 is the largest size of one
|
||||
// address NOP instruction '0F 1F' (see Assembler::nop(i)).
|
||||
MaxLoopPad = 11;
|
||||
}
|
||||
#endif // COMPILER2
|
||||
if( FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) {
|
||||
UseXMMForArrayCopy = true; // use SSE2 movq on new Intel cpus
|
||||
}
|
||||
if( supports_sse4_2() && supports_ht() ) { // Newest Intel cpus
|
||||
if( FLAG_IS_DEFAULT(UseUnalignedLoadStores) && UseXMMForArrayCopy ) {
|
||||
UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(0 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value");
|
||||
assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value");
|
||||
|
||||
// set valid Prefetch instruction
|
||||
if( ReadPrefetchInstr < 0 ) ReadPrefetchInstr = 0;
|
||||
if( ReadPrefetchInstr > 3 ) ReadPrefetchInstr = 3;
|
||||
if( ReadPrefetchInstr == 3 && !supports_3dnow() ) ReadPrefetchInstr = 0;
|
||||
|
||||
if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
|
||||
if( AllocatePrefetchInstr > 3 ) AllocatePrefetchInstr = 3;
|
||||
if( AllocatePrefetchInstr == 3 && !supports_3dnow() ) AllocatePrefetchInstr=0;
|
||||
|
||||
// Allocation prefetch settings
|
||||
intx cache_line_size = L1_data_cache_line_size();
|
||||
if( cache_line_size > AllocatePrefetchStepSize )
|
||||
AllocatePrefetchStepSize = cache_line_size;
|
||||
if( FLAG_IS_DEFAULT(AllocatePrefetchLines) )
|
||||
AllocatePrefetchLines = 3; // Optimistic value
|
||||
assert(AllocatePrefetchLines > 0, "invalid value");
|
||||
if( AllocatePrefetchLines < 1 ) // set valid value in product VM
|
||||
AllocatePrefetchLines = 1; // Conservative value
|
||||
|
||||
AllocatePrefetchDistance = allocate_prefetch_distance();
|
||||
AllocatePrefetchStyle = allocate_prefetch_style();
|
||||
|
||||
if( AllocatePrefetchStyle == 2 && is_intel() &&
|
||||
cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
|
||||
AllocatePrefetchDistance = 384;
|
||||
}
|
||||
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
|
||||
|
||||
// Prefetch settings
|
||||
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
|
||||
PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
|
||||
PrefetchFieldsAhead = prefetch_fields_ahead();
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
tty->print_cr("Logical CPUs per core: %u",
|
||||
logical_processors_per_package());
|
||||
tty->print_cr("UseSSE=%d",UseSSE);
|
||||
tty->print("Allocation: ");
|
||||
if (AllocatePrefetchStyle <= 0) {
|
||||
tty->print_cr("no prefetching");
|
||||
} else {
|
||||
if (AllocatePrefetchInstr == 0) {
|
||||
tty->print("PREFETCHNTA");
|
||||
} else if (AllocatePrefetchInstr == 1) {
|
||||
tty->print("PREFETCHT0");
|
||||
} else if (AllocatePrefetchInstr == 2) {
|
||||
tty->print("PREFETCHT2");
|
||||
} else if (AllocatePrefetchInstr == 3) {
|
||||
tty->print("PREFETCHW");
|
||||
}
|
||||
if (AllocatePrefetchLines > 1) {
|
||||
tty->print_cr(" %d, %d lines with step %d bytes", AllocatePrefetchDistance, AllocatePrefetchLines, AllocatePrefetchStepSize);
|
||||
} else {
|
||||
tty->print_cr(" %d, one line", AllocatePrefetchDistance);
|
||||
}
|
||||
}
|
||||
if (PrefetchCopyIntervalInBytes > 0) {
|
||||
tty->print_cr("PrefetchCopyIntervalInBytes %d", PrefetchCopyIntervalInBytes);
|
||||
}
|
||||
if (PrefetchScanIntervalInBytes > 0) {
|
||||
tty->print_cr("PrefetchScanIntervalInBytes %d", PrefetchScanIntervalInBytes);
|
||||
}
|
||||
if (PrefetchFieldsAhead > 0) {
|
||||
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
||||
}
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
}
|
||||
|
||||
void VM_Version::initialize() {
|
||||
ResourceMark rm;
|
||||
// Making this stub must be FIRST use of assembler
|
||||
|
||||
stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
|
||||
if (stub_blob == NULL) {
|
||||
vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
|
||||
}
|
||||
CodeBuffer c(stub_blob->instructions_begin(),
|
||||
stub_blob->instructions_size());
|
||||
VM_Version_StubGenerator g(&c);
|
||||
getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
|
||||
g.generate_getPsrInfo());
|
||||
|
||||
get_processor_features();
|
||||
}
|
@ -34,10 +34,16 @@
|
||||
extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
|
||||
#endif
|
||||
|
||||
// used by compiler only; may use only caller saved registers rax, rbx, rcx.
|
||||
// rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved.
|
||||
// Leave receiver in rcx; required behavior when +OptoArgsInRegisters
|
||||
// is modifed to put first oop in rcx.
|
||||
// These stubs are used by the compiler only.
|
||||
// Argument registers, which must be preserved:
|
||||
// rcx - receiver (always first argument)
|
||||
// rdx - second argument (if any)
|
||||
// Other registers that might be usable:
|
||||
// rax - inline cache register (is interface for itable stub)
|
||||
// rbx - method (used when calling out to interpreter)
|
||||
// Available now, but may become callee-save at some point:
|
||||
// rsi, rdi
|
||||
// Note that rax and rdx are also used for return values.
|
||||
//
|
||||
VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
const int i486_code_length = VtableStub::pd_code_size_limit(true);
|
||||
@ -94,16 +100,25 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
__ jmp( Address(method, methodOopDesc::from_compiled_offset()));
|
||||
|
||||
masm->flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
vtable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
// Note well: pd_code_size_limit is the absolute minimum we can get away with. If you
|
||||
// add code here, bump the code stub size returned by pd_code_size_limit!
|
||||
const int i486_code_length = VtableStub::pd_code_size_limit(false);
|
||||
VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index);
|
||||
VtableStub* s = new(i486_code_length) VtableStub(false, itable_index);
|
||||
ResourceMark rm;
|
||||
CodeBuffer cb(s->entry_point(), i486_code_length);
|
||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||
@ -123,50 +138,19 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
|
||||
// get receiver klass (also an implicit null-check)
|
||||
address npe_addr = __ pc();
|
||||
__ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes()));
|
||||
__ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes()));
|
||||
|
||||
__ mov(rsi, rbx); // Save klass in free register
|
||||
// Most registers are in use, so save a few
|
||||
__ push(rdx);
|
||||
// compute itable entry offset (in words)
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below");
|
||||
__ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
|
||||
__ lea(rbx, Address(rbx, rdx, Address::times_ptr, base));
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
__ round_to(rbx, BytesPerLong);
|
||||
}
|
||||
|
||||
Label hit, next, entry, throw_icce;
|
||||
|
||||
__ jmpb(entry);
|
||||
|
||||
__ bind(next);
|
||||
__ addptr(rbx, itableOffsetEntry::size() * wordSize);
|
||||
|
||||
__ bind(entry);
|
||||
|
||||
// If the entry is NULL then we've reached the end of the table
|
||||
// without finding the expected interface, so throw an exception
|
||||
__ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ testptr(rdx, rdx);
|
||||
__ jcc(Assembler::zero, throw_icce);
|
||||
__ cmpptr(rax, rdx);
|
||||
__ jcc(Assembler::notEqual, next);
|
||||
|
||||
// We found a hit, move offset into rbx,
|
||||
__ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
|
||||
// Compute itableMethodEntry.
|
||||
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
|
||||
// Most registers are in use; we'll use rax, rbx, rsi, rdi
|
||||
// (If we need to make rsi, rdi callee-save, do a push/pop here.)
|
||||
const Register method = rbx;
|
||||
Label throw_icce;
|
||||
|
||||
// Get methodOop and entrypoint for compiler
|
||||
const Register method = rbx;
|
||||
__ movptr(method, Address(rsi, rdx, Address::times_1, method_offset));
|
||||
|
||||
// Restore saved register, before possible trap.
|
||||
__ pop(rdx);
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
rsi, rax, itable_index,
|
||||
// outputs: method, scan temp. reg
|
||||
method, rdi,
|
||||
throw_icce);
|
||||
|
||||
// method (rbx): methodOop
|
||||
// rcx: receiver
|
||||
@ -187,12 +171,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
__ jmp(Address(method, methodOopDesc::from_compiled_offset()));
|
||||
|
||||
__ bind(throw_icce);
|
||||
// Restore saved register
|
||||
__ pop(rdx);
|
||||
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
||||
|
||||
masm->flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
itable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
@ -207,7 +194,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||
return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
|
||||
} else {
|
||||
// Itable stub size
|
||||
return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
|
||||
return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,17 +98,26 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
__ jmp( Address(rbx, methodOopDesc::from_compiled_offset()));
|
||||
|
||||
__ flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
vtable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
// Note well: pd_code_size_limit is the absolute minimum we can get
|
||||
// away with. If you add code here, bump the code stub size
|
||||
// returned by pd_code_size_limit!
|
||||
const int amd64_code_length = VtableStub::pd_code_size_limit(false);
|
||||
VtableStub* s = new(amd64_code_length) VtableStub(false, vtable_index);
|
||||
VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index);
|
||||
ResourceMark rm;
|
||||
CodeBuffer cb(s->entry_point(), amd64_code_length);
|
||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||
@ -131,68 +140,28 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
// get receiver klass (also an implicit null-check)
|
||||
address npe_addr = __ pc();
|
||||
|
||||
__ load_klass(rbx, j_rarg0);
|
||||
// Most registers are in use; we'll use rax, rbx, r10, r11
|
||||
// (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them)
|
||||
__ load_klass(r10, j_rarg0);
|
||||
|
||||
// If we take a trap while this arg is on the stack we will not
|
||||
// be able to walk the stack properly. This is not an issue except
|
||||
// when there are mistakes in this assembly code that could generate
|
||||
// a spurious fault. Ask me how I know...
|
||||
|
||||
__ push(j_rarg1); // Most registers are in use, so save one
|
||||
|
||||
// compute itable entry offset (in words)
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
assert(vtableEntry::size() * wordSize == 8,
|
||||
"adjust the scaling in the code below");
|
||||
// Get length of vtable
|
||||
__ movl(j_rarg1,
|
||||
Address(rbx, instanceKlass::vtable_length_offset() * wordSize));
|
||||
__ lea(rbx, Address(rbx, j_rarg1, Address::times_8, base));
|
||||
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
__ round_to(rbx, BytesPerLong);
|
||||
}
|
||||
Label hit, next, entry, throw_icce;
|
||||
|
||||
__ jmpb(entry);
|
||||
|
||||
__ bind(next);
|
||||
__ addptr(rbx, itableOffsetEntry::size() * wordSize);
|
||||
|
||||
__ bind(entry);
|
||||
|
||||
// If the entry is NULL then we've reached the end of the table
|
||||
// without finding the expected interface, so throw an exception
|
||||
__ movptr(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ testptr(j_rarg1, j_rarg1);
|
||||
__ jcc(Assembler::zero, throw_icce);
|
||||
__ cmpptr(rax, j_rarg1);
|
||||
__ jccb(Assembler::notEqual, next);
|
||||
|
||||
// We found a hit, move offset into j_rarg1
|
||||
__ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
|
||||
// Compute itableMethodEntry
|
||||
const int method_offset =
|
||||
(itableMethodEntry::size() * wordSize * vtable_index) +
|
||||
itableMethodEntry::method_offset_in_bytes();
|
||||
const Register method = rbx;
|
||||
Label throw_icce;
|
||||
|
||||
// Get methodOop and entrypoint for compiler
|
||||
|
||||
// Get klass pointer again
|
||||
__ load_klass(rax, j_rarg0);
|
||||
|
||||
const Register method = rbx;
|
||||
__ movptr(method, Address(rax, j_rarg1, Address::times_1, method_offset));
|
||||
|
||||
// Restore saved register, before possible trap.
|
||||
__ pop(j_rarg1);
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
r10, rax, itable_index,
|
||||
// outputs: method, scan temp. reg
|
||||
method, r11,
|
||||
throw_icce);
|
||||
|
||||
// method (rbx): methodOop
|
||||
// j_rarg0: receiver
|
||||
|
||||
|
||||
#ifdef ASSERT
|
||||
if (DebugVtables) {
|
||||
Label L2;
|
||||
@ -211,12 +180,16 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
__ jmp(Address(method, methodOopDesc::from_compiled_offset()));
|
||||
|
||||
__ bind(throw_icce);
|
||||
// Restore saved register
|
||||
__ pop(j_rarg1);
|
||||
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
||||
|
||||
__ flush();
|
||||
|
||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||
tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
|
||||
itable_index, s->entry_point(),
|
||||
(int)(s->code_end() - s->entry_point()),
|
||||
(int)(s->code_end() - __ pc()));
|
||||
}
|
||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||
|
||||
s->set_exception_points(npe_addr, ame_addr);
|
||||
@ -230,7 +203,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||
(UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long
|
||||
} else {
|
||||
// Itable stub size
|
||||
return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) +
|
||||
return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) +
|
||||
(UseCompressedOops ? 32 : 0); // 2 leaqs
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -130,7 +130,7 @@ reg_def XMM7b( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next());
|
||||
// allocation. Highest priority is first. A useful heuristic is to
|
||||
// give registers a low priority when they are required by machine
|
||||
// instructions, like EAX and EDX. Registers which are used as
|
||||
// pairs must fall on an even boundry (witness the FPR#L's in this list).
|
||||
// pairs must fall on an even boundary (witness the FPR#L's in this list).
|
||||
// For the Intel integer registers, the equivalent Long pairs are
|
||||
// EDX:EAX, EBX:ECX, and EDI:EBP.
|
||||
alloc_class chunk0( ECX, EBX, EBP, EDI, EAX, EDX, ESI, ESP,
|
||||
@ -3126,14 +3126,12 @@ encode %{
|
||||
|
||||
enc_class movq_ld(regXD dst, memory mem) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
|
||||
__ movq(as_XMMRegister($dst$$reg), madr);
|
||||
__ movq($dst$$XMMRegister, $mem$$Address);
|
||||
%}
|
||||
|
||||
enc_class movq_st(memory mem, regXD src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
|
||||
__ movq(madr, as_XMMRegister($src$$reg));
|
||||
__ movq($mem$$Address, $src$$XMMRegister);
|
||||
%}
|
||||
|
||||
enc_class pshufd_8x8(regX dst, regX src) %{
|
||||
@ -3751,8 +3749,8 @@ encode %{
|
||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
|
||||
// Load first characters
|
||||
masm.load_unsigned_word(rcx, Address(rbx, 0));
|
||||
masm.load_unsigned_word(rdi, Address(rax, 0));
|
||||
masm.load_unsigned_short(rcx, Address(rbx, 0));
|
||||
masm.load_unsigned_short(rdi, Address(rax, 0));
|
||||
|
||||
// Compare first characters
|
||||
masm.subl(rcx, rdi);
|
||||
@ -3782,8 +3780,8 @@ encode %{
|
||||
|
||||
// Compare the rest of the characters
|
||||
masm.bind(WHILE_HEAD_LABEL);
|
||||
masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
|
||||
masm.subl(rcx, rdi);
|
||||
masm.jcc(Assembler::notZero, POP_LABEL);
|
||||
masm.incrementl(rsi);
|
||||
@ -3840,8 +3838,8 @@ encode %{
|
||||
masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
|
||||
|
||||
// Compare 2-byte "tail" at end of arrays
|
||||
masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.cmpl(tmp1Reg, tmp2Reg);
|
||||
masm.jcc(Assembler::notEqual, FALSE_LABEL);
|
||||
masm.testl(resultReg, resultReg);
|
||||
@ -5857,7 +5855,7 @@ operand cmpOp_commute() %{
|
||||
|
||||
//----------OPERAND CLASSES----------------------------------------------------
|
||||
// Operand Classes are groups of operands that are used as to simplify
|
||||
// instruction definitions by not requiring the AD writer to specify seperate
|
||||
// instruction definitions by not requiring the AD writer to specify separate
|
||||
// instructions for every form of operand when the instruction accepts
|
||||
// multiple operand types with the same basic encoding and format. The classic
|
||||
// case of this is memory operands.
|
||||
@ -6396,21 +6394,94 @@ instruct loadB(xRegI dst, memory mem) %{
|
||||
match(Set dst (LoadB mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX8 $dst,$mem" %}
|
||||
opcode(0xBE, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegMem(dst,mem));
|
||||
ins_pipe( ialu_reg_mem );
|
||||
format %{ "MOVSX8 $dst,$mem\t# byte" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Byte (8bit UNsigned)
|
||||
instruct loadUB(xRegI dst, memory mem, immI_255 bytemask) %{
|
||||
match(Set dst (AndI (LoadB mem) bytemask));
|
||||
// Load Byte (8bit signed) into Long Register
|
||||
instruct loadB2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadB mem)));
|
||||
|
||||
ins_cost(375);
|
||||
format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t"
|
||||
"MOV $dst.hi,$dst.lo\n\t"
|
||||
"SAR $dst.hi,7" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
__ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
|
||||
__ sarl(HIGH_FROM_LOW($dst$$Register), 7); // 24+1 MSB are already signed extended.
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8bit UNsigned)
|
||||
instruct loadUB(xRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUB mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVZX8 $dst,$mem" %}
|
||||
opcode(0xB6, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegMem(dst,mem));
|
||||
ins_pipe( ialu_reg_mem );
|
||||
format %{ "MOVZX8 $dst,$mem\t# ubyte -> int" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) into Long Register
|
||||
instruct loadUB2L(eRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadUB mem)));
|
||||
|
||||
ins_cost(250);
|
||||
format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzbl($dst$$Register, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed)
|
||||
instruct loadS(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadS mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst,$mem\t# short" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed) into Long Register
|
||||
instruct loadS2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadS mem)));
|
||||
|
||||
ins_cost(375);
|
||||
format %{ "MOVSX $dst.lo,$mem\t# short -> long\n\t"
|
||||
"MOV $dst.hi,$dst.lo\n\t"
|
||||
"SAR $dst.hi,15" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $mem$$Address);
|
||||
__ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
|
||||
__ sarl(HIGH_FROM_LOW($dst$$Register), 15); // 16+1 MSB are already signed extended.
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit unsigned)
|
||||
@ -6418,10 +6489,30 @@ instruct loadUS(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUS mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVZX $dst,$mem" %}
|
||||
opcode(0xB7, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegMem(dst,mem));
|
||||
ins_pipe( ialu_reg_mem );
|
||||
format %{ "MOVZX $dst,$mem\t# ushort/char -> int" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzwl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
|
||||
instruct loadUS2L(eRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadUS mem)));
|
||||
|
||||
ins_cost(250);
|
||||
format %{ "MOVZX $dst.lo,$mem\t# ushort/char -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzwl($dst$$Register, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer
|
||||
@ -6429,10 +6520,47 @@ instruct loadI(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadI mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOV $dst,$mem" %}
|
||||
opcode(0x8B);
|
||||
ins_encode( OpcP, RegMem(dst,mem));
|
||||
ins_pipe( ialu_reg_mem );
|
||||
format %{ "MOV $dst,$mem\t# int" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into Long Register
|
||||
instruct loadI2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadI mem)));
|
||||
|
||||
ins_cost(375);
|
||||
format %{ "MOV $dst.lo,$mem\t# int -> long\n\t"
|
||||
"MOV $dst.hi,$dst.lo\n\t"
|
||||
"SAR $dst.hi,31" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movl($dst$$Register, $mem$$Address);
|
||||
__ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
|
||||
__ sarl(HIGH_FROM_LOW($dst$$Register), 31);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Integer into Long Register
|
||||
instruct loadUI2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (LoadUI2L mem));
|
||||
|
||||
ins_cost(250);
|
||||
format %{ "MOV $dst.lo,$mem\t# uint -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movl($dst$$Register, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Long. Cannot clobber address while loading, so restrict address
|
||||
@ -6442,11 +6570,17 @@ instruct loadL(eRegL dst, load_long_memory mem) %{
|
||||
match(Set dst (LoadL mem));
|
||||
|
||||
ins_cost(250);
|
||||
format %{ "MOV $dst.lo,$mem\n\t"
|
||||
format %{ "MOV $dst.lo,$mem\t# long\n\t"
|
||||
"MOV $dst.hi,$mem+4" %}
|
||||
opcode(0x8B, 0x8B);
|
||||
ins_encode( OpcP, RegMem(dst,mem), OpcS, RegMem_Hi(dst,mem));
|
||||
ins_pipe( ialu_reg_long_mem );
|
||||
|
||||
ins_encode %{
|
||||
Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, false);
|
||||
Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, false);
|
||||
__ movl($dst$$Register, Amemlo);
|
||||
__ movl(HIGH_FROM_LOW($dst$$Register), Amemhi);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_long_mem);
|
||||
%}
|
||||
|
||||
// Volatile Load Long. Must be atomic, so do 64-bit FILD
|
||||
@ -6521,17 +6655,6 @@ instruct loadKlass(eRegP dst, memory mem) %{
|
||||
ins_pipe( ialu_reg_mem );
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed)
|
||||
instruct loadS(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadS mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst,$mem" %}
|
||||
opcode(0xBF, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegMem(dst,mem));
|
||||
ins_pipe( ialu_reg_mem );
|
||||
%}
|
||||
|
||||
// Load Double
|
||||
instruct loadD(regD dst, memory mem) %{
|
||||
predicate(UseSSE<=1);
|
||||
@ -7957,7 +8080,7 @@ instruct storeLConditional( memory mem, eADXRegL oldval, eBCXRegL newval, eFlags
|
||||
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
|
||||
if( os::is_MP() )
|
||||
__ lock();
|
||||
__ cmpxchg8(Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp));
|
||||
__ cmpxchg8($mem$$Address);
|
||||
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
|
||||
%}
|
||||
ins_pipe( pipe_cmpxchg );
|
||||
@ -11467,6 +11590,7 @@ instruct convI2X_reg(regX dst, eRegI src) %{
|
||||
instruct convI2L_reg( eRegL dst, eRegI src, eFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L src));
|
||||
effect(KILL cr);
|
||||
ins_cost(375);
|
||||
format %{ "MOV $dst.lo,$src\n\t"
|
||||
"MOV $dst.hi,$src\n\t"
|
||||
"SAR $dst.hi,31" %}
|
||||
@ -11478,6 +11602,7 @@ instruct convI2L_reg( eRegL dst, eRegI src, eFlagsReg cr) %{
|
||||
instruct convI2L_reg_zex(eRegL dst, eRegI src, immL_32bits mask, eFlagsReg flags ) %{
|
||||
match(Set dst (AndL (ConvI2L src) mask) );
|
||||
effect( KILL flags );
|
||||
ins_cost(250);
|
||||
format %{ "MOV $dst.lo,$src\n\t"
|
||||
"XOR $dst.hi,$dst.hi" %}
|
||||
opcode(0x33); // XOR
|
||||
@ -11489,6 +11614,7 @@ instruct convI2L_reg_zex(eRegL dst, eRegI src, immL_32bits mask, eFlagsReg flags
|
||||
instruct zerox_long(eRegL dst, eRegL src, immL_32bits mask, eFlagsReg flags ) %{
|
||||
match(Set dst (AndL src mask) );
|
||||
effect( KILL flags );
|
||||
ins_cost(250);
|
||||
format %{ "MOV $dst.lo,$src.lo\n\t"
|
||||
"XOR $dst.hi,$dst.hi\n\t" %}
|
||||
opcode(0x33); // XOR
|
||||
@ -13220,7 +13346,7 @@ instruct safePoint_poll(eFlagsReg cr) %{
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
//
|
||||
// peepmatch ( root_instr_name [preceeding_instruction]* );
|
||||
// peepmatch ( root_instr_name [preceding_instruction]* );
|
||||
//
|
||||
// peepconstraint %{
|
||||
// (instruction_number.operand_name relational_op instruction_number.operand_name
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -3462,14 +3462,12 @@ encode %{
|
||||
|
||||
enc_class movq_ld(regD dst, memory mem) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
|
||||
__ movq(as_XMMRegister($dst$$reg), madr);
|
||||
__ movq($dst$$XMMRegister, $mem$$Address);
|
||||
%}
|
||||
|
||||
enc_class movq_st(memory mem, regD src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
|
||||
__ movq(madr, as_XMMRegister($src$$reg));
|
||||
__ movq($mem$$Address, $src$$XMMRegister);
|
||||
%}
|
||||
|
||||
enc_class pshufd_8x8(regF dst, regF src) %{
|
||||
@ -3765,8 +3763,8 @@ encode %{
|
||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
|
||||
// Load first characters
|
||||
masm.load_unsigned_word(rcx, Address(rbx, 0));
|
||||
masm.load_unsigned_word(rdi, Address(rax, 0));
|
||||
masm.load_unsigned_short(rcx, Address(rbx, 0));
|
||||
masm.load_unsigned_short(rdi, Address(rax, 0));
|
||||
|
||||
// Compare first characters
|
||||
masm.subl(rcx, rdi);
|
||||
@ -3796,8 +3794,8 @@ encode %{
|
||||
|
||||
// Compare the rest of the characters
|
||||
masm.bind(WHILE_HEAD_LABEL);
|
||||
masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
|
||||
masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
|
||||
masm.subl(rcx, rdi);
|
||||
masm.jcc(Assembler::notZero, POP_LABEL);
|
||||
masm.increment(rsi);
|
||||
@ -3854,8 +3852,8 @@ encode %{
|
||||
masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
|
||||
|
||||
// Compare 2-byte "tail" at end of arrays
|
||||
masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
|
||||
masm.cmpl(tmp1Reg, tmp2Reg);
|
||||
masm.jcc(Assembler::notEqual, FALSE_LABEL);
|
||||
masm.testl(resultReg, resultReg);
|
||||
@ -5483,7 +5481,7 @@ operand cmpOpUCF2() %{
|
||||
|
||||
//----------OPERAND CLASSES----------------------------------------------------
|
||||
// Operand Classes are groups of operands that are used as to simplify
|
||||
// instruction definitions by not requiring the AD writer to specify seperate
|
||||
// instruction definitions by not requiring the AD writer to specify separate
|
||||
// instructions for every form of operand when the instruction accepts
|
||||
// multiple operand types with the same basic encoding and format. The classic
|
||||
// case of this is memory operands.
|
||||
@ -6031,70 +6029,88 @@ instruct loadB(rRegI dst, memory mem)
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movsbl $dst, $mem\t# byte" %}
|
||||
opcode(0x0F, 0xBE);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Byte (8 bit signed) into long
|
||||
// instruct loadB2L(rRegL dst, memory mem)
|
||||
// %{
|
||||
// match(Set dst (ConvI2L (LoadB mem)));
|
||||
|
||||
// ins_cost(125);
|
||||
// format %{ "movsbq $dst, $mem\t# byte -> long" %}
|
||||
// opcode(0x0F, 0xBE);
|
||||
// ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
// %}
|
||||
|
||||
// Load Byte (8 bit UNsigned)
|
||||
instruct loadUB(rRegI dst, memory mem, immI_255 bytemask)
|
||||
// Load Byte (8 bit signed) into Long Register
|
||||
instruct loadB2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (AndI (LoadB mem) bytemask));
|
||||
match(Set dst (ConvI2L (LoadB mem)));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movsbq $dst, $mem\t# byte -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movsbq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned)
|
||||
instruct loadUB(rRegI dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadUB mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movzbl $dst, $mem\t# ubyte" %}
|
||||
opcode(0x0F, 0xB6);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movzbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Byte (8 bit UNsigned) into long
|
||||
// instruct loadUB2L(rRegL dst, memory mem, immI_255 bytemask)
|
||||
// %{
|
||||
// match(Set dst (ConvI2L (AndI (LoadB mem) bytemask)));
|
||||
// Load Unsigned Byte (8 bit UNsigned) into Long Register
|
||||
instruct loadUB2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadUB mem)));
|
||||
|
||||
// ins_cost(125);
|
||||
// format %{ "movzbl $dst, $mem\t# ubyte -> long" %}
|
||||
// opcode(0x0F, 0xB6);
|
||||
// ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
// %}
|
||||
ins_cost(125);
|
||||
format %{ "movzbq $dst, $mem\t# ubyte -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzbq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed)
|
||||
instruct loadS(rRegI dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadS mem));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
ins_cost(125);
|
||||
format %{ "movswl $dst, $mem\t# short" %}
|
||||
opcode(0x0F, 0xBF);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed) into long
|
||||
// instruct loadS2L(rRegL dst, memory mem)
|
||||
// %{
|
||||
// match(Set dst (ConvI2L (LoadS mem)));
|
||||
// Load Short (16 bit signed) into Long Register
|
||||
instruct loadS2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadS mem)));
|
||||
|
||||
// ins_cost(125); // XXX
|
||||
// format %{ "movswq $dst, $mem\t# short -> long" %}
|
||||
// opcode(0x0F, 0xBF);
|
||||
// ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
// %}
|
||||
ins_cost(125);
|
||||
format %{ "movswq $dst, $mem\t# short -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movswq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned)
|
||||
instruct loadUS(rRegI dst, memory mem)
|
||||
@ -6103,32 +6119,71 @@ instruct loadUS(rRegI dst, memory mem)
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movzwl $dst, $mem\t# ushort/char" %}
|
||||
opcode(0x0F, 0xB7);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movzwl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into long
|
||||
// instruct loadUS2L(rRegL dst, memory mem)
|
||||
// %{
|
||||
// match(Set dst (ConvI2L (LoadUS mem)));
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
|
||||
instruct loadUS2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadUS mem)));
|
||||
|
||||
// ins_cost(125);
|
||||
// format %{ "movzwl $dst, $mem\t# ushort/char -> long" %}
|
||||
// opcode(0x0F, 0xB7);
|
||||
// ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
// %}
|
||||
ins_cost(125);
|
||||
format %{ "movzwq $dst, $mem\t# ushort/char -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movzwq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer
|
||||
instruct loadI(rRegI dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadI mem));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
ins_cost(125);
|
||||
format %{ "movl $dst, $mem\t# int" %}
|
||||
opcode(0x8B);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into Long Register
|
||||
instruct loadI2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadI mem)));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movslq $dst, $mem\t# int -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movslq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Integer into Long Register
|
||||
instruct loadUI2L(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadUI2L mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movl $dst, $mem\t# uint -> long" %}
|
||||
|
||||
ins_encode %{
|
||||
__ movl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
@ -6137,10 +6192,13 @@ instruct loadL(rRegL dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadL mem));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
ins_cost(125);
|
||||
format %{ "movq $dst, $mem\t# long" %}
|
||||
opcode(0x8B);
|
||||
ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
|
||||
|
||||
ins_encode %{
|
||||
__ movq($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_mem); // XXX
|
||||
%}
|
||||
|
||||
@ -8363,7 +8421,7 @@ instruct divModL_rReg_divmod(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
|
||||
//----------- DivL-By-Constant-Expansions--------------------------------------
|
||||
// DivI cases are handled by the compiler
|
||||
|
||||
// Magic constant, reciprical of 10
|
||||
// Magic constant, reciprocal of 10
|
||||
instruct loadConL_0x6666666666666667(rRegL dst)
|
||||
%{
|
||||
effect(DEF dst);
|
||||
@ -10804,16 +10862,6 @@ instruct convI2L_reg_reg(rRegL dst, rRegI src)
|
||||
// ins_pipe(ialu_reg_reg);
|
||||
// %}
|
||||
|
||||
instruct convI2L_reg_mem(rRegL dst, memory src)
|
||||
%{
|
||||
match(Set dst (ConvI2L (LoadI src)));
|
||||
|
||||
format %{ "movslq $dst, $src\t# i2l" %}
|
||||
opcode(0x63); // needs REX.W
|
||||
ins_encode(REX_reg_mem_wide(dst, src), OpcP, reg_mem(dst,src));
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Zero-extend convert int to long
|
||||
instruct convI2L_reg_reg_zex(rRegL dst, rRegI src, immL_32bits mask)
|
||||
%{
|
||||
@ -12082,7 +12130,7 @@ instruct RethrowException()
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
//
|
||||
// peepmatch ( root_instr_name [precerding_instruction]* );
|
||||
// peepmatch ( root_instr_name [preceding_instruction]* );
|
||||
//
|
||||
// peepconstraint %{
|
||||
// (instruction_number.operand_name relational_op instruction_number.operand_name
|
||||
|
@ -419,7 +419,7 @@ main(int argc, char ** argv)
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
if(mainClass == NULL) { /* exception occurred */
|
||||
ReportExceptionDescription(env);
|
||||
message = "Could not find the main class. Program will exit.";
|
||||
goto leave;
|
||||
@ -441,7 +441,7 @@ main(int argc, char ** argv)
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
if(mainClass == NULL) { /* exception occurred */
|
||||
ReportExceptionDescription(env);
|
||||
message = "Could not find the main class. Program will exit.";
|
||||
goto leave;
|
||||
|
@ -47,7 +47,7 @@
|
||||
#ifdef JAVA_ARGS
|
||||
/*
|
||||
* ApplicationHome is prepended to each of these entries; the resulting
|
||||
* strings are concatenated (seperated by PATH_SEPARATOR) and used as the
|
||||
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
|
||||
* value of -cp option to the launcher.
|
||||
*/
|
||||
#ifndef APP_CLASSPATH
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -192,7 +192,7 @@ static pid_t filename_to_pid(const char* filename) {
|
||||
// check if the given path is considered a secure directory for
|
||||
// the backing store files. Returns true if the directory exists
|
||||
// and is considered a secure location. Returns false if the path
|
||||
// is a symbolic link or if an error occured.
|
||||
// is a symbolic link or if an error occurred.
|
||||
//
|
||||
static bool is_directory_secure(const char* path) {
|
||||
struct stat statbuf;
|
||||
|
@ -419,7 +419,7 @@ main(int argc, char ** argv)
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
if(mainClass == NULL) { /* exception occurred */
|
||||
ReportExceptionDescription(env);
|
||||
message = "Could not find the main class. Program will exit.";
|
||||
goto leave;
|
||||
@ -441,7 +441,7 @@ main(int argc, char ** argv)
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
if(mainClass == NULL) { /* exception occurred */
|
||||
ReportExceptionDescription(env);
|
||||
message = "Could not find the main class. Program will exit.";
|
||||
goto leave;
|
||||
|
@ -47,7 +47,7 @@
|
||||
#ifdef JAVA_ARGS
|
||||
/*
|
||||
* ApplicationHome is prepended to each of these entries; the resulting
|
||||
* strings are concatenated (seperated by PATH_SEPARATOR) and used as the
|
||||
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
|
||||
* value of -cp option to the launcher.
|
||||
*/
|
||||
#ifndef APP_CLASSPATH
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -194,7 +194,7 @@ static pid_t filename_to_pid(const char* filename) {
|
||||
// check if the given path is considered a secure directory for
|
||||
// the backing store files. Returns true if the directory exists
|
||||
// and is considered a secure location. Returns false if the path
|
||||
// is a symbolic link or if an error occured.
|
||||
// is a symbolic link or if an error occurred.
|
||||
//
|
||||
static bool is_directory_secure(const char* path) {
|
||||
struct stat statbuf;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -195,7 +195,7 @@ static int filename_to_pid(const char* filename) {
|
||||
// check if the given path is considered a secure directory for
|
||||
// the backing store files. Returns true if the directory exists
|
||||
// and is considered a secure location. Returns false if the path
|
||||
// is a symbolic link or if an error occured.
|
||||
// is a symbolic link or if an error occurred.
|
||||
//
|
||||
static bool is_directory_secure(const char* path) {
|
||||
|
||||
@ -994,7 +994,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
return false;
|
||||
}
|
||||
|
||||
// if running on windows 2000 or later, set the automatic inheritence
|
||||
// if running on windows 2000 or later, set the automatic inheritance
|
||||
// control flags.
|
||||
SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;
|
||||
_SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr)
|
||||
@ -1002,7 +1002,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
"SetSecurityDescriptorControl");
|
||||
|
||||
if (_SetSecurityDescriptorControl != NULL) {
|
||||
// We do not want to further propogate inherited DACLs, so making them
|
||||
// We do not want to further propagate inherited DACLs, so making them
|
||||
// protected prevents that.
|
||||
if (!_SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED,
|
||||
SE_DACL_PROTECTED)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -532,7 +532,7 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
|
||||
if (oldAct.sa_sigaction != signalHandler) {
|
||||
void* sighand = oldAct.sa_sigaction ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
|
||||
: CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
|
||||
warning("Unexpected Signal %d occured under user-defined signal handler " INTPTR_FORMAT, sig, (intptr_t)sighand);
|
||||
warning("Unexpected Signal %d occurred under user-defined signal handler " INTPTR_FORMAT, sig, (intptr_t)sighand);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -299,13 +299,17 @@ static void check_for_sse_support() {
|
||||
|
||||
}
|
||||
|
||||
#endif // AMD64
|
||||
|
||||
bool os::supports_sse() {
|
||||
#ifdef AMD64
|
||||
return true;
|
||||
#else
|
||||
if (sse_status == SSE_UNKNOWN)
|
||||
check_for_sse_support();
|
||||
return sse_status == SSE_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif // AMD64
|
||||
}
|
||||
|
||||
bool os::is_allocatable(size_t bytes) {
|
||||
#ifdef AMD64
|
||||
@ -690,7 +694,7 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
|
||||
if (oldAct.sa_sigaction != signalHandler) {
|
||||
void* sighand = oldAct.sa_sigaction ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
|
||||
: CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
|
||||
warning("Unexpected Signal %d occured under user-defined signal handler %#lx", sig, (long)sighand);
|
||||
warning("Unexpected Signal %d occurred under user-defined signal handler %#lx", sig, (long)sighand);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,9 +41,10 @@
|
||||
static void fence_bootstrap ();
|
||||
|
||||
static void setup_fpu();
|
||||
static bool supports_sse();
|
||||
#endif // AMD64
|
||||
|
||||
static bool supports_sse();
|
||||
|
||||
static bool is_allocatable(size_t bytes);
|
||||
|
||||
// Used to register dynamic code cache area with the OS
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 2004-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// 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
hotspot/src/share/tools/LogCompilation/Makefile
Normal file
75
hotspot/src/share/tools/LogCompilation/Makefile
Normal file
@ -0,0 +1,75 @@
|
||||
#
|
||||
# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
# have any questions.
|
||||
#
|
||||
#
|
||||
PKGLIST = \
|
||||
com.sun.hotspot.tools.compiler
|
||||
#END PKGLIST
|
||||
|
||||
FILELIST = com/sun/hotspot/tools/compiler/*.java
|
||||
|
||||
ifneq "x$(ALT_BOOTDIR)" "x"
|
||||
BOOTDIR := $(ALT_BOOTDIR)
|
||||
endif
|
||||
|
||||
ifeq "x$(BOOTDIR)" "x"
|
||||
JDK_HOME := $(shell dirname $(shell which java))/..
|
||||
else
|
||||
JDK_HOME := $(BOOTDIR)
|
||||
endif
|
||||
|
||||
isUnix := $(shell test -r c:/; echo $$?)
|
||||
|
||||
ifeq "$(isUnix)" "1"
|
||||
CPS := :
|
||||
else
|
||||
CPS := ";"
|
||||
endif
|
||||
|
||||
SRC_DIR = src
|
||||
BUILD_DIR = build
|
||||
OUTPUT_DIR = $(BUILD_DIR)/classes
|
||||
|
||||
# gnumake 3.78.1 does not accept the *s,
|
||||
# so use the shell to expand them
|
||||
ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST))
|
||||
ALLFILES := $(shell /bin/ls $(ALLFILES))
|
||||
|
||||
JAVAC = $(JDK_HOME)/bin/javac
|
||||
JAR = $(JDK_HOME)/bin/jar
|
||||
|
||||
# Tagging it on because there's no reason not to run it
|
||||
all: logc.jar
|
||||
|
||||
logc.jar: filelist manifest.mf
|
||||
@mkdir -p $(OUTPUT_DIR)
|
||||
$(JAVAC) -source 1.5 -deprecation -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) @filelist
|
||||
$(JAR) cvfm logc.jar manifest.mf -C $(OUTPUT_DIR) com
|
||||
|
||||
.PHONY: filelist
|
||||
filelist: $(ALLFILES)
|
||||
@rm -f $@
|
||||
@echo $(ALLFILES) > $@
|
||||
|
||||
clean::
|
||||
rm -rf filelist logc.jar
|
||||
rm -rf $(BUILD_DIR)
|
18
hotspot/src/share/tools/LogCompilation/README
Normal file
18
hotspot/src/share/tools/LogCompilation/README
Normal file
@ -0,0 +1,18 @@
|
||||
This is a very rough tool for parsing -XX:+LogCompilation output.
|
||||
It's main purpose is to recreate output similar to
|
||||
-XX:+PrintCompilation -XX:+PrintInlining output from a debug JVM. It
|
||||
requires a 1.5 JDK to build and simply typing make should build it.
|
||||
|
||||
It produces a jar file, logc.jar, that can be run on the
|
||||
hotspot.log from LogCompilation output like this:
|
||||
|
||||
java -jar logc.jar hotspot.log
|
||||
|
||||
This will produce something like the normal PrintCompilation output.
|
||||
Adding the -i option with also report inlining like PrintInlining.
|
||||
|
||||
More information about the LogCompilation output can be found at
|
||||
|
||||
http://wikis.sun.com/display/HotSpotInternals/LogCompilation+overview
|
||||
http://wikis.sun.com/display/HotSpotInternals/PrintCompilation
|
||||
http://wikis.sun.com/display/HotSpotInternals/LogCompilation+tool
|
1
hotspot/src/share/tools/LogCompilation/manifest.mf
Normal file
1
hotspot/src/share/tools/LogCompilation/manifest.mf
Normal file
@ -0,0 +1 @@
|
||||
Main-Class: com.sun.hotspot.tools.compiler.LogCompilation
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.sun.hotspot.tools.compiler;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author never
|
||||
*/
|
||||
public abstract class BasicLogEvent implements LogEvent {
|
||||
|
||||
protected final String id;
|
||||
protected final double start;
|
||||
protected double end;
|
||||
protected Compilation compilation;
|
||||
|
||||
BasicLogEvent(double start, String id) {
|
||||
this.start = start;
|
||||
this.end = start;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(double end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public double getElapsedTime() {
|
||||
return ((int) ((getEnd() - getStart()) * 1000)) / 1000.0;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Compilation getCompilation() {
|
||||
return compilation;
|
||||
}
|
||||
|
||||
public void setCompilation(Compilation compilation) {
|
||||
this.compilation = compilation;
|
||||
}
|
||||
|
||||
abstract public void print(PrintStream stream);
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.sun.hotspot.tools.compiler;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CallSite {
|
||||
|
||||
private int bci;
|
||||
private Method method;
|
||||
private int count;
|
||||
private String receiver;
|
||||
private int receiver_count;
|
||||
private String reason;
|
||||
private List<CallSite> calls;
|
||||
|
||||
CallSite() {
|
||||
}
|
||||
|
||||
CallSite(int bci, Method m) {
|
||||
this.bci = bci;
|
||||
this.method = m;
|
||||
}
|
||||
|
||||
void add(CallSite site) {
|
||||
if (getCalls() == null) {
|
||||
setCalls(new ArrayList<CallSite>());
|
||||
}
|
||||
getCalls().add(site);
|
||||
}
|
||||
|
||||
CallSite last() {
|
||||
return last(-1);
|
||||
}
|
||||
|
||||
CallSite last(int fromEnd) {
|
||||
return getCalls().get(getCalls().size() + fromEnd);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (getReason() == null) {
|
||||
sb.append(" @ " + getBci() + " " + getMethod());
|
||||
} else {
|
||||
sb.append("- @ " + getBci() + " " + getMethod() + " " + getReason());
|
||||
}
|
||||
sb.append("\n");
|
||||
if (getCalls() != null) {
|
||||
for (CallSite site : getCalls()) {
|
||||
sb.append(site);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void print(PrintStream stream) {
|
||||
print(stream, 0);
|
||||
}
|
||||
|
||||
void emit(PrintStream stream, int indent) {
|
||||
for (int i = 0; i < indent; i++) {
|
||||
stream.print(' ');
|
||||
}
|
||||
}
|
||||
private static boolean compat = true;
|
||||
|
||||
public void print(PrintStream stream, int indent) {
|
||||
emit(stream, indent);
|
||||
String m = getMethod().getHolder().replace('/', '.') + "::" + getMethod().getName();
|
||||
if (getReason() == null) {
|
||||
stream.println(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
|
||||
|
||||
} else {
|
||||
if (isCompat()) {
|
||||
stream.println(" @ " + getBci() + " " + m + " " + getReason());
|
||||
} else {
|
||||
stream.println("- @ " + getBci() + " " + m +
|
||||
" (" + getMethod().getBytes() + " bytes) " + getReason());
|
||||
}
|
||||
}
|
||||
if (getReceiver() != null) {
|
||||
emit(stream, indent + 3);
|
||||
// stream.println("type profile " + method.holder + " -> " + receiver + " (" +
|
||||
// receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)");
|
||||
stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
|
||||
(getReceiverCount() * 100 / getCount()) + "%)");
|
||||
}
|
||||
if (getCalls() != null) {
|
||||
for (CallSite site : getCalls()) {
|
||||
site.print(stream, indent + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getBci() {
|
||||
return bci;
|
||||
}
|
||||
|
||||
public void setBci(int bci) {
|
||||
this.bci = bci;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(Method method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public String getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public void setReceiver(String receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public int getReceiverCount() {
|
||||
return receiver_count;
|
||||
}
|
||||
|
||||
public void setReceiver_count(int receiver_count) {
|
||||
this.receiver_count = receiver_count;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public List<CallSite> getCalls() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
public void setCalls(List<CallSite> calls) {
|
||||
this.calls = calls;
|
||||
}
|
||||
|
||||
public static boolean isCompat() {
|
||||
return compat;
|
||||
}
|
||||
|
||||
public static void setCompat(boolean aCompat) {
|
||||
compat = aCompat;
|
||||
}
|
||||
}
|
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.sun.hotspot.tools.compiler;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Compilation implements LogEvent {
|
||||
|
||||
private int id;
|
||||
private boolean osr;
|
||||
private Method method;
|
||||
private CallSite call = new CallSite();
|
||||
private int osrBci;
|
||||
private String icount;
|
||||
private String bcount;
|
||||
private String special;
|
||||
private double start;
|
||||
private double end;
|
||||
private int attempts;
|
||||
private NMethod nmethod;
|
||||
private ArrayList<Phase> phases = new ArrayList<Phase>(4);
|
||||
private String failureReason;
|
||||
|
||||
Compilation(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
Phase getPhase(String s) {
|
||||
for (Phase p : getPhases()) {
|
||||
if (p.getName().equals(s)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double getRegallocTime() {
|
||||
return getPhase("regalloc").getElapsedTime();
|
||||
}
|
||||
|
||||
public double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getId());
|
||||
sb.append(" ");
|
||||
sb.append(getMethod());
|
||||
sb.append(" ");
|
||||
sb.append(getIcount());
|
||||
sb.append("+");
|
||||
sb.append(getBcount());
|
||||
sb.append("\n");
|
||||
for (CallSite site : getCall().getCalls()) {
|
||||
sb.append(site);
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void printShort(PrintStream stream) {
|
||||
if (getMethod() == null) {
|
||||
stream.println(getSpecial());
|
||||
} else {
|
||||
int bc = isOsr() ? getOsr_bci() : -1;
|
||||
stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc));
|
||||
}
|
||||
}
|
||||
|
||||
public void print(PrintStream stream) {
|
||||
print(stream, 0, false);
|
||||
}
|
||||
|
||||
public void print(PrintStream stream, boolean printInlining) {
|
||||
print(stream, 0, printInlining);
|
||||
}
|
||||
|
||||
public void print(PrintStream stream, int indent, boolean printInlining) {
|
||||
if (getMethod() == null) {
|
||||
stream.println(getSpecial());
|
||||
} else {
|
||||
int bc = isOsr() ? getOsr_bci() : -1;
|
||||
stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc));
|
||||
stream.println();
|
||||
if (getFailureReason() != null) {
|
||||
stream.println("COMPILE FAILED " + getFailureReason());
|
||||
}
|
||||
if (printInlining && call.getCalls() != null) {
|
||||
for (CallSite site : call.getCalls()) {
|
||||
site.print(stream, indent + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean isOsr() {
|
||||
return osr;
|
||||
}
|
||||
|
||||
public void setOsr(boolean osr) {
|
||||
this.osr = osr;
|
||||
}
|
||||
|
||||
public int getOsr_bci() {
|
||||
return osrBci;
|
||||
}
|
||||
|
||||
public void setOsr_bci(int osrBci) {
|
||||
this.osrBci = osrBci;
|
||||
}
|
||||
|
||||
public String getIcount() {
|
||||
return icount;
|
||||
}
|
||||
|
||||
public void setICount(String icount) {
|
||||
this.icount = icount;
|
||||
}
|
||||
|
||||
public String getBcount() {
|
||||
return bcount;
|
||||
}
|
||||
|
||||
public void setBCount(String bcount) {
|
||||
this.bcount = bcount;
|
||||
}
|
||||
|
||||
public String getSpecial() {
|
||||
return special;
|
||||
}
|
||||
|
||||
public void setSpecial(String special) {
|
||||
this.special = special;
|
||||
}
|
||||
|
||||
public void setStart(double start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(double end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getAttempts() {
|
||||
return attempts;
|
||||
}
|
||||
|
||||
public void setAttempts(int attempts) {
|
||||
this.attempts = attempts;
|
||||
}
|
||||
|
||||
public NMethod getNMethod() {
|
||||
return nmethod;
|
||||
}
|
||||
|
||||
public void setNMethod(NMethod NMethod) {
|
||||
this.nmethod = NMethod;
|
||||
}
|
||||
|
||||
public ArrayList<Phase> getPhases() {
|
||||
return phases;
|
||||
}
|
||||
|
||||
public void setPhases(ArrayList<Phase> phases) {
|
||||
this.setPhases(phases);
|
||||
}
|
||||
|
||||
public String getFailureReason() {
|
||||
return failureReason;
|
||||
}
|
||||
|
||||
public void setFailureReason(String failureReason) {
|
||||
this.failureReason = failureReason;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(Method method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public CallSite getCall() {
|
||||
return call;
|
||||
}
|
||||
|
||||
public void setCall(CallSite call) {
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
public double getElapsedTime() {
|
||||
return end - start;
|
||||
}
|
||||
|
||||
public Compilation getCompilation() {
|
||||
return this;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user