Merge
This commit is contained in:
commit
f973f48305
@ -143,3 +143,4 @@ a4f28069d44a379cda99dd1d921d19f819726d22 jdk8-b15
|
||||
237bc29afbfc6f56a4fe4a6008e2befb59c44bac jdk8-b19
|
||||
5a5eaf6374bcbe23530899579fed17a05b7705f3 jdk8-b20
|
||||
cc771d92284f71765eca14d6d08703c4af254c04 jdk8-b21
|
||||
7ad075c809952e355d25030605da6af30456ed74 jdk8-b22
|
||||
|
@ -143,3 +143,4 @@ e59c47de1ad8982ff3b0e843773a6902b36c2337 jdk8-b14
|
||||
e1366c5d84ef984095a332bcee70b3938232d07d jdk8-b19
|
||||
51d8b6cb18c0978ecfa4f33e1537d35ee01b69fa jdk8-b20
|
||||
f157fc2a71a38ce44007a6f18d5b011824dce705 jdk8-b21
|
||||
a11d0062c445d5f36651c78650ab88aa594bcbff jdk8-b22
|
||||
|
@ -211,3 +211,5 @@ a2fef924d8e6f37dac2a887315e3502876cc8e24 hs23-b08
|
||||
fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20
|
||||
9952d1c439d64c5fd4ad1236a63a62bd5a49d4c3 jdk8-b21
|
||||
513351373923f74a7c91755748b95c9771e59f96 hs23-b10
|
||||
24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22
|
||||
dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11
|
||||
|
@ -367,7 +367,7 @@ endif
|
||||
$(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
|
||||
$(install-file)
|
||||
|
||||
# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h)
|
||||
# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
|
||||
$(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
|
||||
$(install-file)
|
||||
|
||||
@ -384,6 +384,16 @@ $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h: $(HS_JNI_ARCH_SRC)
|
||||
$(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/services/%
|
||||
$(install-file)
|
||||
|
||||
JFR_EXISTS=$(shell if [ -d $(HS_ALT_SRC) ]; then echo 1; else echo 0; fi)
|
||||
# export jfr.h
|
||||
ifeq ($JFR_EXISTS,1)
|
||||
$(EXPORT_INCLUDE_DIR)/%: $(HS_ALT_SRC)/share/vm/jfr/agent/%
|
||||
$(install-file)
|
||||
else
|
||||
$(EXPORT_INCLUDE_DIR)/jfr.h:
|
||||
|
||||
endif
|
||||
|
||||
# Doc files (jvmti.html)
|
||||
$(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/%
|
||||
$(install-file)
|
||||
|
@ -96,6 +96,10 @@ ifdef DEFAULT_LIBPATH
|
||||
CPPFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\""
|
||||
endif
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
CFLAGS += -DINCLUDE_TRACE
|
||||
endif
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
CFLAGS += $(CFLAGS_WARN/BYFILE)
|
||||
|
||||
@ -147,6 +151,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
|
||||
find $(HS_ALT_SRC)/share/vm/jfr -type d; \
|
||||
fi)
|
||||
endif
|
||||
|
||||
CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
|
||||
CORE_PATHS+=$(GENERATED)/jvmtifiles
|
||||
|
||||
|
@ -294,3 +294,7 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmticmlr.h
|
||||
EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h
|
||||
EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h
|
||||
EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h
|
||||
endif
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011
|
||||
|
||||
HS_MAJOR_VER=23
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=10
|
||||
HS_BUILD_NUMBER=11
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=8
|
||||
|
@ -98,6 +98,10 @@ CPPFLAGS = \
|
||||
${JRE_VERSION} \
|
||||
${VM_DISTRO}
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
CFLAGS += -DINCLUDE_TRACE
|
||||
endif
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
CFLAGS += $(CFLAGS_WARN/BYFILE)
|
||||
|
||||
@ -143,6 +147,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
|
||||
find $(HS_ALT_SRC)/share/vm/jfr -type d; \
|
||||
fi)
|
||||
endif
|
||||
|
||||
CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
|
||||
CORE_PATHS+=$(GENERATED)/jvmtifiles
|
||||
|
||||
|
@ -93,7 +93,7 @@ CFLAGS += $(CFLAGS_WARN)
|
||||
CFLAGS += $(CFLAGS/NOEX)
|
||||
|
||||
# Extra flags from gnumake's invocation or environment
|
||||
CFLAGS += $(EXTRA_CFLAGS)
|
||||
CFLAGS += $(EXTRA_CFLAGS) -DINCLUDE_TRACE
|
||||
|
||||
# Math Library (libm.so), do not use -lm.
|
||||
# There might be two versions of libm.so on the build system:
|
||||
@ -160,6 +160,10 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
|
||||
|
||||
SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
|
||||
find $(HS_ALT_SRC)/share/vm/jfr -type d; \
|
||||
fi)
|
||||
|
||||
CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
|
||||
CORE_PATHS+=$(GENERATED)/jvmtifiles
|
||||
|
||||
|
@ -35,6 +35,8 @@ cl 2>&1 | grep "IA-64" >NUL
|
||||
if %errorlevel% == 0 goto isia64
|
||||
cl 2>&1 | grep "AMD64" >NUL
|
||||
if %errorlevel% == 0 goto amd64
|
||||
cl 2>&1 | grep "x64" >NUL
|
||||
if %errorlevel% == 0 goto amd64
|
||||
set ARCH=x86
|
||||
set BUILDARCH=i486
|
||||
set Platform_arch=x86
|
||||
|
@ -73,6 +73,13 @@ done
|
||||
|
||||
BASE_PATHS="${BASE_PATHS} ${GENERATED}/jvmtifiles"
|
||||
|
||||
if [ -d "${ALTSRC}/share/vm/jfr" ]; then
|
||||
BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent"
|
||||
BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent/isolated_deps/util"
|
||||
BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/jvm"
|
||||
BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr"
|
||||
fi
|
||||
|
||||
CORE_PATHS="${BASE_PATHS}"
|
||||
# shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS.
|
||||
if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then
|
||||
|
@ -58,7 +58,8 @@ ProjectCreatorIncludesPRIVATE=\
|
||||
-absoluteInclude $(HOTSPOTBUILDSPACE)/%f/generated \
|
||||
-ignorePath $(HOTSPOTBUILDSPACE)/%f/generated \
|
||||
-ignorePath src\share\vm\adlc \
|
||||
-ignorePath src\share\vm\shark
|
||||
-ignorePath src\share\vm\shark \
|
||||
-ignorePath posix
|
||||
|
||||
# This is referenced externally by both the IDE and batch builds
|
||||
ProjectCreatorOptions=
|
||||
@ -88,7 +89,7 @@ ProjectCreatorIDEOptions=\
|
||||
-jdkTargetRoot $(HOTSPOTJDKDIST) \
|
||||
-define ALIGN_STACK_FRAMES \
|
||||
-define VM_LITTLE_ENDIAN \
|
||||
-prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \
|
||||
-prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \
|
||||
-postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
|
||||
-ignoreFile jsig.c \
|
||||
-ignoreFile jvmtiEnvRecommended.cpp \
|
||||
|
@ -19,7 +19,7 @@
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
# Resource file containing VERSIONINFO
|
||||
@ -30,7 +30,7 @@ Res_Files=.\version.res
|
||||
COMMONSRC=$(WorkSpace)\src
|
||||
ALTSRC=$(WorkSpace)\src\closed
|
||||
|
||||
!ifdef RELEASE
|
||||
!ifdef RELEASE
|
||||
!ifdef DEVELOP
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "DEBUG"
|
||||
!else
|
||||
@ -74,6 +74,10 @@ CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_TARGET=\"$(BUILD_FLAVOR)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\""
|
||||
|
||||
!ifndef JAVASE_EMBEDDED
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "INCLUDE_TRACE"
|
||||
!endif
|
||||
|
||||
CPP_FLAGS=$(CPP_FLAGS) $(CPP_INCLUDE_DIRS)
|
||||
|
||||
# Define that so jni.h is on correct side
|
||||
@ -97,7 +101,7 @@ AGCT_EXPORT=/export:AsyncGetCallTrace
|
||||
!endif
|
||||
|
||||
# If you modify exports below please do the corresponding changes in
|
||||
# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
|
||||
# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
|
||||
LINK_FLAGS=$(LINK_FLAGS) $(STACK_SIZE) /subsystem:windows /dll /base:0x8000000 \
|
||||
/export:JNI_GetDefaultJavaVMInitArgs \
|
||||
/export:JNI_CreateJavaVM \
|
||||
@ -170,6 +174,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/utilities
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/libadt
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/os/windows/vm
|
||||
@ -177,6 +182,13 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/os_cpu/windows_$(Platform_arch)/vm
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/cpu/$(Platform_arch)/vm
|
||||
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/opto
|
||||
|
||||
!if exists($(ALTSRC)\share\vm\jfr)
|
||||
VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent
|
||||
VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent/isolated_deps/util
|
||||
VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/jvm
|
||||
VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr
|
||||
!endif
|
||||
|
||||
VM_PATH={$(VM_PATH)}
|
||||
|
||||
# Special case files not using precompiled header files.
|
||||
@ -263,6 +275,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
|
||||
{$(COMMONSRC)\share\vm\services}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(COMMONSRC)\share\vm\trace}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(COMMONSRC)\share\vm\utilities}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
@ -340,6 +355,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
|
||||
{$(ALTSRC)\share\vm\services}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\trace}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\utilities}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
@ -371,6 +389,18 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
|
||||
{..\generated\jvmtifiles}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\jfr}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\jfr\agent}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\jfr\agent\isolated_deps\util}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
{$(ALTSRC)\share\vm\jfr\jvm}.cpp.obj::
|
||||
$(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $<
|
||||
|
||||
default::
|
||||
|
||||
_build_pch_file.obj:
|
||||
|
@ -391,7 +391,7 @@ int LIR_Assembler::emit_exception_handler() {
|
||||
__ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type);
|
||||
__ delayed()->nop();
|
||||
__ should_not_reach_here();
|
||||
assert(code_offset() - offset <= exception_handler_size, "overflow");
|
||||
guarantee(code_offset() - offset <= exception_handler_size, "overflow");
|
||||
__ end_a_stub();
|
||||
|
||||
return offset;
|
||||
@ -474,8 +474,7 @@ int LIR_Assembler::emit_deopt_handler() {
|
||||
AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
|
||||
__ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp
|
||||
__ delayed()->nop();
|
||||
assert(code_offset() - offset <= deopt_handler_size, "overflow");
|
||||
debug_only(__ stop("should have gone to the caller");)
|
||||
guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
|
||||
__ end_a_stub();
|
||||
|
||||
return offset;
|
||||
|
@ -69,7 +69,7 @@ enum {
|
||||
#else
|
||||
call_stub_size = 20,
|
||||
#endif // _LP64
|
||||
exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4),
|
||||
deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4) };
|
||||
exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
|
||||
deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) };
|
||||
|
||||
#endif // CPU_SPARC_VM_C1_LIRASSEMBLER_SPARC_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -82,6 +82,8 @@ inline address* frame::O0_addr() const { return (address*) &younger_sp()[ I0->s
|
||||
|
||||
inline intptr_t* frame::sender_sp() const { return fp(); }
|
||||
|
||||
inline intptr_t* frame::real_fp() const { return fp(); }
|
||||
|
||||
// Used only in frame::oopmapreg_to_location
|
||||
// This return a value in VMRegImpl::slot_size
|
||||
inline int frame::pd_oop_map_offset_adjustment() const {
|
||||
|
@ -1045,7 +1045,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS)
|
||||
// OP_COLLECT_ARGS is below...
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS)
|
||||
|(!UseRicochetFrames ? 0 :
|
||||
|(
|
||||
java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 :
|
||||
((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS)
|
||||
|
@ -406,7 +406,7 @@ int LIR_Assembler::emit_exception_handler() {
|
||||
// search an exception handler (rax: exception oop, rdx: throwing pc)
|
||||
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id)));
|
||||
__ should_not_reach_here();
|
||||
assert(code_offset() - offset <= exception_handler_size, "overflow");
|
||||
guarantee(code_offset() - offset <= exception_handler_size, "overflow");
|
||||
__ end_a_stub();
|
||||
|
||||
return offset;
|
||||
@ -490,8 +490,7 @@ int LIR_Assembler::emit_deopt_handler() {
|
||||
|
||||
__ pushptr(here.addr());
|
||||
__ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
|
||||
|
||||
assert(code_offset() - offset <= deopt_handler_size, "overflow");
|
||||
guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
|
||||
__ end_a_stub();
|
||||
|
||||
return offset;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -675,3 +675,21 @@ intptr_t *frame::initial_deoptimization_info() {
|
||||
// used to reset the saved FP
|
||||
return fp();
|
||||
}
|
||||
|
||||
intptr_t* frame::real_fp() const {
|
||||
if (_cb != NULL) {
|
||||
// use the frame size if valid
|
||||
int size = _cb->frame_size();
|
||||
if ((size > 0) &&
|
||||
(! is_ricochet_frame())) {
|
||||
// Work-around: ricochet explicitly excluded because frame size is not
|
||||
// constant for the ricochet blob but its frame_size could not, for
|
||||
// some reasons, be declared as <= 0. This potentially confusing
|
||||
// size declaration should be fixed as another CR.
|
||||
return unextended_sp() + size;
|
||||
}
|
||||
}
|
||||
// else rely on fp()
|
||||
assert(! is_compiled_frame(), "unknown compiled frame size");
|
||||
return fp();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -188,6 +188,7 @@
|
||||
frame(intptr_t* sp, intptr_t* fp);
|
||||
|
||||
// accessors for the instance variables
|
||||
// Note: not necessarily the real 'frame pointer' (see real_fp)
|
||||
intptr_t* fp() const { return _fp; }
|
||||
|
||||
inline address* sender_pc_addr() const;
|
||||
|
@ -1005,7 +1005,7 @@ void trace_method_handle_stub(const char* adaptername,
|
||||
intptr_t* base_sp = last_sp;
|
||||
typedef MethodHandles::RicochetFrame RicochetFrame;
|
||||
RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes());
|
||||
if (!UseRicochetFrames || Universe::heap()->is_in((address) rfp->saved_args_base())) {
|
||||
if (Universe::heap()->is_in((address) rfp->saved_args_base())) {
|
||||
// Probably an interpreter frame.
|
||||
base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
|
||||
}
|
||||
@ -1104,7 +1104,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS)
|
||||
//OP_COLLECT_ARGS is below...
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS)
|
||||
|(!UseRicochetFrames ? 0 :
|
||||
|(
|
||||
java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 :
|
||||
((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -72,6 +72,10 @@ inline intptr_t* frame::sender_sp() const {
|
||||
return fp() + 1;
|
||||
}
|
||||
|
||||
inline intptr_t* frame::real_fp() const {
|
||||
return fp();
|
||||
}
|
||||
|
||||
inline intptr_t* frame::link() const {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
@ -29,43 +29,3 @@ enum /* platform_dependent_constants */ {
|
||||
adapter_code_size = 0
|
||||
};
|
||||
|
||||
#define TARGET_ARCH_NYI_6939861 1
|
||||
// ..#ifdef TARGET_ARCH_NYI_6939861
|
||||
// .. // Here are some backward compatible declarations until the 6939861 ports are updated.
|
||||
// .. #define _adapter_flyby (_EK_LIMIT + 10)
|
||||
// .. #define _adapter_ricochet (_EK_LIMIT + 11)
|
||||
// .. #define _adapter_opt_spread_1 _adapter_opt_spread_1_ref
|
||||
// .. #define _adapter_opt_spread_more _adapter_opt_spread_ref
|
||||
// .. enum {
|
||||
// .. _INSERT_NO_MASK = -1,
|
||||
// .. _INSERT_REF_MASK = 0,
|
||||
// .. _INSERT_INT_MASK = 1,
|
||||
// .. _INSERT_LONG_MASK = 3
|
||||
// .. };
|
||||
// .. static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) {
|
||||
// .. arg_type = ek_bound_mh_arg_type(ek);
|
||||
// .. arg_mask = 0;
|
||||
// .. arg_slots = type2size[arg_type];;
|
||||
// .. }
|
||||
// .. static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) {
|
||||
// .. int swap_slots = ek_adapter_opt_swap_slots(ek);
|
||||
// .. rotate = ek_adapter_opt_swap_mode(ek);
|
||||
// .. swap_bytes = swap_slots * Interpreter::stackElementSize;
|
||||
// .. }
|
||||
// .. static int get_ek_adapter_opt_spread_info(EntryKind ek) {
|
||||
// .. return ek_adapter_opt_spread_count(ek);
|
||||
// .. }
|
||||
// ..
|
||||
// .. static void insert_arg_slots(MacroAssembler* _masm,
|
||||
// .. RegisterOrConstant arg_slots,
|
||||
// .. int arg_mask,
|
||||
// .. Register argslot_reg,
|
||||
// .. Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
||||
// ..
|
||||
// .. static void remove_arg_slots(MacroAssembler* _masm,
|
||||
// .. RegisterOrConstant arg_slots,
|
||||
// .. Register argslot_reg,
|
||||
// .. Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
||||
// ..
|
||||
// .. static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
|
||||
// ..#endif //TARGET_ARCH_NYI_6939861
|
||||
|
31
hotspot/src/os/bsd/vm/decoder_machO.cpp
Normal file
31
hotspot/src/os/bsd/vm/decoder_machO.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "decoder_machO.hpp"
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,45 +22,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prims/jvm.h"
|
||||
#include "utilities/decoder.hpp"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#ifndef OS_BSD_VM_DECODER_MACHO_HPP
|
||||
#define OS_BSD_VM_DECODER_MACHO_HPP
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
void Decoder::initialize() {
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void Decoder::uninitialize() {
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
bool Decoder::can_decode_C_frame_in_vm() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
|
||||
return symbol_not_found;
|
||||
}
|
||||
#include "utilities/decoder.hpp"
|
||||
|
||||
// Just a placehold for now
|
||||
class MachODecoder: public NullDecoder {
|
||||
public:
|
||||
MachODecoder() { }
|
||||
~MachODecoder() { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
int status;
|
||||
char* result;
|
||||
size_t size = (size_t)buflen;
|
||||
#endif // OS_BSD_VM_DECODER_MACHO_HPP
|
||||
|
||||
// Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
|
||||
// __cxa_demangle will call system "realloc" for additional memory, which
|
||||
// may use different malloc/realloc mechanism that allocates 'buf'.
|
||||
if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
|
||||
jio_snprintf(buf, buflen, "%s", result);
|
||||
// call c library's free
|
||||
::free(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1920,7 +1920,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
return true;
|
||||
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,11 @@
|
||||
*/
|
||||
|
||||
#include "prims/jvm.h"
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "utilities/decoder_elf.hpp"
|
||||
|
||||
#include <cxxabi.h>
|
||||
|
||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
int status;
|
||||
char* result;
|
||||
size_t size = (size_t)buflen;
|
||||
@ -43,3 +43,4 @@ bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1732,7 +1732,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
return true;
|
||||
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "utilities/decoder_elf.hpp"
|
||||
|
||||
#include <demangle.h>
|
||||
|
||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
return !cplus_demangle(symbol, buf, (size_t)buflen);
|
||||
}
|
||||
|
||||
|
@ -1997,7 +1997,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
}
|
||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2015,7 +2015,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
return true;
|
||||
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,22 +24,24 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "prims/jvm.h"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "decoder_windows.hpp"
|
||||
|
||||
HMODULE Decoder::_dbghelp_handle = NULL;
|
||||
bool Decoder::_can_decode_in_vm = false;
|
||||
pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL;
|
||||
pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL;
|
||||
WindowsDecoder::WindowsDecoder() {
|
||||
_dbghelp_handle = NULL;
|
||||
_can_decode_in_vm = false;
|
||||
_pfnSymGetSymFromAddr64 = NULL;
|
||||
_pfnUndecorateSymbolName = NULL;
|
||||
|
||||
void Decoder::initialize() {
|
||||
if (!_initialized) {
|
||||
_initialized = true;
|
||||
_decoder_status = no_error;
|
||||
initialize();
|
||||
}
|
||||
|
||||
HINSTANCE handle = os::win32::load_Windows_dll("dbghelp.dll", NULL, 0);
|
||||
void WindowsDecoder::initialize() {
|
||||
if (!has_error() && _dbghelp_handle == NULL) {
|
||||
HMODULE handle = ::LoadLibrary("dbghelp.dll");
|
||||
if (!handle) {
|
||||
_decoder_status = helper_not_found;
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
_dbghelp_handle = handle;
|
||||
@ -70,32 +72,29 @@ void Decoder::initialize() {
|
||||
|
||||
// find out if jvm.dll contains private symbols, by decoding
|
||||
// current function and comparing the result
|
||||
address addr = (address)Decoder::initialize;
|
||||
address addr = (address)Decoder::decode;
|
||||
char buf[MAX_PATH];
|
||||
if (decode(addr, buf, sizeof(buf), NULL) == no_error) {
|
||||
_can_decode_in_vm = !strcmp(buf, "Decoder::initialize");
|
||||
if (decode(addr, buf, sizeof(buf), NULL)) {
|
||||
_can_decode_in_vm = !strcmp(buf, "Decoder::decode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decoder::uninitialize() {
|
||||
assert(_initialized, "Decoder not yet initialized");
|
||||
void WindowsDecoder::uninitialize() {
|
||||
_pfnSymGetSymFromAddr64 = NULL;
|
||||
_pfnUndecorateSymbolName = NULL;
|
||||
if (_dbghelp_handle != NULL) {
|
||||
::FreeLibrary(_dbghelp_handle);
|
||||
}
|
||||
_initialized = false;
|
||||
_dbghelp_handle = NULL;
|
||||
}
|
||||
|
||||
bool Decoder::can_decode_C_frame_in_vm() {
|
||||
initialize();
|
||||
return _can_decode_in_vm;
|
||||
bool WindowsDecoder::can_decode_C_frame_in_vm() const {
|
||||
return (!has_error() && _can_decode_in_vm);
|
||||
}
|
||||
|
||||
|
||||
Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) {
|
||||
assert(_initialized, "Decoder not yet initialized");
|
||||
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
|
||||
if (_pfnSymGetSymFromAddr64 != NULL) {
|
||||
PIMAGEHLP_SYMBOL64 pSymbol;
|
||||
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
||||
@ -105,19 +104,20 @@ Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int
|
||||
DWORD64 displacement;
|
||||
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
||||
if (buf != NULL) {
|
||||
if (!demangle(pSymbol->Name, buf, buflen)) {
|
||||
if (demangle(pSymbol->Name, buf, buflen)) {
|
||||
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
||||
}
|
||||
}
|
||||
if (offset != NULL) *offset = (int)displacement;
|
||||
return no_error;
|
||||
if(offset != NULL) *offset = (int)displacement;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return helper_not_found;
|
||||
if (buf != NULL && buflen > 0) buf[0] = '\0';
|
||||
if (offset != NULL) *offset = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
assert(_initialized, "Decoder not yet initialized");
|
||||
bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||
return _pfnUndecorateSymbolName != NULL &&
|
||||
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
|
||||
}
|
||||
|
61
hotspot/src/os/windows/vm/decoder_windows.hpp
Normal file
61
hotspot/src/os/windows/vm/decoder_windows.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP
|
||||
#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP
|
||||
|
||||
#include <windows.h>
|
||||
#include <imagehlp.h>
|
||||
|
||||
#include "utilities/decoder.hpp"
|
||||
|
||||
// functions needed for decoding symbols
|
||||
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
|
||||
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
|
||||
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
|
||||
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
|
||||
|
||||
class WindowsDecoder: public NullDecoder {
|
||||
|
||||
public:
|
||||
WindowsDecoder();
|
||||
~WindowsDecoder() { uninitialize(); };
|
||||
|
||||
bool can_decode_C_frame_in_vm() const;
|
||||
bool demangle(const char* symbol, char *buf, int buflen);
|
||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL);
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
void uninitialize();
|
||||
|
||||
private:
|
||||
HMODULE _dbghelp_handle;
|
||||
bool _can_decode_in_vm;
|
||||
pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
||||
pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
|
||||
};
|
||||
|
||||
#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP
|
||||
|
@ -1391,7 +1391,7 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int *offset) {
|
||||
if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) {
|
||||
if (Decoder::decode(addr, buf, buflen, offset)) {
|
||||
return true;
|
||||
}
|
||||
if (offset != NULL) *offset = -1;
|
||||
|
@ -204,6 +204,24 @@ Symbol* SymbolTable::lookup_only(const char* name, int len,
|
||||
return s;
|
||||
}
|
||||
|
||||
// Look up the address of the literal in the SymbolTable for this Symbol*
|
||||
// Do not create any new symbols
|
||||
// Do not increment the reference count to keep this alive
|
||||
Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){
|
||||
unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length());
|
||||
int index = the_table()->hash_to_index(hash);
|
||||
|
||||
for (HashtableEntry<Symbol*>* e = the_table()->bucket(index); e != NULL; e = e->next()) {
|
||||
if (e->hash() == hash) {
|
||||
Symbol* literal_sym = e->literal();
|
||||
if (sym == literal_sym) {
|
||||
return e->literal_addr();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Suggestion: Push unicode-based lookup all the way into the hashing
|
||||
// and probing logic, so there is no need for convert_to_utf8 until
|
||||
// an actual new Symbol* is created.
|
||||
|
@ -144,6 +144,9 @@ public:
|
||||
|
||||
static void release(Symbol* sym);
|
||||
|
||||
// Look up the address of the literal in the SymbolTable for this Symbol*
|
||||
static Symbol** lookup_symbol_addr(Symbol* sym);
|
||||
|
||||
// jchar (utf16) version of lookups
|
||||
static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
|
||||
static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
|
||||
|
@ -2131,6 +2131,12 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
|
||||
}
|
||||
}
|
||||
|
||||
// Assign a classid if one has not already been assigned. The
|
||||
// counter does not need to be atomically incremented since this
|
||||
// is only done while holding the SystemDictionary_lock.
|
||||
// All loaded classes get a unique ID.
|
||||
TRACE_INIT_ID(k);
|
||||
|
||||
// Check for a placeholder. If there, remove it and make a
|
||||
// new system dictionary entry.
|
||||
placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD);
|
||||
|
@ -158,6 +158,9 @@ klassOop Klass::base_create_klass_oop(KlassHandle& klass, int size,
|
||||
kl->set_next_sibling(NULL);
|
||||
kl->set_alloc_count(0);
|
||||
kl->set_alloc_size(0);
|
||||
#ifdef TRACE_SET_KLASS_TRACE_ID
|
||||
TRACE_SET_KLASS_TRACE_ID(kl, 0);
|
||||
#endif
|
||||
|
||||
kl->set_prototype_header(markOopDesc::prototype());
|
||||
kl->set_biased_lock_revocation_count(0);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "oops/klassPS.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "runtime/orderAccess.hpp"
|
||||
#include "trace/traceMacros.hpp"
|
||||
#include "utilities/accessFlags.hpp"
|
||||
#ifndef SERIALGC
|
||||
#include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
|
||||
@ -80,6 +81,7 @@
|
||||
// [last_biased_lock_bulk_revocation_time] (64 bits)
|
||||
// [prototype_header]
|
||||
// [biased_lock_revocation_count]
|
||||
// [trace_id]
|
||||
|
||||
|
||||
// Forward declarations.
|
||||
@ -263,6 +265,9 @@ class Klass : public Klass_vtbl {
|
||||
markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type
|
||||
jint _biased_lock_revocation_count;
|
||||
|
||||
#ifdef TRACE_DEFINE_KLASS_TRACE_ID
|
||||
TRACE_DEFINE_KLASS_TRACE_ID;
|
||||
#endif
|
||||
public:
|
||||
|
||||
// returns the enclosing klassOop
|
||||
@ -683,6 +688,9 @@ class Klass : public Klass_vtbl {
|
||||
jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; }
|
||||
void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; }
|
||||
|
||||
#ifdef TRACE_DEFINE_KLASS_METHODS
|
||||
TRACE_DEFINE_KLASS_METHODS;
|
||||
#endif
|
||||
|
||||
// garbage collection support
|
||||
virtual void follow_weak_klass_links(
|
||||
|
@ -83,6 +83,7 @@ methodOop methodKlass::allocate(constMethodHandle xconst,
|
||||
m->set_max_stack(0);
|
||||
m->set_max_locals(0);
|
||||
m->set_intrinsic_id(vmIntrinsics::_none);
|
||||
m->set_jfr_towrite(false);
|
||||
m->set_method_data(NULL);
|
||||
m->set_interpreter_throwout_count(0);
|
||||
m->set_vtable_index(methodOopDesc::garbage_vtable_index);
|
||||
|
@ -77,7 +77,7 @@
|
||||
// | method_size | max_stack |
|
||||
// | max_locals | size_of_parameters |
|
||||
// |------------------------------------------------------|
|
||||
// | intrinsic_id, (unused) | throwout_count |
|
||||
// |intrinsic_id| flags | throwout_count |
|
||||
// |------------------------------------------------------|
|
||||
// | num_breakpoints | (unused) |
|
||||
// |------------------------------------------------------|
|
||||
@ -124,6 +124,8 @@ class methodOopDesc : public oopDesc {
|
||||
u2 _max_locals; // Number of local variables used by this method
|
||||
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
||||
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
|
||||
u1 _jfr_towrite : 1, // Flags
|
||||
: 7;
|
||||
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
|
||||
u2 _number_of_breakpoints; // fullspeed debugging support
|
||||
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
|
||||
@ -225,6 +227,7 @@ class methodOopDesc : public oopDesc {
|
||||
void clear_number_of_breakpoints() { _number_of_breakpoints = 0; }
|
||||
|
||||
// index into instanceKlass methods() array
|
||||
// note: also used by jfr
|
||||
u2 method_idnum() const { return constMethod()->method_idnum(); }
|
||||
void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); }
|
||||
|
||||
@ -650,6 +653,9 @@ class methodOopDesc : public oopDesc {
|
||||
void init_intrinsic_id(); // updates from _none if a match
|
||||
static vmSymbols::SID klass_id_for_intrinsics(klassOop holder);
|
||||
|
||||
bool jfr_towrite() { return _jfr_towrite; }
|
||||
void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
|
||||
|
||||
// On-stack replacement support
|
||||
bool has_osr_nmethod(int level, bool match_level) {
|
||||
return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "oops/typeArrayOop.hpp"
|
||||
#include "prims/jni.h"
|
||||
#include "prims/jniCheck.hpp"
|
||||
#include "prims/jniExport.hpp"
|
||||
#include "prims/jniFastGetField.hpp"
|
||||
#include "prims/jvm.h"
|
||||
#include "prims/jvm_misc.hpp"
|
||||
@ -66,6 +67,8 @@
|
||||
#include "runtime/signature.hpp"
|
||||
#include "runtime/vm_operations.hpp"
|
||||
#include "services/runtimeService.hpp"
|
||||
#include "trace/tracing.hpp"
|
||||
#include "trace/traceEventTypes.hpp"
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/dtrace.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
@ -5139,6 +5142,11 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v
|
||||
if (JvmtiExport::should_post_thread_life()) {
|
||||
JvmtiExport::post_thread_start(thread);
|
||||
}
|
||||
|
||||
EVENT_BEGIN(TraceEventThreadStart, event);
|
||||
EVENT_COMMIT(event,
|
||||
EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj())));
|
||||
|
||||
// Check if we should compile all classes on bootclasspath
|
||||
NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();)
|
||||
// Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
|
||||
@ -5337,6 +5345,10 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
|
||||
JvmtiExport::post_thread_start(thread);
|
||||
}
|
||||
|
||||
EVENT_BEGIN(TraceEventThreadStart, event);
|
||||
EVENT_COMMIT(event,
|
||||
EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj())));
|
||||
|
||||
*(JNIEnv**)penv = thread->jni_environment();
|
||||
|
||||
// Now leaving the VM, so change thread_state. This is normally automatically taken care
|
||||
@ -5464,8 +5476,7 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (JvmtiExport::is_jvmti_version(version)) {
|
||||
ret = JvmtiExport::get_jvmti_interface(vm, penv, version);
|
||||
if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
42
hotspot/src/share/vm/prims/jniExport.hpp
Normal file
42
hotspot/src/share/vm/prims/jniExport.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_PRIMS_JNI_EXPORT_HPP
|
||||
#define SHARE_VM_PRIMS_JNI_EXPORT_HPP
|
||||
|
||||
#include "prims/jni.h"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
|
||||
class JniExportedInterface {
|
||||
public:
|
||||
static bool GetExportedInterface(JavaVM* vm, void** penv, jint version, jint* iface) {
|
||||
if (JvmtiExport::is_jvmti_version(version)) {
|
||||
*iface = JvmtiExport::get_jvmti_interface(vm, penv, version);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_PRIMS_JNI_EXPORT_HPP
|
@ -194,9 +194,6 @@ bool MethodHandles::spot_check_entry_names() {
|
||||
// MethodHandles::generate_adapters
|
||||
//
|
||||
void MethodHandles::generate_adapters() {
|
||||
#ifdef TARGET_ARCH_NYI_6939861
|
||||
if (FLAG_IS_DEFAULT(UseRicochetFrames)) UseRicochetFrames = false;
|
||||
#endif
|
||||
if (!EnableInvokeDynamic || SystemDictionary::MethodHandle_klass() == NULL) return;
|
||||
|
||||
assert(_adapter_code == NULL, "generate only once");
|
||||
@ -230,18 +227,6 @@ void MethodHandlesAdapterGenerator::generate() {
|
||||
}
|
||||
|
||||
|
||||
#ifdef TARGET_ARCH_NYI_6939861
|
||||
// these defs belong in methodHandles_<arch>.cpp
|
||||
frame MethodHandles::ricochet_frame_sender(const frame& fr, RegisterMap *map) {
|
||||
ShouldNotCallThis();
|
||||
return fr;
|
||||
}
|
||||
void MethodHandles::ricochet_frame_oops_do(const frame& fr, OopClosure* f, const RegisterMap* reg_map) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
#endif //TARGET_ARCH_NYI_6939861
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MethodHandles::ek_supported
|
||||
//
|
||||
@ -251,28 +236,11 @@ bool MethodHandles::ek_supported(MethodHandles::EntryKind ek) {
|
||||
case _adapter_unused_13:
|
||||
return false; // not defined yet
|
||||
case _adapter_prim_to_ref:
|
||||
return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF);
|
||||
return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF);
|
||||
case _adapter_collect_args:
|
||||
return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS);
|
||||
return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS);
|
||||
case _adapter_fold_args:
|
||||
return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS);
|
||||
case _adapter_opt_return_any:
|
||||
return UseRicochetFrames;
|
||||
#ifdef TARGET_ARCH_NYI_6939861
|
||||
// ports before 6939861 supported only three kinds of spread ops
|
||||
case _adapter_spread_args:
|
||||
// restrict spreads to three kinds:
|
||||
switch (ek) {
|
||||
case _adapter_opt_spread_0:
|
||||
case _adapter_opt_spread_1:
|
||||
case _adapter_opt_spread_more:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif //TARGET_ARCH_NYI_6939861
|
||||
return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1988,9 +1956,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
||||
case _adapter_prim_to_ref: // boxer MH to use
|
||||
case _adapter_collect_args: // method handle which collects the args
|
||||
case _adapter_fold_args: // method handle which collects the args
|
||||
if (!UseRicochetFrames) {
|
||||
{ err = "box/collect/fold operators are not supported"; break; }
|
||||
}
|
||||
if (!java_lang_invoke_MethodHandle::is_instance(argument()))
|
||||
{ err = "MethodHandle adapter argument required"; break; }
|
||||
arg_mtype = Handle(THREAD, java_lang_invoke_MethodHandle::type(argument()));
|
||||
@ -2370,7 +2335,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
|
||||
case _adapter_prim_to_ref:
|
||||
{
|
||||
assert(UseRicochetFrames, "else don't come here");
|
||||
// vminfo will be the location to insert the return value
|
||||
vminfo = argslot;
|
||||
ek_opt = _adapter_opt_collect_ref;
|
||||
@ -2436,20 +2400,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
|
||||
case _adapter_spread_args:
|
||||
{
|
||||
#ifdef TARGET_ARCH_NYI_6939861
|
||||
// ports before 6939861 supported only three kinds of spread ops
|
||||
if (!UseRicochetFrames) {
|
||||
int array_size = slots_pushed + 1;
|
||||
assert(array_size >= 0, "");
|
||||
vminfo = array_size;
|
||||
switch (array_size) {
|
||||
case 0: ek_opt = _adapter_opt_spread_0; break;
|
||||
case 1: ek_opt = _adapter_opt_spread_1; break;
|
||||
default: ek_opt = _adapter_opt_spread_more; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif //TARGET_ARCH_NYI_6939861
|
||||
// vminfo will be the required length of the array
|
||||
int array_size = (slots_pushed + 1) / (type2size[dest] == 2 ? 2 : 1);
|
||||
vminfo = array_size;
|
||||
@ -2494,7 +2444,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
|
||||
case _adapter_collect_args:
|
||||
{
|
||||
assert(UseRicochetFrames, "else don't come here");
|
||||
int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument()));
|
||||
// vminfo will be the location to insert the return value
|
||||
vminfo = argslot;
|
||||
@ -2563,7 +2512,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
|
||||
case _adapter_fold_args:
|
||||
{
|
||||
assert(UseRicochetFrames, "else don't come here");
|
||||
int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument()));
|
||||
// vminfo will be the location to insert the return value
|
||||
vminfo = argslot + elem_slots;
|
||||
|
@ -738,46 +738,6 @@ public:
|
||||
#ifdef TARGET_ARCH_ppc
|
||||
# include "methodHandles_ppc.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_ARCH_NYI_6939861
|
||||
// Here are some backward compatible declarations until the 6939861 ports are updated.
|
||||
#define _adapter_flyby (_EK_LIMIT + 10)
|
||||
#define _adapter_ricochet (_EK_LIMIT + 11)
|
||||
#define _adapter_opt_spread_1 _adapter_opt_spread_1_ref
|
||||
#define _adapter_opt_spread_more _adapter_opt_spread_ref
|
||||
enum {
|
||||
_INSERT_NO_MASK = -1,
|
||||
_INSERT_REF_MASK = 0,
|
||||
_INSERT_INT_MASK = 1,
|
||||
_INSERT_LONG_MASK = 3
|
||||
};
|
||||
static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) {
|
||||
arg_type = ek_bound_mh_arg_type(ek);
|
||||
arg_mask = 0;
|
||||
arg_slots = type2size[arg_type];;
|
||||
}
|
||||
static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) {
|
||||
int swap_slots = ek_adapter_opt_swap_slots(ek);
|
||||
rotate = ek_adapter_opt_swap_mode(ek);
|
||||
swap_bytes = swap_slots * Interpreter::stackElementSize;
|
||||
}
|
||||
static int get_ek_adapter_opt_spread_info(EntryKind ek) {
|
||||
return ek_adapter_opt_spread_count(ek);
|
||||
}
|
||||
|
||||
static void insert_arg_slots(MacroAssembler* _masm,
|
||||
RegisterOrConstant arg_slots,
|
||||
int arg_mask,
|
||||
Register argslot_reg,
|
||||
Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
||||
|
||||
static void remove_arg_slots(MacroAssembler* _masm,
|
||||
RegisterOrConstant arg_slots,
|
||||
Register argslot_reg,
|
||||
Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
||||
|
||||
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
|
||||
#endif //TARGET_ARCH_NYI_6939861
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1334,24 +1334,21 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
|
||||
|
||||
|
||||
void frame::describe(FrameValues& values, int frame_no) {
|
||||
intptr_t* frame_pointer = real_fp();
|
||||
if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) {
|
||||
// Label values common to most frames
|
||||
values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no));
|
||||
values.describe(-1, sp(), err_msg("sp for #%d", frame_no));
|
||||
if (is_compiled_frame()) {
|
||||
values.describe(-1, sp() + _cb->frame_size(), err_msg("computed fp for #%d", frame_no));
|
||||
} else {
|
||||
values.describe(-1, fp(), err_msg("fp for #%d", frame_no));
|
||||
}
|
||||
values.describe(-1, frame_pointer, err_msg("frame pointer for #%d", frame_no));
|
||||
}
|
||||
if (is_interpreted_frame()) {
|
||||
methodOop m = interpreter_frame_method();
|
||||
int bci = interpreter_frame_bci();
|
||||
|
||||
// Label the method and current bci
|
||||
values.describe(-1, MAX2(sp(), fp()),
|
||||
values.describe(-1, MAX2(sp(), frame_pointer),
|
||||
FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2);
|
||||
values.describe(-1, MAX2(sp(), fp()),
|
||||
values.describe(-1, MAX2(sp(), frame_pointer),
|
||||
err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1);
|
||||
if (m->max_locals() > 0) {
|
||||
intptr_t* l0 = interpreter_frame_local_at(0);
|
||||
@ -1383,18 +1380,18 @@ void frame::describe(FrameValues& values, int frame_no) {
|
||||
}
|
||||
} else if (is_entry_frame()) {
|
||||
// For now just label the frame
|
||||
values.describe(-1, MAX2(sp(), fp()), err_msg("#%d entry frame", frame_no), 2);
|
||||
values.describe(-1, MAX2(sp(), frame_pointer), err_msg("#%d entry frame", frame_no), 2);
|
||||
} else if (is_compiled_frame()) {
|
||||
// For now just label the frame
|
||||
nmethod* nm = cb()->as_nmethod_or_null();
|
||||
values.describe(-1, MAX2(sp(), fp()),
|
||||
values.describe(-1, MAX2(sp(), frame_pointer),
|
||||
FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no,
|
||||
nm, nm->method()->name_and_sig_as_C_string(),
|
||||
is_deoptimized_frame() ? " (deoptimized" : ""), 2);
|
||||
} else if (is_native_frame()) {
|
||||
// For now just label the frame
|
||||
nmethod* nm = cb()->as_nmethod_or_null();
|
||||
values.describe(-1, MAX2(sp(), fp()),
|
||||
values.describe(-1, MAX2(sp(), frame_pointer),
|
||||
FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no,
|
||||
nm, nm->method()->name_and_sig_as_C_string()), 2);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -221,6 +221,15 @@ class frame VALUE_OBJ_CLASS_SPEC {
|
||||
// returns the stack pointer of the calling frame
|
||||
intptr_t* sender_sp() const;
|
||||
|
||||
// Returns the real 'frame pointer' for the current frame.
|
||||
// This is the value expected by the platform ABI when it defines a
|
||||
// frame pointer register. It may differ from the effective value of
|
||||
// the FP register when that register is used in the JVM for other
|
||||
// purposes (like compiled frames on some platforms).
|
||||
// On other platforms, it is defined so that the stack area used by
|
||||
// this frame goes from real_fp() to sp().
|
||||
intptr_t* real_fp() const;
|
||||
|
||||
// Deoptimization info, if needed (platform dependent).
|
||||
// Stored in the initial_info field of the unroll info, to be used by
|
||||
// the platform dependent deoptimization blobs.
|
||||
|
@ -3826,10 +3826,6 @@ class CommandLineFlags {
|
||||
develop(bool, StressMethodHandleWalk, false, \
|
||||
"Process all method handles with MethodHandleWalk") \
|
||||
\
|
||||
diagnostic(bool, UseRicochetFrames, true, \
|
||||
"use ricochet stack frames for method handle combination, " \
|
||||
"if the platform supports them") \
|
||||
\
|
||||
experimental(bool, TrustFinalNonStaticFields, false, \
|
||||
"trust final non-static declarations for constant folding") \
|
||||
\
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "runtime/task.hpp"
|
||||
#include "runtime/timer.hpp"
|
||||
#include "runtime/vm_operations.hpp"
|
||||
#include "trace/tracing.hpp"
|
||||
#include "trace/traceEventTypes.hpp"
|
||||
#include "utilities/dtrace.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/histogram.hpp"
|
||||
@ -502,6 +504,11 @@ void before_exit(JavaThread * thread) {
|
||||
if (JvmtiExport::should_post_thread_life()) {
|
||||
JvmtiExport::post_thread_end(thread);
|
||||
}
|
||||
|
||||
EVENT_BEGIN(TraceEventThreadEnd, event);
|
||||
EVENT_COMMIT(event,
|
||||
EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj())));
|
||||
|
||||
// Always call even when there are not JVMTI environments yet, since environments
|
||||
// may be attached late and JVMTI must track phases of VM execution
|
||||
JvmtiExport::post_vm_death();
|
||||
|
@ -132,7 +132,13 @@ Mutex* HotCardCache_lock = NULL;
|
||||
Monitor* GCTaskManager_lock = NULL;
|
||||
|
||||
Mutex* Management_lock = NULL;
|
||||
Monitor* Service_lock = NULL;
|
||||
Monitor* Service_lock = NULL;
|
||||
Mutex* Stacktrace_lock = NULL;
|
||||
|
||||
Monitor* JfrQuery_lock = NULL;
|
||||
Monitor* JfrMsg_lock = NULL;
|
||||
Mutex* JfrBuffer_lock = NULL;
|
||||
Mutex* JfrStream_lock = NULL;
|
||||
|
||||
#define MAX_NUM_MUTEX 128
|
||||
static Monitor * _mutex_array[MAX_NUM_MUTEX];
|
||||
@ -207,6 +213,7 @@ void mutex_init() {
|
||||
def(Patching_lock , Mutex , special, true ); // used for safepointing and code patching.
|
||||
def(ObjAllocPost_lock , Monitor, special, false);
|
||||
def(Service_lock , Monitor, special, true ); // used for service thread operations
|
||||
def(Stacktrace_lock , Mutex, special, true ); // used for JFR stacktrace database
|
||||
def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs.
|
||||
|
||||
def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread
|
||||
@ -271,6 +278,11 @@ void mutex_init() {
|
||||
def(Debug3_lock , Mutex , nonleaf+4, true );
|
||||
def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread
|
||||
def(CompileThread_lock , Monitor, nonleaf+5, false );
|
||||
|
||||
def(JfrQuery_lock , Monitor, nonleaf, true); // JFR locks, keep these in consecutive order
|
||||
def(JfrMsg_lock , Monitor, nonleaf+2, true);
|
||||
def(JfrBuffer_lock , Mutex, nonleaf+3, true);
|
||||
def(JfrStream_lock , Mutex, nonleaf+4, true);
|
||||
}
|
||||
|
||||
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
|
||||
|
@ -135,6 +135,12 @@ extern Mutex* HotCardCache_lock; // protects the hot card cache
|
||||
|
||||
extern Mutex* Management_lock; // a lock used to serialize JVM management
|
||||
extern Monitor* Service_lock; // a lock used for service thread operation
|
||||
extern Mutex* Stacktrace_lock; // used to guard access to the stacktrace table
|
||||
|
||||
extern Monitor* JfrQuery_lock; // protects JFR use
|
||||
extern Monitor* JfrMsg_lock; // protects JFR messaging
|
||||
extern Mutex* JfrBuffer_lock; // protects JFR buffer operations
|
||||
extern Mutex* JfrStream_lock; // protects JFR stream access
|
||||
|
||||
// A MutexLocker provides mutual exclusion with respect to a given mutex
|
||||
// for the scope which contains the locker. The lock is an OS lock, not
|
||||
|
@ -1101,6 +1101,7 @@ bool os::set_boot_path(char fileSep, char pathSep) {
|
||||
"%/lib/jsse.jar:"
|
||||
"%/lib/jce.jar:"
|
||||
"%/lib/charsets.jar:"
|
||||
"%/lib/jfr.jar:"
|
||||
#ifdef __APPLE__
|
||||
"%/lib/JObjC.jar:"
|
||||
#endif
|
||||
|
@ -121,7 +121,6 @@ void SharedRuntime::generate_stubs() {
|
||||
void SharedRuntime::generate_ricochet_blob() {
|
||||
if (!EnableInvokeDynamic) return; // leave it as a null
|
||||
|
||||
#ifndef TARGET_ARCH_NYI_6939861
|
||||
// allocate space for the code
|
||||
ResourceMark rm;
|
||||
// setup code generation tools
|
||||
@ -142,7 +141,6 @@ void SharedRuntime::generate_ricochet_blob() {
|
||||
}
|
||||
|
||||
_ricochet_blob = RicochetBlob::create(&buffer, bounce_offset, exception_offset, frame_size_in_words);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "services/attachListener.hpp"
|
||||
#include "services/management.hpp"
|
||||
#include "services/threadService.hpp"
|
||||
#include "trace/traceEventTypes.hpp"
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/dtrace.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
@ -232,6 +233,7 @@ Thread::Thread() {
|
||||
CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
|
||||
_jvmti_env_iteration_count = 0;
|
||||
set_allocated_bytes(0);
|
||||
set_trace_buffer(NULL);
|
||||
_vm_operation_started_count = 0;
|
||||
_vm_operation_completed_count = 0;
|
||||
_current_pending_monitor = NULL;
|
||||
@ -1512,6 +1514,10 @@ void JavaThread::run() {
|
||||
JvmtiExport::post_thread_start(this);
|
||||
}
|
||||
|
||||
EVENT_BEGIN(TraceEventThreadStart, event);
|
||||
EVENT_COMMIT(event,
|
||||
EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj())));
|
||||
|
||||
// We call another function to do the rest so we are sure that the stack addresses used
|
||||
// from there will be lower than the stack base just computed
|
||||
thread_main_inner();
|
||||
@ -1641,6 +1647,15 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Called before the java thread exit since we want to read info
|
||||
// from java_lang_Thread object
|
||||
EVENT_BEGIN(TraceEventThreadEnd, event);
|
||||
EVENT_COMMIT(event,
|
||||
EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj())));
|
||||
|
||||
// Call after last event on thread
|
||||
EVENT_THREAD_EXIT(this);
|
||||
|
||||
// Call Thread.exit(). We try 3 times in case we got another Thread.stop during
|
||||
// the execution of the method. If that is not enough, then we don't really care. Thread.stop
|
||||
// is deprecated anyhow.
|
||||
@ -3186,6 +3201,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Must be run after init_ft which initializes ft_enabled
|
||||
if (TRACE_INITIALIZE() != JNI_OK) {
|
||||
vm_exit_during_initialization("Failed to initialize tracing backend");
|
||||
}
|
||||
|
||||
// Should be done after the heap is fully created
|
||||
main_thread->cache_global_variables();
|
||||
|
||||
@ -3423,6 +3443,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
create_vm_init_libraries();
|
||||
}
|
||||
|
||||
if (!TRACE_START()) {
|
||||
vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
|
||||
}
|
||||
|
||||
// Notify JVMTI agents that VM initialization is complete - nop if no agents.
|
||||
JvmtiExport::post_vm_initialized();
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/threadLocalStorage.hpp"
|
||||
#include "runtime/unhandledOops.hpp"
|
||||
#include "trace/tracing.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
#include "utilities/top.hpp"
|
||||
#ifndef SERIALGC
|
||||
@ -246,6 +247,8 @@ class Thread: public ThreadShadow {
|
||||
jlong _allocated_bytes; // Cumulative number of bytes allocated on
|
||||
// the Java heap
|
||||
|
||||
TRACE_BUFFER _trace_buffer; // Thread-local buffer for tracing
|
||||
|
||||
int _vm_operation_started_count; // VM_Operation support
|
||||
int _vm_operation_completed_count; // VM_Operation support
|
||||
|
||||
@ -414,6 +417,9 @@ class Thread: public ThreadShadow {
|
||||
return allocated_bytes;
|
||||
}
|
||||
|
||||
TRACE_BUFFER trace_buffer() { return _trace_buffer; }
|
||||
void set_trace_buffer(TRACE_BUFFER buf) { _trace_buffer = buf; }
|
||||
|
||||
// VM operation support
|
||||
int vm_operation_ticket() { return ++_vm_operation_started_count; }
|
||||
int vm_operation_completed_count() { return _vm_operation_completed_count; }
|
||||
|
@ -93,6 +93,7 @@
|
||||
template(HeapWalkOperation) \
|
||||
template(HeapIterateOperation) \
|
||||
template(ReportJavaOutOfMemory) \
|
||||
template(JFRCheckpoint) \
|
||||
template(Exit) \
|
||||
|
||||
class VM_Operation: public CHeapObj {
|
||||
|
30
hotspot/src/share/vm/trace/traceEventTypes.hpp
Normal file
30
hotspot/src/share/vm/trace/traceEventTypes.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP
|
||||
#define SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP
|
||||
|
||||
/* Empty, just a placeholder for tracing events */
|
||||
|
||||
#endif
|
43
hotspot/src/share/vm/trace/traceMacros.hpp
Normal file
43
hotspot/src/share/vm/trace/traceMacros.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_TRACE_TRACE_MACRO_HPP
|
||||
#define SHARE_VM_TRACE_TRACE_MACRO_HPP
|
||||
|
||||
#define EVENT_BEGIN(type, name)
|
||||
#define EVENT_SET(name, field, value)
|
||||
#define EVENT_COMMIT(name, ...)
|
||||
#define EVENT_STARTED(name, time)
|
||||
#define EVENT_ENDED(name, time)
|
||||
#define EVENT_THREAD_EXIT(thread)
|
||||
|
||||
#define TRACE_ENABLED 0
|
||||
|
||||
#define TRACE_INIT_ID(k)
|
||||
#define TRACE_BUFFER void*
|
||||
|
||||
#define TRACE_START() true
|
||||
#define TRACE_INITIALIZE() 0
|
||||
|
||||
#endif
|
30
hotspot/src/share/vm/trace/tracing.hpp
Normal file
30
hotspot/src/share/vm/trace/tracing.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_TRACE_TRACING_HPP
|
||||
#define SHARE_VM_TRACE_TRACING_HPP
|
||||
|
||||
#include "trace/traceMacros.hpp"
|
||||
|
||||
#endif
|
@ -24,80 +24,85 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "prims/jvm.h"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "utilities/decoder.hpp"
|
||||
|
||||
Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error;
|
||||
bool Decoder::_initialized = false;
|
||||
#if defined(_WINDOWS)
|
||||
#include "decoder_windows.hpp"
|
||||
#elif defined(__APPLE__)
|
||||
#include "decoder_machO.hpp"
|
||||
#else
|
||||
#include "decoder_elf.hpp"
|
||||
#endif
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
NullDecoder* Decoder::_decoder = NULL;
|
||||
NullDecoder Decoder::_do_nothing_decoder;
|
||||
Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint,
|
||||
"DecoderLock");
|
||||
|
||||
// Implementation of common functionalities among Solaris and Linux
|
||||
#include "utilities/elfFile.hpp"
|
||||
// _decoder_lock should already acquired before enter this method
|
||||
NullDecoder* Decoder::get_decoder() {
|
||||
assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(),
|
||||
"Require DecoderLock to enter");
|
||||
|
||||
ElfFile* Decoder::_opened_elf_files = NULL;
|
||||
if (_decoder != NULL) {
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
// Decoder is a secondary service. Although, it is good to have,
|
||||
// but we can live without it.
|
||||
#if defined(_WINDOWS)
|
||||
_decoder = new (std::nothrow) WindowsDecoder();
|
||||
#elif defined (__APPLE__)
|
||||
_decoder = new (std::nothrow)MachODecoder();
|
||||
#else
|
||||
_decoder = new (std::nothrow)ElfDecoder();
|
||||
#endif
|
||||
|
||||
if (_decoder == NULL || _decoder->has_error()) {
|
||||
if (_decoder != NULL) {
|
||||
delete _decoder;
|
||||
}
|
||||
_decoder = &_do_nothing_decoder;
|
||||
}
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
||||
assert(_decoder_lock != NULL, "Just check");
|
||||
MutexLockerEx locker(_decoder_lock, true);
|
||||
NullDecoder* decoder = get_decoder();
|
||||
assert(decoder != NULL, "null decoder");
|
||||
|
||||
return decoder->decode(addr, buf, buflen, offset, modulepath);
|
||||
}
|
||||
|
||||
bool Decoder::demangle(const char* symbol, char* buf, int buflen) {
|
||||
assert(_decoder_lock != NULL, "Just check");
|
||||
MutexLockerEx locker(_decoder_lock, true);
|
||||
NullDecoder* decoder = get_decoder();
|
||||
assert(decoder != NULL, "null decoder");
|
||||
return decoder->demangle(symbol, buf, buflen);
|
||||
}
|
||||
|
||||
bool Decoder::can_decode_C_frame_in_vm() {
|
||||
return true;
|
||||
assert(_decoder_lock != NULL, "Just check");
|
||||
MutexLockerEx locker(_decoder_lock, true);
|
||||
NullDecoder* decoder = get_decoder();
|
||||
assert(decoder != NULL, "null decoder");
|
||||
return decoder->can_decode_C_frame_in_vm();
|
||||
}
|
||||
|
||||
void Decoder::initialize() {
|
||||
_initialized = true;
|
||||
// shutdown real decoder and replace it with
|
||||
// _do_nothing_decoder
|
||||
void Decoder::shutdown() {
|
||||
assert(_decoder_lock != NULL, "Just check");
|
||||
MutexLockerEx locker(_decoder_lock, true);
|
||||
|
||||
if (_decoder != NULL && _decoder != &_do_nothing_decoder) {
|
||||
delete _decoder;
|
||||
}
|
||||
|
||||
_decoder = &_do_nothing_decoder;
|
||||
}
|
||||
|
||||
void Decoder::uninitialize() {
|
||||
if (_opened_elf_files != NULL) {
|
||||
delete _opened_elf_files;
|
||||
_opened_elf_files = NULL;
|
||||
}
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
|
||||
if (_decoder_status != no_error) {
|
||||
return _decoder_status;
|
||||
}
|
||||
|
||||
ElfFile* file = get_elf_file(filepath);
|
||||
if (_decoder_status != no_error) {
|
||||
return _decoder_status;
|
||||
}
|
||||
|
||||
const char* symbol = file->decode(addr, offset);
|
||||
if (file->get_status() == out_of_memory) {
|
||||
_decoder_status = out_of_memory;
|
||||
return _decoder_status;
|
||||
} else if (symbol != NULL) {
|
||||
if (!demangle(symbol, buf, buflen)) {
|
||||
jio_snprintf(buf, buflen, "%s", symbol);
|
||||
}
|
||||
return no_error;
|
||||
} else {
|
||||
return symbol_not_found;
|
||||
}
|
||||
}
|
||||
|
||||
ElfFile* Decoder::get_elf_file(const char* filepath) {
|
||||
if (_decoder_status != no_error) {
|
||||
return NULL;
|
||||
}
|
||||
ElfFile* file = _opened_elf_files;
|
||||
while (file != NULL) {
|
||||
if (file->same_elf_file(filepath)) {
|
||||
return file;
|
||||
}
|
||||
file = file->m_next;
|
||||
}
|
||||
|
||||
file = new ElfFile(filepath);
|
||||
if (file == NULL) {
|
||||
_decoder_status = out_of_memory;
|
||||
}
|
||||
if (_opened_elf_files != NULL) {
|
||||
file->m_next = _opened_elf_files;
|
||||
}
|
||||
|
||||
_opened_elf_files = file;
|
||||
return file;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,83 +23,78 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __DECODER_HPP
|
||||
#define __DECODER_HPP
|
||||
#ifndef SHARE_VM_UTILITIES_DECODER_HPP
|
||||
#define SHARE_VM_UTILITIES_DECODER_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#include <imagehlp.h>
|
||||
|
||||
// functions needed for decoding symbols
|
||||
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
|
||||
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
|
||||
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
|
||||
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#else
|
||||
|
||||
class ElfFile;
|
||||
|
||||
#endif // _WINDOWS
|
||||
|
||||
|
||||
class Decoder: public StackObj {
|
||||
|
||||
public:
|
||||
class NullDecoder: public CHeapObj {
|
||||
public:
|
||||
// status code for decoding native C frame
|
||||
enum decoder_status {
|
||||
no_error, // successfully decoded frames
|
||||
not_available = -10, // real decoder is not available
|
||||
no_error = 0, // successfully decoded frames
|
||||
out_of_memory, // out of memory
|
||||
file_invalid, // invalid elf file
|
||||
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
|
||||
helper_not_found, // could not load dbghelp.dll (Windows only)
|
||||
helper_func_error, // decoding functions not found (Windows only)
|
||||
helper_init_error, // SymInitialize failed (Windows only)
|
||||
symbol_not_found // could not find the symbol
|
||||
helper_init_error // SymInitialize failed (Windows only)
|
||||
};
|
||||
|
||||
public:
|
||||
Decoder() { initialize(); };
|
||||
~Decoder() { uninitialize(); };
|
||||
NullDecoder() {
|
||||
_decoder_status = not_available;
|
||||
}
|
||||
|
||||
static bool can_decode_C_frame_in_vm();
|
||||
~NullDecoder() {};
|
||||
|
||||
static void initialize();
|
||||
static void uninitialize();
|
||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||
const char* modulepath = NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
static decoder_status decode(address addr, char *buf, int buflen, int *offset);
|
||||
#else
|
||||
static decoder_status decode(address addr, const char* filepath, char *buf, int buflen, int *offset);
|
||||
#endif
|
||||
virtual bool demangle(const char* symbol, char* buf, int buflen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool demangle(const char* symbol, char *buf, int buflen);
|
||||
virtual bool can_decode_C_frame_in_vm() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static decoder_status get_status() { return _decoder_status; };
|
||||
virtual decoder_status status() const {
|
||||
return _decoder_status;
|
||||
}
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
private:
|
||||
static ElfFile* get_elf_file(const char* filepath);
|
||||
#endif // _WINDOWS
|
||||
virtual bool has_error() const {
|
||||
return is_error(_decoder_status);
|
||||
}
|
||||
|
||||
static bool is_error(decoder_status status) {
|
||||
return (status > 0);
|
||||
}
|
||||
|
||||
private:
|
||||
static decoder_status _decoder_status;
|
||||
static bool _initialized;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
static HMODULE _dbghelp_handle;
|
||||
static bool _can_decode_in_vm;
|
||||
static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
||||
static pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
|
||||
#elif __APPLE__
|
||||
#else
|
||||
static ElfFile* _opened_elf_files;
|
||||
#endif // _WINDOWS
|
||||
protected:
|
||||
decoder_status _decoder_status;
|
||||
};
|
||||
|
||||
#endif // __DECODER_HPP
|
||||
|
||||
class Decoder: AllStatic {
|
||||
public:
|
||||
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL);
|
||||
static bool demangle(const char* symbol, char* buf, int buflen);
|
||||
static bool can_decode_C_frame_in_vm();
|
||||
|
||||
static void shutdown();
|
||||
protected:
|
||||
static NullDecoder* get_decoder();
|
||||
|
||||
private:
|
||||
static NullDecoder* _decoder;
|
||||
static NullDecoder _do_nothing_decoder;
|
||||
|
||||
protected:
|
||||
static Mutex* _decoder_lock;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_UTILITIES_DECODER_HPP
|
||||
|
76
hotspot/src/share/vm/utilities/decoder_elf.cpp
Normal file
76
hotspot/src/share/vm/utilities/decoder_elf.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
#include "decoder_elf.hpp"
|
||||
|
||||
ElfDecoder::~ElfDecoder() {
|
||||
if (_opened_elf_files != NULL) {
|
||||
delete _opened_elf_files;
|
||||
_opened_elf_files = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) {
|
||||
assert(filepath, "null file path");
|
||||
assert(buf != NULL && buflen > 0, "Invalid buffer");
|
||||
if (has_error()) return false;
|
||||
ElfFile* file = get_elf_file(filepath);
|
||||
if (file == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file->decode(addr, buf, buflen, offset)) {
|
||||
return false;
|
||||
}
|
||||
if (buf[0] != '\0') {
|
||||
demangle(buf, buf, buflen);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ElfFile* ElfDecoder::get_elf_file(const char* filepath) {
|
||||
ElfFile* file;
|
||||
|
||||
file = _opened_elf_files;
|
||||
while (file != NULL) {
|
||||
if (file->same_elf_file(filepath)) {
|
||||
return file;
|
||||
}
|
||||
file = file->next();
|
||||
}
|
||||
|
||||
file = new (std::nothrow)ElfFile(filepath);
|
||||
if (file != NULL) {
|
||||
if (_opened_elf_files != NULL) {
|
||||
file->set_next(_opened_elf_files);
|
||||
}
|
||||
_opened_elf_files = file;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
#endif
|
55
hotspot/src/share/vm/utilities/decoder_elf.hpp
Normal file
55
hotspot/src/share/vm/utilities/decoder_elf.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
||||
#define SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "utilities/elfFile.hpp"
|
||||
|
||||
class ElfDecoder: public NullDecoder {
|
||||
|
||||
public:
|
||||
ElfDecoder() {
|
||||
_opened_elf_files = NULL;
|
||||
_decoder_status = no_error;
|
||||
}
|
||||
~ElfDecoder();
|
||||
|
||||
bool can_decode_C_frame_in_vm() const { return true; }
|
||||
|
||||
bool demangle(const char* symbol, char *buf, int buflen);
|
||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL);
|
||||
|
||||
private:
|
||||
ElfFile* get_elf_file(const char* filepath);
|
||||
|
||||
private:
|
||||
ElfFile* _opened_elf_files;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
@ -44,7 +44,7 @@ ElfFile::ElfFile(const char* filepath) {
|
||||
m_string_tables = NULL;
|
||||
m_symbol_tables = NULL;
|
||||
m_next = NULL;
|
||||
m_status = Decoder::no_error;
|
||||
m_status = NullDecoder::no_error;
|
||||
|
||||
int len = strlen(filepath) + 1;
|
||||
m_filepath = (const char*)os::malloc(len * sizeof(char));
|
||||
@ -54,10 +54,10 @@ ElfFile::ElfFile(const char* filepath) {
|
||||
if (m_file != NULL) {
|
||||
load_tables();
|
||||
} else {
|
||||
m_status = Decoder::file_not_found;
|
||||
m_status = NullDecoder::file_not_found;
|
||||
}
|
||||
} else {
|
||||
m_status = Decoder::out_of_memory;
|
||||
m_status = NullDecoder::out_of_memory;
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,41 +96,41 @@ bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
|
||||
|
||||
bool ElfFile::load_tables() {
|
||||
assert(m_file, "file not open");
|
||||
assert(m_status == Decoder::no_error, "already in error");
|
||||
assert(!NullDecoder::is_error(m_status), "already in error");
|
||||
|
||||
// read elf file header
|
||||
if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_elf_file(m_elfHdr)) {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
// walk elf file's section headers, and load string tables
|
||||
Elf_Shdr shdr;
|
||||
if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
|
||||
if (m_status != Decoder::no_error) return false;
|
||||
if (NullDecoder::is_error(m_status)) return false;
|
||||
|
||||
for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
|
||||
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
// string table
|
||||
if (shdr.sh_type == SHT_STRTAB) {
|
||||
ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
|
||||
if (table == NULL) {
|
||||
m_status = Decoder::out_of_memory;
|
||||
m_status = NullDecoder::out_of_memory;
|
||||
return false;
|
||||
}
|
||||
add_string_table(table);
|
||||
} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
|
||||
ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
|
||||
if (table == NULL) {
|
||||
m_status = Decoder::out_of_memory;
|
||||
m_status = NullDecoder::out_of_memory;
|
||||
return false;
|
||||
}
|
||||
add_symbol_table(table);
|
||||
@ -140,32 +140,33 @@ bool ElfFile::load_tables() {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* ElfFile::decode(address addr, int* offset) {
|
||||
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
||||
// something already went wrong, just give up
|
||||
if (m_status != Decoder::no_error) {
|
||||
return NULL;
|
||||
if (NullDecoder::is_error(m_status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ElfSymbolTable* symbol_table = m_symbol_tables;
|
||||
int string_table_index;
|
||||
int pos_in_string_table;
|
||||
int off = INT_MAX;
|
||||
bool found_symbol = false;
|
||||
while (symbol_table != NULL) {
|
||||
if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
|
||||
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
|
||||
found_symbol = true;
|
||||
}
|
||||
symbol_table = symbol_table->m_next;
|
||||
}
|
||||
if (!found_symbol) return NULL;
|
||||
if (!found_symbol) return false;
|
||||
|
||||
ElfStringTable* string_table = get_string_table(string_table_index);
|
||||
|
||||
if (string_table == NULL) {
|
||||
m_status = Decoder::file_invalid;
|
||||
return NULL;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
if (offset) *offset = off;
|
||||
return string_table->string_at(pos_in_string_table);
|
||||
|
||||
return string_table->string_at(pos_in_string_table, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ELF_FILE_HPP
|
||||
#define __ELF_FILE_HPP
|
||||
#ifndef SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||
#define SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
@ -83,12 +83,12 @@ class ElfSymbolTable;
|
||||
// part of code to be very defensive, and bait out if anything went wrong.
|
||||
|
||||
class ElfFile: public CHeapObj {
|
||||
friend class Decoder;
|
||||
friend class ElfDecoder;
|
||||
public:
|
||||
ElfFile(const char* filepath);
|
||||
~ElfFile();
|
||||
|
||||
const char* decode(address addr, int* offset);
|
||||
bool decode(address addr, char* buf, int buflen, int* offset);
|
||||
const char* filepath() {
|
||||
return m_filepath;
|
||||
}
|
||||
@ -99,7 +99,7 @@ class ElfFile: public CHeapObj {
|
||||
return (m_filepath && !strcmp(filepath, m_filepath));
|
||||
}
|
||||
|
||||
Decoder::decoder_status get_status() {
|
||||
NullDecoder::decoder_status get_status() {
|
||||
return m_status;
|
||||
}
|
||||
|
||||
@ -119,8 +119,9 @@ class ElfFile: public CHeapObj {
|
||||
// return a string table at specified section index
|
||||
ElfStringTable* get_string_table(int index);
|
||||
|
||||
// look up an address and return the nearest symbol
|
||||
const char* look_up(Elf_Shdr shdr, address addr, int* offset);
|
||||
protected:
|
||||
ElfFile* next() const { return m_next; }
|
||||
void set_next(ElfFile* file) { m_next = file; }
|
||||
|
||||
protected:
|
||||
ElfFile* m_next;
|
||||
@ -131,17 +132,17 @@ class ElfFile: public CHeapObj {
|
||||
FILE* m_file;
|
||||
|
||||
// Elf header
|
||||
Elf_Ehdr m_elfHdr;
|
||||
Elf_Ehdr m_elfHdr;
|
||||
|
||||
// symbol tables
|
||||
ElfSymbolTable* m_symbol_tables;
|
||||
ElfSymbolTable* m_symbol_tables;
|
||||
|
||||
// string tables
|
||||
ElfStringTable* m_string_tables;
|
||||
ElfStringTable* m_string_tables;
|
||||
|
||||
Decoder::decoder_status m_status;
|
||||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS
|
||||
|
||||
#endif // __ELF_FILE_HPP
|
||||
#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||
|
@ -38,7 +38,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
|
||||
m_index = index;
|
||||
m_next = NULL;
|
||||
m_file = file;
|
||||
m_status = Decoder::no_error;
|
||||
m_status = NullDecoder::no_error;
|
||||
|
||||
// try to load the string table
|
||||
long cur_offset = ftell(file);
|
||||
@ -48,7 +48,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
|
||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
||||
fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
|
||||
fseek(file, cur_offset, SEEK_SET)) {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
os::free((void*)m_table);
|
||||
m_table = NULL;
|
||||
}
|
||||
@ -67,22 +67,23 @@ ElfStringTable::~ElfStringTable() {
|
||||
}
|
||||
}
|
||||
|
||||
const char* ElfStringTable::string_at(int pos) {
|
||||
if (m_status != Decoder::no_error) {
|
||||
return NULL;
|
||||
bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
|
||||
if (NullDecoder::is_error(m_status)) {
|
||||
return false;
|
||||
}
|
||||
if (m_table != NULL) {
|
||||
return (const char*)(m_table + pos);
|
||||
jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
|
||||
return true;
|
||||
} else {
|
||||
long cur_pos = ftell(m_file);
|
||||
if (cur_pos == -1 ||
|
||||
fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
|
||||
fread(m_symbol, 1, MAX_SYMBOL_LEN, m_file) <= 0 ||
|
||||
fread(buf, 1, buflen, m_file) <= 0 ||
|
||||
fseek(m_file, cur_pos, SEEK_SET)) {
|
||||
m_status = Decoder::file_invalid;
|
||||
return NULL;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
return (const char*)m_symbol;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ELF_STRING_TABLE_HPP
|
||||
#define __ELF_STRING_TABLE_HPP
|
||||
#ifndef SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||
#define SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
@ -35,9 +35,6 @@
|
||||
// The string table represents a string table section in an elf file.
|
||||
// Whenever there is enough memory, it will load whole string table as
|
||||
// one blob. Otherwise, it will load string from file when requested.
|
||||
|
||||
#define MAX_SYMBOL_LEN 256
|
||||
|
||||
class ElfStringTable: CHeapObj {
|
||||
friend class ElfFile;
|
||||
public:
|
||||
@ -48,10 +45,10 @@ class ElfStringTable: CHeapObj {
|
||||
int index() { return m_index; };
|
||||
|
||||
// get string at specified offset
|
||||
const char* string_at(int offset);
|
||||
bool string_at(int offset, char* buf, int buflen);
|
||||
|
||||
// get status code
|
||||
Decoder::decoder_status get_status() { return m_status; };
|
||||
NullDecoder::decoder_status get_status() { return m_status; };
|
||||
|
||||
protected:
|
||||
ElfStringTable* m_next;
|
||||
@ -69,13 +66,10 @@ class ElfStringTable: CHeapObj {
|
||||
// section header
|
||||
Elf_Shdr m_shdr;
|
||||
|
||||
// buffer for reading individual string
|
||||
char m_symbol[MAX_SYMBOL_LEN];
|
||||
|
||||
// error code
|
||||
Decoder::decoder_status m_status;
|
||||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // _WINDOWS and _APPLE
|
||||
|
||||
#endif // __ELF_STRING_TABLE_HPP
|
||||
#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||
|
@ -34,7 +34,7 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
||||
m_symbols = NULL;
|
||||
m_next = NULL;
|
||||
m_file = file;
|
||||
m_status = Decoder::no_error;
|
||||
m_status = NullDecoder::no_error;
|
||||
|
||||
// try to load the string table
|
||||
long cur_offset = ftell(file);
|
||||
@ -45,16 +45,16 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
||||
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
|
||||
fseek(file, cur_offset, SEEK_SET)) {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
os::free(m_symbols);
|
||||
m_symbols = NULL;
|
||||
}
|
||||
}
|
||||
if (m_status == Decoder::no_error) {
|
||||
if (!NullDecoder::is_error(m_status)) {
|
||||
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
||||
}
|
||||
} else {
|
||||
m_status = Decoder::file_invalid;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,13 +68,13 @@ ElfSymbolTable::~ElfSymbolTable() {
|
||||
}
|
||||
}
|
||||
|
||||
Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
|
||||
bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
|
||||
assert(stringtableIndex, "null string table index pointer");
|
||||
assert(posIndex, "null string table offset pointer");
|
||||
assert(offset, "null offset pointer");
|
||||
|
||||
if (m_status != Decoder::no_error) {
|
||||
return m_status;
|
||||
if (NullDecoder::is_error(m_status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
address pc = 0;
|
||||
@ -97,8 +97,8 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd
|
||||
long cur_pos;
|
||||
if ((cur_pos = ftell(m_file)) == -1 ||
|
||||
fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
|
||||
m_status = Decoder::file_invalid;
|
||||
return m_status;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Elf_Sym sym;
|
||||
@ -114,13 +114,13 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_status = Decoder::file_invalid;
|
||||
return m_status;
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fseek(m_file, cur_pos, SEEK_SET);
|
||||
}
|
||||
return m_status;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // _WINDOWS
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ELF_SYMBOL_TABLE_HPP
|
||||
#define __ELF_SYMBOL_TABLE_HPP
|
||||
#ifndef SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||
#define SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
@ -45,9 +45,9 @@ class ElfSymbolTable: public CHeapObj {
|
||||
~ElfSymbolTable();
|
||||
|
||||
// search the symbol that is nearest to the specified address.
|
||||
Decoder::decoder_status lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
|
||||
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
|
||||
|
||||
Decoder::decoder_status get_status() { return m_status; };
|
||||
NullDecoder::decoder_status get_status() { return m_status; };
|
||||
|
||||
protected:
|
||||
ElfSymbolTable* m_next;
|
||||
@ -62,9 +62,9 @@ class ElfSymbolTable: public CHeapObj {
|
||||
// section header
|
||||
Elf_Shdr m_shdr;
|
||||
|
||||
Decoder::decoder_status m_status;
|
||||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // _WINDOWS and _APPLE
|
||||
|
||||
#endif // __ELF_SYMBOL_TABLE_HPP
|
||||
#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||
|
@ -298,6 +298,11 @@ const jushort max_jushort = (jushort)-1; // 0xFFFF largest jushort
|
||||
const juint max_juint = (juint)-1; // 0xFFFFFFFF largest juint
|
||||
const julong max_julong = (julong)-1; // 0xFF....FF largest julong
|
||||
|
||||
typedef jbyte s1;
|
||||
typedef jshort s2;
|
||||
typedef jint s4;
|
||||
typedef jlong s8;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// JVM spec restrictions
|
||||
|
||||
|
@ -571,8 +571,6 @@ void VMError::report(outputStream* st) {
|
||||
if (fr.pc()) {
|
||||
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
||||
|
||||
// initialize decoder to decode C frames
|
||||
Decoder decoder;
|
||||
|
||||
int count = 0;
|
||||
while (count++ < StackPrintLimit) {
|
||||
|
@ -143,3 +143,4 @@ b71d1acfae5240d8c1359443cd02b5ddb587231c jdk8-b17
|
||||
3778f85773055e81eab6c5ef828935ecca241810 jdk8-b19
|
||||
39e938cd1b82ec3aab0a9aa66fd8a0457cd0c9c2 jdk8-b20
|
||||
664fa4fb0ee411ef048903c479f8b962fcdb2f4b jdk8-b21
|
||||
dda27c73d8db4a9c7a23872b6f0c5106edcb2021 jdk8-b22
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,15 +25,24 @@
|
||||
|
||||
BUILDDIR = ../..
|
||||
PRODUCT = oracle
|
||||
#SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true
|
||||
#SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true
|
||||
#SUBDIRS_MAKEFLAGS += JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation,-path
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Files to compile
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = com/oracle
|
||||
# build com/oracle/security/ucrypto on Solaris platform for non-OpenJDK builds
|
||||
UCRYPTO =
|
||||
ifndef OPENJDK
|
||||
ifeq ($(PLATFORM), solaris)
|
||||
UCRYPTO = security/ucrypto
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
|
||||
SUBDIRS = net nio util $(UCRYPTO)
|
||||
|
||||
include $(BUILDDIR)/common/Subdirs.gmk
|
||||
|
||||
all build clean clobber::
|
||||
$(SUBDIRS-loop)
|
||||
|
||||
|
40
jdk/make/com/oracle/net/Makefile
Normal file
40
jdk/make/com/oracle/net/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../..
|
||||
PACKAGE = com.oracle.net
|
||||
PRODUCT = oracle
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = com/oracle/net
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
|
40
jdk/make/com/oracle/nio/Makefile
Normal file
40
jdk/make/com/oracle/nio/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../..
|
||||
PACKAGE = com.oracle.nio
|
||||
PRODUCT = oracle
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = com/oracle/nio
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
|
30
jdk/make/com/oracle/security/ucrypto/FILES_c.gmk
Normal file
30
jdk/make/com/oracle/security/ucrypto/FILES_c.gmk
Normal file
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
ifndef OPENJDK
|
||||
FILES_c = \
|
||||
nativeFunc.c \
|
||||
nativeCrypto.c
|
||||
endif
|
270
jdk/make/com/oracle/security/ucrypto/Makefile
Normal file
270
jdk/make/com/oracle/security/ucrypto/Makefile
Normal file
@ -0,0 +1,270 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for building ucrypto.jar and its native libraries.
|
||||
#
|
||||
# This file was modified from make/sun/security/pkcs11/Makefile.
|
||||
#
|
||||
#
|
||||
# (The terms "OpenJDK" and "JDK" below refer to OpenJDK and Oracle
|
||||
# JDK builds respectively.)
|
||||
#
|
||||
# This Makefile does the "real" build of the Ucrypto provider files.
|
||||
# Since the sources are unavailable for OpenJDK, this Makefile is only
|
||||
# useful for JDK.
|
||||
#
|
||||
#
|
||||
# Main Targets (JDK on Solaris):
|
||||
#
|
||||
# all The usual, ucrypto.jar plus the native libraries.
|
||||
# builds and installs the prebuilt/signed jar.
|
||||
#
|
||||
# clobber/clean Cleans up the temp directory, ucrypto.jar, the
|
||||
# native libraries, and the config file from the
|
||||
# build area
|
||||
#
|
||||
# jar Builds, signs and installs ucrypto.jar
|
||||
# (Can only be done on machines with access to
|
||||
# the signing keystore)
|
||||
#
|
||||
# Other lesser-used Targets (JDK on Solaris):
|
||||
#
|
||||
# build-jar Builds ucrypto.jar (no sign/install)
|
||||
#
|
||||
# sign Builds/signs ucrypto.jar (no install)
|
||||
#
|
||||
# release Builds all targets in preparation
|
||||
# for workspace integration.
|
||||
# (Can only be done on machines with access to
|
||||
# the signing keystore)
|
||||
#
|
||||
# install-prebuilt Installs the pre-built jar files
|
||||
#
|
||||
# NOTE: None of the above target will update the prebuilt provider binary
|
||||
# under the closed workspace. To update it, you must explicitly copy the
|
||||
# binary from either the tmp/signed or lib/ext directory.
|
||||
#
|
||||
# This makefile was written to support parallel target execution.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../../..
|
||||
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
ifndef OPENJDK
|
||||
ifneq ($(PLATFORM), solaris)
|
||||
all:
|
||||
else
|
||||
PACKAGE = com.oracle.security.ucrypto
|
||||
LIBRARY = j2ucrypto
|
||||
PRODUCT = oracle
|
||||
|
||||
#
|
||||
# The following is for when we need to do postprocessing
|
||||
# (signing/obfuscation) against a read-only build. If the OUTPUTDIR
|
||||
# isn't writable, the build currently crashes out.
|
||||
#
|
||||
ifdef ALT_JCE_BUILD_DIR
|
||||
# =====================================================
|
||||
# Where to place the output, in case we're building from a read-only
|
||||
# build area. (e.g. a release engineering build.)
|
||||
JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
|
||||
IGNORE_WRITABLE_OUTPUTDIR_TEST=true
|
||||
else
|
||||
JCE_BUILD_DIR=${TEMPDIR}
|
||||
endif
|
||||
|
||||
JAVAC_MAX_WARNINGS=false
|
||||
JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation
|
||||
JAVAC_WARNINGS_FATAL=true
|
||||
|
||||
#
|
||||
# C and Java Files
|
||||
#
|
||||
include FILES_c.gmk
|
||||
|
||||
#
|
||||
# Subdirectories of these are automatically included.
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = com/oracle/security/ucrypto
|
||||
|
||||
#
|
||||
# Java files that define native methods
|
||||
#
|
||||
FILES_export = \
|
||||
com/oracle/security/ucrypto/UcryptoProvider.java \
|
||||
com/oracle/security/ucrypto/NativeCipher.java \
|
||||
com/oracle/security/ucrypto/NativeDigest.java \
|
||||
com/oracle/security/ucrypto/NativeKey.java \
|
||||
com/oracle/security/ucrypto/NativeRSASignature.java \
|
||||
com/oracle/security/ucrypto/NativeRSACipher.java
|
||||
|
||||
#
|
||||
# Find native code
|
||||
#
|
||||
vpath %.c \
|
||||
$(CLOSED_PLATFORM_SRC)/native/com/oracle/security/ucrypto
|
||||
|
||||
#
|
||||
# Find include files
|
||||
#
|
||||
OTHER_INCLUDES += \
|
||||
-I$(CLOSED_PLATFORM_SRC)/native/com/oracle/security/ucrypto
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
CLASSDESTDIR = $(TEMPDIR)/classes
|
||||
JAVAHFLAGS = -bootclasspath \
|
||||
"$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)"
|
||||
|
||||
include $(BUILDDIR)/common/Mapfile-vers.gmk
|
||||
include $(BUILDDIR)/common/Library.gmk
|
||||
|
||||
#
|
||||
# Libraries to link
|
||||
#
|
||||
OTHER_LDLIBS = -ldl
|
||||
|
||||
# Default config file
|
||||
UCRYPTO_CFG_SRC = $(CLOSED_SRC)/share/lib/security/ucrypto-solaris.cfg
|
||||
UCRYPTO_CFG_BUILD = $(LIBDIR)/security/ucrypto-solaris.cfg
|
||||
|
||||
#
|
||||
# We use a variety of subdirectories in the $(TEMPDIR) depending on what
|
||||
# part of the build we're doing. Build is initially done in the unsigned
|
||||
# area and when files are signed, they will be placed in the appropriate area.
|
||||
#
|
||||
UNSIGNED_DIR = $(TEMPDIR)/unsigned
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
all: ucrypto-cfg build-jar install-prebuilt
|
||||
$(build-warning)
|
||||
|
||||
ucrypto-cfg: $(UCRYPTO_CFG_BUILD)
|
||||
|
||||
$(UCRYPTO_CFG_BUILD): $(UCRYPTO_CFG_SRC)
|
||||
$(install-file)
|
||||
|
||||
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
||||
|
||||
|
||||
# =====================================================
|
||||
# Build the unsigned ucrypto.jar file.
|
||||
#
|
||||
|
||||
JAR_DESTFILE = $(EXTDIR)/ucrypto.jar
|
||||
|
||||
#
|
||||
# The ucrypto.jar needs to be in the extension class directory,
|
||||
# therefore none of its classes can appear in $(CLASSBINDIR).
|
||||
# Currently no one is using any of the internals, so these files
|
||||
# should not have been built.
|
||||
#
|
||||
|
||||
#
|
||||
# Since the -C option to jar is used below, each directory entry must be
|
||||
# preceded with the appropriate directory to "cd" into.
|
||||
#
|
||||
JAR_DIRS = $(patsubst %, -C $(CLASSDESTDIR) %, $(AUTO_FILES_JAVA_DIRS))
|
||||
|
||||
build-jar: $(UNSIGNED_DIR)/ucrypto.jar
|
||||
|
||||
#
|
||||
# Build ucrypto.jar.
|
||||
#
|
||||
$(UNSIGNED_DIR)/ucrypto.jar: build
|
||||
$(prep-target)
|
||||
$(BOOT_JAR_CMD) cf $@ $(JAR_DIRS) \
|
||||
$(BOOT_JAR_JFLAGS)
|
||||
@$(java-vm-cleanup)
|
||||
|
||||
#
|
||||
# Sign ucrypto.jar
|
||||
#
|
||||
SIGNED_DIR = $(JCE_BUILD_DIR)/signed
|
||||
|
||||
sign: $(SIGNED_DIR)/ucrypto.jar
|
||||
|
||||
ifndef ALT_JCE_BUILD_DIR
|
||||
$(SIGNED_DIR)/ucrypto.jar: $(UNSIGNED_DIR)/ucrypto.jar
|
||||
else
|
||||
#
|
||||
# We have to remove the build dependency, otherwise, we'll try to rebuild it
|
||||
# which we can't do on a read-only filesystem.
|
||||
#
|
||||
$(SIGNED_DIR)/ucrypto.jar:
|
||||
@if [ ! -r $(UNSIGNED_DIR)/ucrypto.jar ] ; then \
|
||||
$(ECHO) "Couldn't find $(UNSIGNED_DIR)/ucrypto.jar"; \
|
||||
exit 1; \
|
||||
fi
|
||||
endif
|
||||
$(call sign-file, $(UNSIGNED_DIR)/ucrypto.jar)
|
||||
|
||||
|
||||
# =====================================================
|
||||
# Create the Release Engineering files. Signed builds, etc.
|
||||
#
|
||||
|
||||
release: $(SIGNED_DIR)/ucrypto.jar
|
||||
$(RM) $(JCE_BUILD_DIR)/release/ucrypto.jar
|
||||
$(MKDIR) -p $(JCE_BUILD_DIR)/release
|
||||
$(CP) $(SIGNED_DIR)/ucrypto.jar $(JCE_BUILD_DIR)/release
|
||||
$(release-warning)
|
||||
|
||||
|
||||
# =====================================================
|
||||
# Install routines.
|
||||
#
|
||||
|
||||
#
|
||||
# Install ucrypto.jar, depending on which type is requested.
|
||||
#
|
||||
jar: $(JAR_DESTFILE)
|
||||
$(release-warning)
|
||||
|
||||
$(JAR_DESTFILE): $(SIGNED_DIR)/ucrypto.jar
|
||||
$(install-file)
|
||||
|
||||
install-prebuilt:
|
||||
@$(ECHO) "\n>>>Installing prebuilt OracleUcrypto provider..."
|
||||
$(RM) $(JAR_DESTFILE)
|
||||
$(CP) $(PREBUILT_DIR)/ucrypto/ucrypto.jar $(JAR_DESTFILE)
|
||||
|
||||
|
||||
# =====================================================
|
||||
# Support routines.
|
||||
#
|
||||
clobber clean::
|
||||
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
|
||||
$(RM) -r $(UCRYPTO_CFG_BUILD)
|
||||
|
||||
.PHONY: build-jar jar sign release install-prebuilt
|
||||
|
||||
endif #ifneq ($(PLATFORM), solaris)
|
||||
endif #ifndef OPENJDK
|
69
jdk/make/com/oracle/security/ucrypto/mapfile-vers
Normal file
69
jdk/make/com/oracle/security/ucrypto/mapfile-vers
Normal file
@ -0,0 +1,69 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
# Define public interface.
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
JNI_OnLoad;
|
||||
Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries;
|
||||
Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList;
|
||||
Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
|
||||
Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
|
||||
Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
|
||||
Java_com_oracle_security_ucrypto_NativeDigest_nativeClone;
|
||||
Java_com_oracle_security_ucrypto_NativeDigest_nativeFree;
|
||||
Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
|
||||
Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
|
||||
Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
|
||||
Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
|
||||
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
|
||||
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
|
||||
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
|
||||
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
|
||||
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
|
||||
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
|
||||
Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
|
||||
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
|
||||
JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
40
jdk/make/com/oracle/util/Makefile
Normal file
40
jdk/make/com/oracle/util/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../..
|
||||
PACKAGE = com.oracle.util
|
||||
PRODUCT = oracle
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = com/oracle/util
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
|
@ -65,7 +65,7 @@ FILES_export = \
|
||||
$(MIDIFILES_export) \
|
||||
$(PORTFILES_export)
|
||||
|
||||
LDFLAGS += -lasound
|
||||
OTHER_LDLIBS += -lasound
|
||||
|
||||
CPPFLAGS += \
|
||||
-DUSE_DAUDIO=TRUE \
|
||||
|
@ -367,7 +367,8 @@ else
|
||||
FONTCONFIGS_SRC = $(CLOSED_SRC)/solaris/classes/sun/awt/fontconfigs
|
||||
_FONTCONFIGS = \
|
||||
fontconfig.properties \
|
||||
fontconfig.RedHat.5.5.properties \
|
||||
fontconfig.RedHat.5.properties \
|
||||
fontconfig.RedHat.6.properties \
|
||||
fontconfig.Turbo.properties \
|
||||
fontconfig.SuSE.10.properties \
|
||||
fontconfig.SuSE.11.properties
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,8 +47,8 @@ SUNWprivate_1.1 {
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession;
|
||||
# Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo;
|
||||
# Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState;
|
||||
# Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout;
|
||||
Java_sun_security_pkcs11_wrapper_PKCS11_C_1CreateObject;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1225,14 +1225,7 @@ LoadMainClass(JNIEnv *env, int mode, char *name)
|
||||
"checkAndLoadMain",
|
||||
"(ZILjava/lang/String;)Ljava/lang/Class;"));
|
||||
|
||||
switch (mode) {
|
||||
case LM_CLASS:
|
||||
str = NewPlatformString(env, name);
|
||||
break;
|
||||
default:
|
||||
str = (*env)->NewStringUTF(env, name);
|
||||
break;
|
||||
}
|
||||
str = NewPlatformString(env, name);
|
||||
result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str);
|
||||
|
||||
if (JLI_IsTraceLauncher()) {
|
||||
|
@ -154,7 +154,7 @@ public final class TypeResolver {
|
||||
* @see #resolve(Type)
|
||||
*/
|
||||
public static Type resolve(Type actual, Type formal) {
|
||||
return new TypeResolver(actual).resolve(formal);
|
||||
return getTypeResolver(actual).resolve(formal);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +169,7 @@ public final class TypeResolver {
|
||||
* @see #resolve(Type[])
|
||||
*/
|
||||
public static Type[] resolve(Type actual, Type[] formals) {
|
||||
return new TypeResolver(actual).resolve(formals);
|
||||
return getTypeResolver(actual).resolve(formals);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,9 +228,20 @@ public final class TypeResolver {
|
||||
return classes;
|
||||
}
|
||||
|
||||
public static TypeResolver getTypeResolver(Type type) {
|
||||
synchronized (CACHE) {
|
||||
TypeResolver resolver = CACHE.get(type);
|
||||
if (resolver == null) {
|
||||
resolver = new TypeResolver(type);
|
||||
CACHE.put(type, resolver);
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<TypeVariable<?>, Type> map
|
||||
= new HashMap<TypeVariable<?>, Type>();
|
||||
private static final WeakCache<Type, TypeResolver> CACHE = new WeakCache<>();
|
||||
|
||||
private final Map<TypeVariable<?>, Type> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs the type resolver for the given actual type.
|
||||
|
@ -802,8 +802,11 @@ public class AWTKeyStroke implements Serializable {
|
||||
*/
|
||||
protected Object readResolve() throws java.io.ObjectStreamException {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
|
||||
if (getClass().equals(getAWTKeyStrokeClass())) {
|
||||
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static int mapOldModifiers(int modifiers) {
|
||||
|
@ -3118,4 +3118,9 @@ public final
|
||||
AnnotationType getAnnotationType() {
|
||||
return annotationType;
|
||||
}
|
||||
|
||||
/* Backing store of user-defined values pertaining to this class.
|
||||
* Maintained by the ClassValue class.
|
||||
*/
|
||||
transient ClassValue.ClassValueMap classValueMap;
|
||||
}
|
||||
|
@ -25,9 +25,14 @@
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.lang.ClassValue.ClassValueMap;
|
||||
import java.util.WeakHashMap;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
|
||||
import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
|
||||
|
||||
/**
|
||||
* Lazily associate a computed value with (potentially) every type.
|
||||
* For example, if a dynamic language needs to construct a message dispatch
|
||||
@ -92,14 +97,22 @@ public abstract class ClassValue<T> {
|
||||
* @see #computeValue
|
||||
*/
|
||||
public T get(Class<?> type) {
|
||||
ClassValueMap map = getMap(type);
|
||||
if (map != null) {
|
||||
Object x = map.get(this);
|
||||
if (x != null) {
|
||||
return (T) map.unmaskNull(x);
|
||||
}
|
||||
}
|
||||
return setComputedValue(type);
|
||||
// non-racing this.hashCodeForCache : final int
|
||||
Entry<?>[] cache;
|
||||
Entry<T> e = probeHomeLocation(cache = getCacheCarefully(type), this);
|
||||
// racing e : current value <=> stale value from current cache or from stale cache
|
||||
// invariant: e is null or an Entry with readable Entry.version and Entry.value
|
||||
if (match(e))
|
||||
// invariant: No false positive matches. False negatives are OK if rare.
|
||||
// The key fact that makes this work: if this.version == e.version,
|
||||
// then this thread has a right to observe (final) e.value.
|
||||
return e.value();
|
||||
// The fast path can fail for any of these reasons:
|
||||
// 1. no entry has been computed yet
|
||||
// 2. hash code collision (before or after reduction mod cache.length)
|
||||
// 3. an entry has been removed (either on this type or another)
|
||||
// 4. the GC has somehow managed to delete e.version and clear the reference
|
||||
return getFromBackup(cache, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,83 +170,582 @@ public abstract class ClassValue<T> {
|
||||
*/
|
||||
public void remove(Class<?> type) {
|
||||
ClassValueMap map = getMap(type);
|
||||
if (map != null) {
|
||||
synchronized (map) {
|
||||
map.remove(this);
|
||||
}
|
||||
}
|
||||
map.removeEntry(this);
|
||||
}
|
||||
|
||||
/// Implementation...
|
||||
// FIXME: Use a data structure here similar that of ThreadLocal (7030453).
|
||||
|
||||
private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
|
||||
|
||||
/** Slow path for {@link #get}. */
|
||||
private T setComputedValue(Class<?> type) {
|
||||
// Possible functionality for JSR 292 MR 1
|
||||
/*public*/ void put(Class<?> type, T value) {
|
||||
ClassValueMap map = getMap(type);
|
||||
if (map == null) {
|
||||
map = initializeMap(type);
|
||||
}
|
||||
T value = computeValue(type);
|
||||
STORE_BARRIER.lazySet(0);
|
||||
// All stores pending from computeValue are completed.
|
||||
synchronized (map) {
|
||||
// Warm up the table with a null entry.
|
||||
map.preInitializeEntry(this);
|
||||
}
|
||||
STORE_BARRIER.lazySet(0);
|
||||
// All stores pending from table expansion are completed.
|
||||
synchronized (map) {
|
||||
value = (T) map.initializeEntry(this, value);
|
||||
// One might fear a possible race condition here
|
||||
// if the code for map.put has flushed the write
|
||||
// to map.table[*] before the writes to the Map.Entry
|
||||
// are done. This is not possible, since we have
|
||||
// warmed up the table with an empty entry.
|
||||
}
|
||||
return value;
|
||||
map.changeEntry(this, value);
|
||||
}
|
||||
|
||||
// Replace this map by a per-class slot.
|
||||
private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
|
||||
= new WeakHashMap<Class<?>, ClassValueMap>();
|
||||
/// --------
|
||||
/// Implementation...
|
||||
/// --------
|
||||
|
||||
/** Return the cache, if it exists, else a dummy empty cache. */
|
||||
private static Entry<?>[] getCacheCarefully(Class<?> type) {
|
||||
// racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y]
|
||||
ClassValueMap map = type.classValueMap;
|
||||
if (map == null) return EMPTY_CACHE;
|
||||
Entry<?>[] cache = map.getCache();
|
||||
return cache;
|
||||
// invariant: returned value is safe to dereference and check for an Entry
|
||||
}
|
||||
|
||||
/** Initial, one-element, empty cache used by all Class instances. Must never be filled. */
|
||||
private static final Entry<?>[] EMPTY_CACHE = { null };
|
||||
|
||||
/**
|
||||
* Slow tail of ClassValue.get to retry at nearby locations in the cache,
|
||||
* or take a slow lock and check the hash table.
|
||||
* Called only if the first probe was empty or a collision.
|
||||
* This is a separate method, so compilers can process it independently.
|
||||
*/
|
||||
private T getFromBackup(Entry<?>[] cache, Class<?> type) {
|
||||
Entry<T> e = probeBackupLocations(cache, this);
|
||||
if (e != null)
|
||||
return e.value();
|
||||
return getFromHashMap(type);
|
||||
}
|
||||
|
||||
// Hack to suppress warnings on the (T) cast, which is a no-op.
|
||||
@SuppressWarnings("unchecked")
|
||||
Entry<T> castEntry(Entry<?> e) { return (Entry<T>) e; }
|
||||
|
||||
/** Called when the fast path of get fails, and cache reprobe also fails.
|
||||
*/
|
||||
private T getFromHashMap(Class<?> type) {
|
||||
// The fail-safe recovery is to fall back to the underlying classValueMap.
|
||||
ClassValueMap map = getMap(type);
|
||||
for (;;) {
|
||||
Entry<T> e = map.startEntry(this);
|
||||
if (!e.isPromise())
|
||||
return e.value();
|
||||
try {
|
||||
// Try to make a real entry for the promised version.
|
||||
e = makeEntry(e.version(), computeValue(type));
|
||||
} finally {
|
||||
// Whether computeValue throws or returns normally,
|
||||
// be sure to remove the empty entry.
|
||||
e = map.finishEntry(this, e);
|
||||
}
|
||||
if (e != null)
|
||||
return e.value();
|
||||
// else try again, in case a racing thread called remove (so e == null)
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that e is non-null, matches this ClassValue, and is live. */
|
||||
boolean match(Entry<?> e) {
|
||||
// racing e.version : null (blank) => unique Version token => null (GC-ed version)
|
||||
// non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile)
|
||||
return (e != null && e.get() == this.version);
|
||||
// invariant: No false positives on version match. Null is OK for false negative.
|
||||
// invariant: If version matches, then e.value is readable (final set in Entry.<init>)
|
||||
}
|
||||
|
||||
/** Internal hash code for accessing Class.classValueMap.cacheArray. */
|
||||
final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK;
|
||||
|
||||
/** Value stream for hashCodeForCache. See similar structure in ThreadLocal. */
|
||||
private static final AtomicInteger nextHashCode = new AtomicInteger();
|
||||
|
||||
/** Good for power-of-two tables. See similar structure in ThreadLocal. */
|
||||
private static final int HASH_INCREMENT = 0x61c88647;
|
||||
|
||||
/** Mask a hash code to be positive but not too large, to prevent wraparound. */
|
||||
static final int HASH_MASK = (-1 >>> 2);
|
||||
|
||||
/**
|
||||
* Private key for retrieval of this object from ClassValueMap.
|
||||
*/
|
||||
static class Identity {
|
||||
}
|
||||
/**
|
||||
* This ClassValue's identity, expressed as an opaque object.
|
||||
* The main object {@code ClassValue.this} is incorrect since
|
||||
* subclasses may override {@code ClassValue.equals}, which
|
||||
* could confuse keys in the ClassValueMap.
|
||||
*/
|
||||
final Identity identity = new Identity();
|
||||
|
||||
/**
|
||||
* Current version for retrieving this class value from the cache.
|
||||
* Any number of computeValue calls can be cached in association with one version.
|
||||
* But the version changes when a remove (on any type) is executed.
|
||||
* A version change invalidates all cache entries for the affected ClassValue,
|
||||
* by marking them as stale. Stale cache entries do not force another call
|
||||
* to computeValue, but they do require a synchronized visit to a backing map.
|
||||
* <p>
|
||||
* All user-visible state changes on the ClassValue take place under
|
||||
* a lock inside the synchronized methods of ClassValueMap.
|
||||
* Readers (of ClassValue.get) are notified of such state changes
|
||||
* when this.version is bumped to a new token.
|
||||
* This variable must be volatile so that an unsynchronized reader
|
||||
* will receive the notification without delay.
|
||||
* <p>
|
||||
* If version were not volatile, one thread T1 could persistently hold onto
|
||||
* a stale value this.value == V1, while while another thread T2 advances
|
||||
* (under a lock) to this.value == V2. This will typically be harmless,
|
||||
* but if T1 and T2 interact causally via some other channel, such that
|
||||
* T1's further actions are constrained (in the JMM) to happen after
|
||||
* the V2 event, then T1's observation of V1 will be an error.
|
||||
* <p>
|
||||
* The practical effect of making this.version be volatile is that it cannot
|
||||
* be hoisted out of a loop (by an optimizing JIT) or otherwise cached.
|
||||
* Some machines may also require a barrier instruction to execute
|
||||
* before this.version.
|
||||
*/
|
||||
private volatile Version<T> version = new Version<>(this);
|
||||
Version<T> version() { return version; }
|
||||
void bumpVersion() { version = new Version<>(this); }
|
||||
static class Version<T> {
|
||||
private final ClassValue<T> classValue;
|
||||
private final Entry<T> promise = new Entry<>(this);
|
||||
Version(ClassValue<T> classValue) { this.classValue = classValue; }
|
||||
ClassValue<T> classValue() { return classValue; }
|
||||
Entry<T> promise() { return promise; }
|
||||
boolean isLive() { return classValue.version() == this; }
|
||||
}
|
||||
|
||||
/** One binding of a value to a class via a ClassValue.
|
||||
* States are:<ul>
|
||||
* <li> promise if value == Entry.this
|
||||
* <li> else dead if version == null
|
||||
* <li> else stale if version != classValue.version
|
||||
* <li> else live </ul>
|
||||
* Promises are never put into the cache; they only live in the
|
||||
* backing map while a computeValue call is in flight.
|
||||
* Once an entry goes stale, it can be reset at any time
|
||||
* into the dead state.
|
||||
*/
|
||||
static class Entry<T> extends WeakReference<Version<T>> {
|
||||
final Object value; // usually of type T, but sometimes (Entry)this
|
||||
Entry(Version<T> version, T value) {
|
||||
super(version);
|
||||
this.value = value; // for a regular entry, value is of type T
|
||||
}
|
||||
private void assertNotPromise() { assert(!isPromise()); }
|
||||
/** For creating a promise. */
|
||||
Entry(Version<T> version) {
|
||||
super(version);
|
||||
this.value = this; // for a promise, value is not of type T, but Entry!
|
||||
}
|
||||
/** Fetch the value. This entry must not be a promise. */
|
||||
@SuppressWarnings("unchecked") // if !isPromise, type is T
|
||||
T value() { assertNotPromise(); return (T) value; }
|
||||
boolean isPromise() { return value == this; }
|
||||
Version<T> version() { return get(); }
|
||||
ClassValue<T> classValueOrNull() {
|
||||
Version<T> v = version();
|
||||
return (v == null) ? null : v.classValue();
|
||||
}
|
||||
boolean isLive() {
|
||||
Version<T> v = version();
|
||||
if (v == null) return false;
|
||||
if (v.isLive()) return true;
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
Entry<T> refreshVersion(Version<T> v2) {
|
||||
assertNotPromise();
|
||||
@SuppressWarnings("unchecked") // if !isPromise, type is T
|
||||
Entry<T> e2 = new Entry<>(v2, (T) value);
|
||||
clear();
|
||||
// value = null -- caller must drop
|
||||
return e2;
|
||||
}
|
||||
static final Entry<?> DEAD_ENTRY = new Entry<>(null, null);
|
||||
}
|
||||
|
||||
/** Return the backing map associated with this type. */
|
||||
private static ClassValueMap getMap(Class<?> type) {
|
||||
type.getClass(); // test for null
|
||||
return ROOT.get(type);
|
||||
// racing type.classValueMap : null (blank) => unique ClassValueMap
|
||||
// if a null is observed, a map is created (lazily, synchronously, uniquely)
|
||||
// all further access to that map is synchronized
|
||||
ClassValueMap map = type.classValueMap;
|
||||
if (map != null) return map;
|
||||
return initializeMap(type);
|
||||
}
|
||||
|
||||
private static final Object CRITICAL_SECTION = new Object();
|
||||
private static ClassValueMap initializeMap(Class<?> type) {
|
||||
synchronized (ClassValue.class) {
|
||||
ClassValueMap map = ROOT.get(type);
|
||||
if (map == null)
|
||||
ROOT.put(type, map = new ClassValueMap());
|
||||
ClassValueMap map;
|
||||
synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks
|
||||
// happens about once per type
|
||||
if ((map = type.classValueMap) == null)
|
||||
type.classValueMap = map = new ClassValueMap(type);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static <T> Entry<T> makeEntry(Version<T> explicitVersion, T value) {
|
||||
// Note that explicitVersion might be different from this.version.
|
||||
return new Entry<>(explicitVersion, value);
|
||||
|
||||
// As soon as the Entry is put into the cache, the value will be
|
||||
// reachable via a data race (as defined by the Java Memory Model).
|
||||
// This race is benign, assuming the value object itself can be
|
||||
// read safely by multiple threads. This is up to the user.
|
||||
//
|
||||
// The entry and version fields themselves can be safely read via
|
||||
// a race because they are either final or have controlled states.
|
||||
// If the pointer from the entry to the version is still null,
|
||||
// or if the version goes immediately dead and is nulled out,
|
||||
// the reader will take the slow path and retry under a lock.
|
||||
}
|
||||
|
||||
static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
|
||||
/** Make sure this table contains an Entry for the given key, even if it is empty. */
|
||||
void preInitializeEntry(ClassValue key) {
|
||||
if (!this.containsKey(key))
|
||||
this.put(key, null);
|
||||
}
|
||||
/** Make sure this table contains a non-empty Entry for the given key. */
|
||||
Object initializeEntry(ClassValue key, Object value) {
|
||||
Object prior = this.get(key);
|
||||
if (prior != null) {
|
||||
return unmaskNull(prior);
|
||||
}
|
||||
this.put(key, maskNull(value));
|
||||
return value;
|
||||
// The following class could also be top level and non-public:
|
||||
|
||||
/** A backing map for all ClassValues, relative a single given type.
|
||||
* Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
|
||||
* Also manages an unserialized fast-path cache.
|
||||
*/
|
||||
static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
|
||||
private final Class<?> type;
|
||||
private Entry<?>[] cacheArray;
|
||||
private int cacheLoad, cacheLoadLimit;
|
||||
|
||||
/** Number of entries initially allocated to each type when first used with any ClassValue.
|
||||
* It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
|
||||
* Must be a power of 2.
|
||||
*/
|
||||
private static final int INITIAL_ENTRIES = 32;
|
||||
|
||||
/** Build a backing map for ClassValues, relative the given type.
|
||||
* Also, create an empty cache array and install it on the class.
|
||||
*/
|
||||
ClassValueMap(Class<?> type) {
|
||||
this.type = type;
|
||||
sizeCache(INITIAL_ENTRIES);
|
||||
}
|
||||
|
||||
Object maskNull(Object x) {
|
||||
return x == null ? this : x;
|
||||
Entry<?>[] getCache() { return cacheArray; }
|
||||
|
||||
/** Initiate a query. Store a promise (placeholder) if there is no value yet. */
|
||||
synchronized
|
||||
<T> Entry<T> startEntry(ClassValue<T> classValue) {
|
||||
@SuppressWarnings("unchecked") // one map has entries for all value types <T>
|
||||
Entry<T> e = (Entry<T>) get(classValue.identity);
|
||||
Version<T> v = classValue.version();
|
||||
if (e == null) {
|
||||
e = v.promise();
|
||||
// The presence of a promise means that a value is pending for v.
|
||||
// Eventually, finishEntry will overwrite the promise.
|
||||
put(classValue.identity, e);
|
||||
// Note that the promise is never entered into the cache!
|
||||
return e;
|
||||
} else if (e.isPromise()) {
|
||||
// Somebody else has asked the same question.
|
||||
// Let the races begin!
|
||||
if (e.version() != v) {
|
||||
e = v.promise();
|
||||
put(classValue.identity, e);
|
||||
}
|
||||
return e;
|
||||
} else {
|
||||
// there is already a completed entry here; report it
|
||||
if (e.version() != v) {
|
||||
// There is a stale but valid entry here; make it fresh again.
|
||||
// Once an entry is in the hash table, we don't care what its version is.
|
||||
e = e.refreshVersion(v);
|
||||
put(classValue.identity, e);
|
||||
}
|
||||
// Add to the cache, to enable the fast path, next time.
|
||||
checkCacheLoad();
|
||||
addToCache(classValue, e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
Object unmaskNull(Object x) {
|
||||
return x == this ? null : x;
|
||||
|
||||
/** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */
|
||||
synchronized
|
||||
<T> Entry<T> finishEntry(ClassValue<T> classValue, Entry<T> e) {
|
||||
@SuppressWarnings("unchecked") // one map has entries for all value types <T>
|
||||
Entry<T> e0 = (Entry<T>) get(classValue.identity);
|
||||
if (e == e0) {
|
||||
// We can get here during exception processing, unwinding from computeValue.
|
||||
assert(e.isPromise());
|
||||
remove(classValue.identity);
|
||||
return null;
|
||||
} else if (e0 != null && e0.isPromise() && e0.version() == e.version()) {
|
||||
// If e0 matches the intended entry, there has not been a remove call
|
||||
// between the previous startEntry and now. So now overwrite e0.
|
||||
Version<T> v = classValue.version();
|
||||
if (e.version() != v)
|
||||
e = e.refreshVersion(v);
|
||||
put(classValue.identity, e);
|
||||
// Add to the cache, to enable the fast path, next time.
|
||||
checkCacheLoad();
|
||||
addToCache(classValue, e);
|
||||
return e;
|
||||
} else {
|
||||
// Some sort of mismatch; caller must try again.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove an entry. */
|
||||
synchronized
|
||||
void removeEntry(ClassValue<?> classValue) {
|
||||
// make all cache elements for this guy go stale:
|
||||
if (remove(classValue.identity) != null) {
|
||||
classValue.bumpVersion();
|
||||
removeStaleEntries(classValue);
|
||||
}
|
||||
}
|
||||
|
||||
/** Change the value for an entry. */
|
||||
synchronized
|
||||
<T> void changeEntry(ClassValue<T> classValue, T value) {
|
||||
@SuppressWarnings("unchecked") // one map has entries for all value types <T>
|
||||
Entry<T> e0 = (Entry<T>) get(classValue.identity);
|
||||
Version<T> version = classValue.version();
|
||||
if (e0 != null) {
|
||||
if (e0.version() == version && e0.value() == value)
|
||||
// no value change => no version change needed
|
||||
return;
|
||||
classValue.bumpVersion();
|
||||
removeStaleEntries(classValue);
|
||||
}
|
||||
Entry<T> e = makeEntry(version, value);
|
||||
put(classValue.identity, e);
|
||||
// Add to the cache, to enable the fast path, next time.
|
||||
checkCacheLoad();
|
||||
addToCache(classValue, e);
|
||||
}
|
||||
|
||||
/// --------
|
||||
/// Cache management.
|
||||
/// --------
|
||||
|
||||
// Statics do not need synchronization.
|
||||
|
||||
/** Load the cache entry at the given (hashed) location. */
|
||||
static Entry<?> loadFromCache(Entry<?>[] cache, int i) {
|
||||
// non-racing cache.length : constant
|
||||
// racing cache[i & (mask)] : null <=> Entry
|
||||
return cache[i & (cache.length-1)];
|
||||
// invariant: returned value is null or well-constructed (ready to match)
|
||||
}
|
||||
|
||||
/** Look in the cache, at the home location for the given ClassValue. */
|
||||
static <T> Entry<T> probeHomeLocation(Entry<?>[] cache, ClassValue<T> classValue) {
|
||||
return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache));
|
||||
}
|
||||
|
||||
/** Given that first probe was a collision, retry at nearby locations. */
|
||||
static <T> Entry<T> probeBackupLocations(Entry<?>[] cache, ClassValue<T> classValue) {
|
||||
if (PROBE_LIMIT <= 0) return null;
|
||||
// Probe the cache carefully, in a range of slots.
|
||||
int mask = (cache.length-1);
|
||||
int home = (classValue.hashCodeForCache & mask);
|
||||
Entry<?> e2 = cache[home]; // victim, if we find the real guy
|
||||
if (e2 == null) {
|
||||
return null; // if nobody is at home, no need to search nearby
|
||||
}
|
||||
// assume !classValue.match(e2), but do not assert, because of races
|
||||
int pos2 = -1;
|
||||
for (int i = home + 1; i < home + PROBE_LIMIT; i++) {
|
||||
Entry<?> e = cache[i & mask];
|
||||
if (e == null) {
|
||||
break; // only search within non-null runs
|
||||
}
|
||||
if (classValue.match(e)) {
|
||||
// relocate colliding entry e2 (from cache[home]) to first empty slot
|
||||
cache[home] = e;
|
||||
if (pos2 >= 0) {
|
||||
cache[i & mask] = Entry.DEAD_ENTRY;
|
||||
} else {
|
||||
pos2 = i;
|
||||
}
|
||||
cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT)
|
||||
? e2 // put e2 here if it fits
|
||||
: Entry.DEAD_ENTRY);
|
||||
return classValue.castEntry(e);
|
||||
}
|
||||
// Remember first empty slot, if any:
|
||||
if (!e.isLive() && pos2 < 0) pos2 = i;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** How far out of place is e? */
|
||||
private static int entryDislocation(Entry<?>[] cache, int pos, Entry<?> e) {
|
||||
ClassValue<?> cv = e.classValueOrNull();
|
||||
if (cv == null) return 0; // entry is not live!
|
||||
int mask = (cache.length-1);
|
||||
return (pos - cv.hashCodeForCache) & mask;
|
||||
}
|
||||
|
||||
/// --------
|
||||
/// Below this line all functions are private, and assume synchronized access.
|
||||
/// --------
|
||||
|
||||
private void sizeCache(int length) {
|
||||
assert((length & (length-1)) == 0); // must be power of 2
|
||||
cacheLoad = 0;
|
||||
cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100);
|
||||
cacheArray = new Entry<?>[length];
|
||||
}
|
||||
|
||||
/** Make sure the cache load stays below its limit, if possible. */
|
||||
private void checkCacheLoad() {
|
||||
if (cacheLoad >= cacheLoadLimit) {
|
||||
reduceCacheLoad();
|
||||
}
|
||||
}
|
||||
private void reduceCacheLoad() {
|
||||
removeStaleEntries();
|
||||
if (cacheLoad < cacheLoadLimit)
|
||||
return; // win
|
||||
Entry<?>[] oldCache = getCache();
|
||||
if (oldCache.length > HASH_MASK)
|
||||
return; // lose
|
||||
sizeCache(oldCache.length * 2);
|
||||
for (Entry<?> e : oldCache) {
|
||||
if (e != null && e.isLive()) {
|
||||
addToCache(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove stale entries in the given range.
|
||||
* Should be executed under a Map lock.
|
||||
*/
|
||||
private void removeStaleEntries(Entry<?>[] cache, int begin, int count) {
|
||||
if (PROBE_LIMIT <= 0) return;
|
||||
int mask = (cache.length-1);
|
||||
int removed = 0;
|
||||
for (int i = begin; i < begin + count; i++) {
|
||||
Entry<?> e = cache[i & mask];
|
||||
if (e == null || e.isLive())
|
||||
continue; // skip null and live entries
|
||||
Entry<?> replacement = null;
|
||||
if (PROBE_LIMIT > 1) {
|
||||
// avoid breaking up a non-null run
|
||||
replacement = findReplacement(cache, i);
|
||||
}
|
||||
cache[i & mask] = replacement;
|
||||
if (replacement == null) removed += 1;
|
||||
}
|
||||
cacheLoad = Math.max(0, cacheLoad - removed);
|
||||
}
|
||||
|
||||
/** Clearing a cache slot risks disconnecting following entries
|
||||
* from the head of a non-null run, which would allow them
|
||||
* to be found via reprobes. Find an entry after cache[begin]
|
||||
* to plug into the hole, or return null if none is needed.
|
||||
*/
|
||||
private Entry<?> findReplacement(Entry<?>[] cache, int home1) {
|
||||
Entry<?> replacement = null;
|
||||
int haveReplacement = -1, replacementPos = 0;
|
||||
int mask = (cache.length-1);
|
||||
for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) {
|
||||
Entry<?> e2 = cache[i2 & mask];
|
||||
if (e2 == null) break; // End of non-null run.
|
||||
if (!e2.isLive()) continue; // Doomed anyway.
|
||||
int dis2 = entryDislocation(cache, i2, e2);
|
||||
if (dis2 == 0) continue; // e2 already optimally placed
|
||||
int home2 = i2 - dis2;
|
||||
if (home2 <= home1) {
|
||||
// e2 can replace entry at cache[home1]
|
||||
if (home2 == home1) {
|
||||
// Put e2 exactly where he belongs.
|
||||
haveReplacement = 1;
|
||||
replacementPos = i2;
|
||||
replacement = e2;
|
||||
} else if (haveReplacement <= 0) {
|
||||
haveReplacement = 0;
|
||||
replacementPos = i2;
|
||||
replacement = e2;
|
||||
}
|
||||
// And keep going, so we can favor larger dislocations.
|
||||
}
|
||||
}
|
||||
if (haveReplacement >= 0) {
|
||||
if (cache[(replacementPos+1) & mask] != null) {
|
||||
// Be conservative, to avoid breaking up a non-null run.
|
||||
cache[replacementPos & mask] = (Entry<?>) Entry.DEAD_ENTRY;
|
||||
} else {
|
||||
cache[replacementPos & mask] = null;
|
||||
cacheLoad -= 1;
|
||||
}
|
||||
}
|
||||
return replacement;
|
||||
}
|
||||
|
||||
/** Remove stale entries in the range near classValue. */
|
||||
private void removeStaleEntries(ClassValue<?> classValue) {
|
||||
removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT);
|
||||
}
|
||||
|
||||
/** Remove all stale entries, everywhere. */
|
||||
private void removeStaleEntries() {
|
||||
Entry[] cache = getCache();
|
||||
removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);
|
||||
}
|
||||
|
||||
/** Add the given entry to the cache, in its home location, unless it is out of date. */
|
||||
private <T> void addToCache(Entry<T> e) {
|
||||
ClassValue<T> classValue = e.classValueOrNull();
|
||||
if (classValue != null)
|
||||
addToCache(classValue, e);
|
||||
}
|
||||
|
||||
/** Add the given entry to the cache, in its home location. */
|
||||
private <T> void addToCache(ClassValue<T> classValue, Entry<T> e) {
|
||||
if (PROBE_LIMIT <= 0) return; // do not fill cache
|
||||
// Add e to the cache.
|
||||
Entry<?>[] cache = getCache();
|
||||
int mask = (cache.length-1);
|
||||
int home = classValue.hashCodeForCache & mask;
|
||||
Entry<?> e2 = placeInCache(cache, home, e, false);
|
||||
if (e2 == null) return; // done
|
||||
if (PROBE_LIMIT > 1) {
|
||||
// try to move e2 somewhere else in his probe range
|
||||
int dis2 = entryDislocation(cache, home, e2);
|
||||
int home2 = home - dis2;
|
||||
for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) {
|
||||
if (placeInCache(cache, i2 & mask, e2, true) == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: At this point, e2 is just dropped from the cache.
|
||||
}
|
||||
|
||||
/** Store the given entry. Update cacheLoad, and return any live victim.
|
||||
* 'Gently' means return self rather than dislocating a live victim.
|
||||
*/
|
||||
private Entry<?> placeInCache(Entry<?>[] cache, int pos, Entry<?> e, boolean gently) {
|
||||
Entry<?> e2 = overwrittenEntry(cache[pos]);
|
||||
if (gently && e2 != null) {
|
||||
// do not overwrite a live entry
|
||||
return e;
|
||||
} else {
|
||||
cache[pos] = e;
|
||||
return e2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Note an entry that is about to be overwritten.
|
||||
* If it is not live, quietly replace it by null.
|
||||
* If it is an actual null, increment cacheLoad,
|
||||
* because the caller is going to store something
|
||||
* in its place.
|
||||
*/
|
||||
private <T> Entry<T> overwrittenEntry(Entry<T> e2) {
|
||||
if (e2 == null) cacheLoad += 1;
|
||||
else if (e2.isLive()) return e2;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Percent loading of cache before resize. */
|
||||
private static final int CACHE_LOAD_LIMIT = 67; // 0..100
|
||||
/** Maximum number of probes to attempt. */
|
||||
private static final int PROBE_LIMIT = 6; // 1..
|
||||
// N.B. Set PROBE_LIMIT=0 to disable all fast paths.
|
||||
}
|
||||
}
|
||||
|
@ -818,8 +818,9 @@ public final class Math {
|
||||
return (a >= b) ? a : b;
|
||||
}
|
||||
|
||||
private static long negativeZeroFloatBits = Float.floatToIntBits(-0.0f);
|
||||
private static long negativeZeroDoubleBits = Double.doubleToLongBits(-0.0d);
|
||||
// Use raw bit-wise conversions on guaranteed non-NaN arguments.
|
||||
private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);
|
||||
private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);
|
||||
|
||||
/**
|
||||
* Returns the greater of two {@code float} values. That is,
|
||||
@ -836,9 +837,12 @@ public final class Math {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static float max(float a, float b) {
|
||||
if (a != a) return a; // a is NaN
|
||||
if ((a == 0.0f) && (b == 0.0f)
|
||||
&& (Float.floatToIntBits(a) == negativeZeroFloatBits)) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0f) &&
|
||||
(b == 0.0f) &&
|
||||
(Float.floatToRawIntBits(a) == negativeZeroFloatBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a >= b) ? a : b;
|
||||
@ -859,9 +863,12 @@ public final class Math {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static double max(double a, double b) {
|
||||
if (a != a) return a; // a is NaN
|
||||
if ((a == 0.0d) && (b == 0.0d)
|
||||
&& (Double.doubleToLongBits(a) == negativeZeroDoubleBits)) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0d) &&
|
||||
(b == 0.0d) &&
|
||||
(Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a >= b) ? a : b;
|
||||
@ -910,9 +917,12 @@ public final class Math {
|
||||
* @return the smaller of {@code a} and {@code b}.
|
||||
*/
|
||||
public static float min(float a, float b) {
|
||||
if (a != a) return a; // a is NaN
|
||||
if ((a == 0.0f) && (b == 0.0f)
|
||||
&& (Float.floatToIntBits(b) == negativeZeroFloatBits)) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0f) &&
|
||||
(b == 0.0f) &&
|
||||
(Float.floatToRawIntBits(b) == negativeZeroFloatBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a <= b) ? a : b;
|
||||
@ -933,9 +943,12 @@ public final class Math {
|
||||
* @return the smaller of {@code a} and {@code b}.
|
||||
*/
|
||||
public static double min(double a, double b) {
|
||||
if (a != a) return a; // a is NaN
|
||||
if ((a == 0.0d) && (b == 0.0d)
|
||||
&& (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0d) &&
|
||||
(b == 0.0d) &&
|
||||
(Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a <= b) ? a : b;
|
||||
@ -1900,7 +1913,7 @@ public final class Math {
|
||||
/**
|
||||
* Returns a floating-point power of two in the normal range.
|
||||
*/
|
||||
public static float powerOfTwoF(int n) {
|
||||
static float powerOfTwoF(int n) {
|
||||
assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT);
|
||||
return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) <<
|
||||
(FloatConsts.SIGNIFICAND_WIDTH-1))
|
||||
|
@ -58,8 +58,7 @@ public class Object {
|
||||
*
|
||||
* @return The {@code Class} object that represents the runtime
|
||||
* class of this object.
|
||||
* @see Class Literals, section 15.8.2 of
|
||||
* <cite>The Java™ Language Specification</cite>.
|
||||
* @jls 15.8.2 Class Literals
|
||||
*/
|
||||
public final native Class<?> getClass();
|
||||
|
||||
@ -92,7 +91,7 @@ public class Object {
|
||||
* objects. (This is typically implemented by converting the internal
|
||||
* address of the object into an integer, but this implementation
|
||||
* technique is not required by the
|
||||
* Java<font size="-2"><sup>TM</sup></font> programming language.)
|
||||
* Java™ programming language.)
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
@ -203,7 +202,7 @@ public class Object {
|
||||
* exception at run time.
|
||||
*
|
||||
* @return a clone of this instance.
|
||||
* @exception CloneNotSupportedException if the object's class does not
|
||||
* @throws CloneNotSupportedException if the object's class does not
|
||||
* support the {@code Cloneable} interface. Subclasses
|
||||
* that override the {@code clone} method can also
|
||||
* throw this exception to indicate that an instance cannot
|
||||
@ -264,7 +263,7 @@ public class Object {
|
||||
* <p>
|
||||
* Only one thread at a time can own an object's monitor.
|
||||
*
|
||||
* @exception IllegalMonitorStateException if the current thread is not
|
||||
* @throws IllegalMonitorStateException if the current thread is not
|
||||
* the owner of this object's monitor.
|
||||
* @see java.lang.Object#notifyAll()
|
||||
* @see java.lang.Object#wait()
|
||||
@ -288,7 +287,7 @@ public class Object {
|
||||
* description of the ways in which a thread can become the owner of
|
||||
* a monitor.
|
||||
*
|
||||
* @exception IllegalMonitorStateException if the current thread is not
|
||||
* @throws IllegalMonitorStateException if the current thread is not
|
||||
* the owner of this object's monitor.
|
||||
* @see java.lang.Object#notify()
|
||||
* @see java.lang.Object#wait()
|
||||
@ -368,11 +367,11 @@ public class Object {
|
||||
* a monitor.
|
||||
*
|
||||
* @param timeout the maximum time to wait in milliseconds.
|
||||
* @exception IllegalArgumentException if the value of timeout is
|
||||
* @throws IllegalArgumentException if the value of timeout is
|
||||
* negative.
|
||||
* @exception IllegalMonitorStateException if the current thread is not
|
||||
* @throws IllegalMonitorStateException if the current thread is not
|
||||
* the owner of the object's monitor.
|
||||
* @exception InterruptedException if any thread interrupted the
|
||||
* @throws InterruptedException if any thread interrupted the
|
||||
* current thread before or while the current thread
|
||||
* was waiting for a notification. The <i>interrupted
|
||||
* status</i> of the current thread is cleared when
|
||||
@ -433,12 +432,12 @@ public class Object {
|
||||
* @param timeout the maximum time to wait in milliseconds.
|
||||
* @param nanos additional time, in nanoseconds range
|
||||
* 0-999999.
|
||||
* @exception IllegalArgumentException if the value of timeout is
|
||||
* @throws IllegalArgumentException if the value of timeout is
|
||||
* negative or the value of nanos is
|
||||
* not in the range 0-999999.
|
||||
* @exception IllegalMonitorStateException if the current thread is not
|
||||
* @throws IllegalMonitorStateException if the current thread is not
|
||||
* the owner of this object's monitor.
|
||||
* @exception InterruptedException if any thread interrupted the
|
||||
* @throws InterruptedException if any thread interrupted the
|
||||
* current thread before or while the current thread
|
||||
* was waiting for a notification. The <i>interrupted
|
||||
* status</i> of the current thread is cleared when
|
||||
@ -489,9 +488,9 @@ public class Object {
|
||||
* description of the ways in which a thread can become the owner of
|
||||
* a monitor.
|
||||
*
|
||||
* @exception IllegalMonitorStateException if the current thread is not
|
||||
* @throws IllegalMonitorStateException if the current thread is not
|
||||
* the owner of the object's monitor.
|
||||
* @exception InterruptedException if any thread interrupted the
|
||||
* @throws InterruptedException if any thread interrupted the
|
||||
* current thread before or while the current thread
|
||||
* was waiting for a notification. The <i>interrupted
|
||||
* status</i> of the current thread is cleared when
|
||||
@ -510,7 +509,7 @@ public class Object {
|
||||
* system resources or to perform other cleanup.
|
||||
* <p>
|
||||
* The general contract of {@code finalize} is that it is invoked
|
||||
* if and when the Java<font size="-2"><sup>TM</sup></font> virtual
|
||||
* if and when the Java™ virtual
|
||||
* machine has determined that there is no longer any
|
||||
* means by which this object can be accessed by any thread that has
|
||||
* not yet died, except as a result of an action taken by the
|
||||
@ -549,6 +548,9 @@ public class Object {
|
||||
* ignored.
|
||||
*
|
||||
* @throws Throwable the {@code Exception} raised by this method
|
||||
* @see java.lang.ref.WeakReference
|
||||
* @see java.lang.ref.PhantomReference
|
||||
* @jls 12.6 Finalization of Class Instances
|
||||
*/
|
||||
protected void finalize() throws Throwable { }
|
||||
}
|
||||
|
@ -161,6 +161,8 @@ public final class StrictMath {
|
||||
* in radians.
|
||||
*/
|
||||
public static strictfp double toRadians(double angdeg) {
|
||||
// Do not delegate to Math.toRadians(angdeg) because
|
||||
// this method has the strictfp modifier.
|
||||
return angdeg / 180.0 * PI;
|
||||
}
|
||||
|
||||
@ -176,6 +178,8 @@ public final class StrictMath {
|
||||
* in degrees.
|
||||
*/
|
||||
public static strictfp double toDegrees(double angrad) {
|
||||
// Do not delegate to Math.toDegrees(angrad) because
|
||||
// this method has the strictfp modifier.
|
||||
return angrad * 180.0 / PI;
|
||||
}
|
||||
|
||||
@ -708,7 +712,7 @@ public final class StrictMath {
|
||||
* @return the absolute value of the argument.
|
||||
*/
|
||||
public static int abs(int a) {
|
||||
return (a < 0) ? -a : a;
|
||||
return Math.abs(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -725,7 +729,7 @@ public final class StrictMath {
|
||||
* @return the absolute value of the argument.
|
||||
*/
|
||||
public static long abs(long a) {
|
||||
return (a < 0) ? -a : a;
|
||||
return Math.abs(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -744,7 +748,7 @@ public final class StrictMath {
|
||||
* @return the absolute value of the argument.
|
||||
*/
|
||||
public static float abs(float a) {
|
||||
return (a <= 0.0F) ? 0.0F - a : a;
|
||||
return Math.abs(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -763,7 +767,7 @@ public final class StrictMath {
|
||||
* @return the absolute value of the argument.
|
||||
*/
|
||||
public static double abs(double a) {
|
||||
return (a <= 0.0D) ? 0.0D - a : a;
|
||||
return Math.abs(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -777,7 +781,7 @@ public final class StrictMath {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static int max(int a, int b) {
|
||||
return (a >= b) ? a : b;
|
||||
return Math.max(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -791,13 +795,9 @@ public final class StrictMath {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static long max(long a, long b) {
|
||||
return (a >= b) ? a : b;
|
||||
return Math.max(a, b);
|
||||
}
|
||||
|
||||
// Use raw bit-wise conversions on guaranteed non-NaN arguments.
|
||||
private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);
|
||||
private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);
|
||||
|
||||
/**
|
||||
* Returns the greater of two {@code float} values. That is,
|
||||
* the result is the argument closer to positive infinity. If the
|
||||
@ -813,15 +813,7 @@ public final class StrictMath {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static float max(float a, float b) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0f) &&
|
||||
(b == 0.0f) &&
|
||||
(Float.floatToRawIntBits(a) == negativeZeroFloatBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a >= b) ? a : b;
|
||||
return Math.max(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -839,15 +831,7 @@ public final class StrictMath {
|
||||
* @return the larger of {@code a} and {@code b}.
|
||||
*/
|
||||
public static double max(double a, double b) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0d) &&
|
||||
(b == 0.0d) &&
|
||||
(Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a >= b) ? a : b;
|
||||
return Math.max(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -861,7 +845,7 @@ public final class StrictMath {
|
||||
* @return the smaller of {@code a} and {@code b}.
|
||||
*/
|
||||
public static int min(int a, int b) {
|
||||
return (a <= b) ? a : b;
|
||||
return Math.min(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -875,7 +859,7 @@ public final class StrictMath {
|
||||
* @return the smaller of {@code a} and {@code b}.
|
||||
*/
|
||||
public static long min(long a, long b) {
|
||||
return (a <= b) ? a : b;
|
||||
return Math.min(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -893,15 +877,7 @@ public final class StrictMath {
|
||||
* @return the smaller of {@code a} and {@code b.}
|
||||
*/
|
||||
public static float min(float a, float b) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0f) &&
|
||||
(b == 0.0f) &&
|
||||
(Float.floatToRawIntBits(b) == negativeZeroFloatBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a <= b) ? a : b;
|
||||
return Math.min(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -919,15 +895,7 @@ public final class StrictMath {
|
||||
* @return the smaller of {@code a} and {@code b}.
|
||||
*/
|
||||
public static double min(double a, double b) {
|
||||
if (a != a)
|
||||
return a; // a is NaN
|
||||
if ((a == 0.0d) &&
|
||||
(b == 0.0d) &&
|
||||
(Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) {
|
||||
// Raw conversion ok since NaN can't map to -0.0.
|
||||
return b;
|
||||
}
|
||||
return (a <= b) ? a : b;
|
||||
return Math.min(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -625,7 +625,7 @@ public class Throwable implements Serializable {
|
||||
* at Resource2.close(Resource2.java:20)
|
||||
* at Foo4.main(Foo4.java:5)
|
||||
* Caused by: java.lang.Exception: Rats, you caught me
|
||||
* at Resource2$CloseFailException.<init>(Resource2.java:45)
|
||||
* at Resource2$CloseFailException.<init>(Resource2.java:45)
|
||||
* ... 2 more
|
||||
* </pre>
|
||||
*/
|
||||
|
@ -378,6 +378,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
}
|
||||
|
||||
/** Construct an adapter conversion descriptor for a single-argument conversion. */
|
||||
@SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings
|
||||
private static long makeConv(int convOp, int argnum, int src, int dest) {
|
||||
assert(src == (src & CONV_TYPE_MASK));
|
||||
assert(dest == (dest & CONV_TYPE_MASK));
|
||||
@ -390,6 +391,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
insertStackMove(stackMove)
|
||||
);
|
||||
}
|
||||
@SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings
|
||||
private static long makeDupConv(int convOp, int argnum, int stackMove) {
|
||||
// simple argument motion, requiring one slot to specify
|
||||
assert(convOp == OP_DUP_ARGS || convOp == OP_DROP_ARGS);
|
||||
@ -401,6 +403,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
insertStackMove(stackMove)
|
||||
);
|
||||
}
|
||||
@SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings
|
||||
private static long makeSwapConv(int convOp, int srcArg, byte srcType, int destSlot, byte destType) {
|
||||
// more complex argument motion, requiring two slots to specify
|
||||
assert(convOp == OP_SWAP_ARGS || convOp == OP_ROT_ARGS);
|
||||
@ -411,6 +414,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
(int) destSlot << CONV_VMINFO_SHIFT
|
||||
);
|
||||
}
|
||||
@SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings
|
||||
private static long makeSpreadConv(int convOp, int argnum, int src, int dest, int stackMove) {
|
||||
// spreading or collecting, at a particular slot location
|
||||
assert(convOp == OP_SPREAD_ARGS || convOp == OP_COLLECT_ARGS || convOp == OP_FOLD_ARGS);
|
||||
|
@ -353,7 +353,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
assert(isResolved());
|
||||
}
|
||||
/** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
|
||||
public MemberName(Constructor ctor) {
|
||||
public MemberName(Constructor<?> ctor) {
|
||||
Object[] typeInfo = { void.class, ctor.getParameterTypes() };
|
||||
init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
|
||||
// fill in vmtarget, vmindex while we have ctor in hand:
|
||||
|
@ -275,7 +275,7 @@ mh.invokeExact(System.out, "Hello, world.");
|
||||
* generates a single invokevirtual instruction with
|
||||
* the symbolic type descriptor indicated in the following comment.
|
||||
* In these examples, the helper method {@code assertEquals} is assumed to
|
||||
* be a method which calls {@link Objects.equals java.util.Objects#equals}
|
||||
* be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals }
|
||||
* on its arguments, and asserts that the result is true.
|
||||
*
|
||||
* <h3>Exceptions</h3>
|
||||
|
@ -112,7 +112,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
AllocateObject allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
@ -120,19 +120,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
return fold;
|
||||
}
|
||||
|
||||
static final class AllocateObject<C> extends BoundMethodHandle {
|
||||
static final class AllocateObject /*<C>*/ extends BoundMethodHandle {
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
private final Class<C> allocateClass;
|
||||
private final Class<?> /*<C>*/ allocateClass;
|
||||
|
||||
// for allocation only:
|
||||
private AllocateObject(Class<C> allocateClass) {
|
||||
private AllocateObject(Class<?> /*<C>*/ allocateClass) {
|
||||
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
|
||||
this.allocateClass = allocateClass;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private C allocate() throws InstantiationException {
|
||||
return (C) unsafe.allocateInstance(allocateClass);
|
||||
private Object /*C*/ allocate() throws InstantiationException {
|
||||
return unsafe.allocateInstance(allocateClass);
|
||||
}
|
||||
static final MethodHandle ALLOCATE;
|
||||
static {
|
||||
@ -148,8 +148,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodHandle accessField(MemberName member, boolean isSetter,
|
||||
Class<?> lookupClass) {
|
||||
// Use sun. misc.Unsafe to dig up the dirt on the field.
|
||||
MethodHandle mh = new FieldAccessor(member, isSetter);
|
||||
return mh;
|
||||
FieldAccessor accessor = new FieldAccessor(member, isSetter);
|
||||
return accessor;
|
||||
}
|
||||
|
||||
static
|
||||
@ -175,7 +175,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
return mhs[isSetter ? 1 : 0];
|
||||
}
|
||||
|
||||
static final class FieldAccessor<C,V> extends BoundMethodHandle {
|
||||
static final class FieldAccessor /*<C,V>*/ extends BoundMethodHandle {
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
final Object base; // for static refs only
|
||||
final long offset;
|
||||
@ -190,26 +190,24 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
@Override
|
||||
String debugString() { return addTypeString(name, this); }
|
||||
|
||||
int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
|
||||
void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
|
||||
long getFieldJ(C obj) { return unsafe.getLong(obj, offset); }
|
||||
void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); }
|
||||
float getFieldF(C obj) { return unsafe.getFloat(obj, offset); }
|
||||
void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); }
|
||||
double getFieldD(C obj) { return unsafe.getDouble(obj, offset); }
|
||||
void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); }
|
||||
boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); }
|
||||
void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
|
||||
byte getFieldB(C obj) { return unsafe.getByte(obj, offset); }
|
||||
void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); }
|
||||
short getFieldS(C obj) { return unsafe.getShort(obj, offset); }
|
||||
void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); }
|
||||
char getFieldC(C obj) { return unsafe.getChar(obj, offset); }
|
||||
void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); }
|
||||
@SuppressWarnings("unchecked")
|
||||
V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); }
|
||||
@SuppressWarnings("unchecked")
|
||||
void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
|
||||
int getFieldI(Object /*C*/ obj) { return unsafe.getInt(obj, offset); }
|
||||
void setFieldI(Object /*C*/ obj, int x) { unsafe.putInt(obj, offset, x); }
|
||||
long getFieldJ(Object /*C*/ obj) { return unsafe.getLong(obj, offset); }
|
||||
void setFieldJ(Object /*C*/ obj, long x) { unsafe.putLong(obj, offset, x); }
|
||||
float getFieldF(Object /*C*/ obj) { return unsafe.getFloat(obj, offset); }
|
||||
void setFieldF(Object /*C*/ obj, float x) { unsafe.putFloat(obj, offset, x); }
|
||||
double getFieldD(Object /*C*/ obj) { return unsafe.getDouble(obj, offset); }
|
||||
void setFieldD(Object /*C*/ obj, double x) { unsafe.putDouble(obj, offset, x); }
|
||||
boolean getFieldZ(Object /*C*/ obj) { return unsafe.getBoolean(obj, offset); }
|
||||
void setFieldZ(Object /*C*/ obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
|
||||
byte getFieldB(Object /*C*/ obj) { return unsafe.getByte(obj, offset); }
|
||||
void setFieldB(Object /*C*/ obj, byte x) { unsafe.putByte(obj, offset, x); }
|
||||
short getFieldS(Object /*C*/ obj) { return unsafe.getShort(obj, offset); }
|
||||
void setFieldS(Object /*C*/ obj, short x) { unsafe.putShort(obj, offset, x); }
|
||||
char getFieldC(Object /*C*/ obj) { return unsafe.getChar(obj, offset); }
|
||||
void setFieldC(Object /*C*/ obj, char x) { unsafe.putChar(obj, offset, x); }
|
||||
Object /*V*/ getFieldL(Object /*C*/ obj) { return unsafe.getObject(obj, offset); }
|
||||
void setFieldL(Object /*C*/ obj, Object /*V*/ x) { unsafe.putObject(obj, offset, x); }
|
||||
// cast (V) is OK here, since we wrap convertArguments around the MH.
|
||||
|
||||
static Object staticBase(final MemberName field) {
|
||||
@ -244,8 +242,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
void setStaticS(short x) { unsafe.putShort(base, offset, x); }
|
||||
char getStaticC() { return unsafe.getChar(base, offset); }
|
||||
void setStaticC(char x) { unsafe.putChar(base, offset, x); }
|
||||
V getStaticL() { return (V) unsafe.getObject(base, offset); }
|
||||
void setStaticL(V x) { unsafe.putObject(base, offset, x); }
|
||||
@SuppressWarnings("unchecked") // (V) is for internal clarity but triggers warning
|
||||
Object /*V*/ getStaticL() { return unsafe.getObject(base, offset); }
|
||||
void setStaticL(Object /*V*/ x) { unsafe.putObject(base, offset, x); }
|
||||
|
||||
static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) {
|
||||
String stem;
|
||||
|
@ -150,7 +150,7 @@ public class MethodHandleProxies {
|
||||
}
|
||||
return intfc.cast(Proxy.newProxyInstance(
|
||||
intfc.getClassLoader(),
|
||||
new Class[]{ intfc, WrapperInstance.class },
|
||||
new Class<?>[]{ intfc, WrapperInstance.class },
|
||||
new InvocationHandler() {
|
||||
private Object getArg(String name) {
|
||||
if ((Object)name == "getWrapperInstanceTarget") return target;
|
||||
|
@ -948,10 +948,11 @@ return mh1;
|
||||
public MethodHandle unreflect(Method m) throws IllegalAccessException {
|
||||
MemberName method = new MemberName(m);
|
||||
assert(method.isMethod());
|
||||
if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic());
|
||||
if (m.isAccessible())
|
||||
return MethodHandleImpl.findMethod(method, true, /*no lookupClass*/ null);
|
||||
checkMethod(method.getDeclaringClass(), method, method.isStatic());
|
||||
MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
|
||||
if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh);
|
||||
return mh;
|
||||
return restrictProtectedReceiver(method, mh);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1006,11 +1007,17 @@ return mh1;
|
||||
* is set and {@code asVarargsCollector} fails
|
||||
* @throws NullPointerException if the argument is null
|
||||
*/
|
||||
@SuppressWarnings("rawtypes") // Will be Constructor<?> after JSR 292 MR
|
||||
public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
|
||||
MemberName ctor = new MemberName(c);
|
||||
assert(ctor.isConstructor());
|
||||
if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor);
|
||||
MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
|
||||
MethodHandle rawCtor;
|
||||
if (c.isAccessible()) {
|
||||
rawCtor = MethodHandleImpl.findMethod(ctor, false, /*no lookupClass*/ null);
|
||||
} else {
|
||||
checkAccess(c.getDeclaringClass(), ctor);
|
||||
rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
|
||||
}
|
||||
MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor);
|
||||
return fixVarargs(allocator, rawCtor);
|
||||
}
|
||||
@ -1225,7 +1232,7 @@ return mh1;
|
||||
? "expected a static field"
|
||||
: "expected a non-static field", this);
|
||||
if (trusted)
|
||||
return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
|
||||
return MethodHandleImpl.accessField(field, isSetter, /*no lookupClass*/ null);
|
||||
checkAccess(refc, field);
|
||||
MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
|
||||
return restrictProtectedReceiver(field, mh);
|
||||
|
@ -92,7 +92,7 @@ class FileTreeWalker {
|
||||
(System.getSecurityManager() == null))
|
||||
{
|
||||
BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
|
||||
if (!followLinks || !cached.isSymbolicLink())
|
||||
if (cached != null && (!followLinks || !cached.isSymbolicLink()))
|
||||
attrs = cached;
|
||||
}
|
||||
IOException exc = null;
|
||||
|
@ -1431,7 +1431,7 @@ public final class Files {
|
||||
* <li>It is <i>transitive</i>: for three {@code Paths}
|
||||
* {@code f}, {@code g}, and {@code h}, if {@code isSameFile(f,g)} returns
|
||||
* {@code true} and {@code isSameFile(g,h)} returns {@code true}, then
|
||||
* {@code isSameFile(g,h)} will return return {@code true}.
|
||||
* {@code isSameFile(f,h)} will return return {@code true}.
|
||||
* </ul>
|
||||
*
|
||||
* @param path
|
||||
|
@ -72,7 +72,7 @@ import java.util.Iterator;
|
||||
* directory and is UTF-8 encoded.
|
||||
* <pre>
|
||||
* Path path = FileSystems.getDefault().getPath("logs", "access.log");
|
||||
* BufferReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
|
||||
* BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
|
||||
* </pre>
|
||||
*
|
||||
* <a name="interop"><h4>Interoperability</h4></a>
|
||||
|
@ -1932,20 +1932,22 @@ public class BasicTreeUI extends TreeUI
|
||||
else {
|
||||
Rectangle beginRect = getPathBounds(tree, getPathForRow
|
||||
(tree, beginRow));
|
||||
Rectangle visRect = tree.getVisibleRect();
|
||||
Rectangle testRect = beginRect;
|
||||
int beginY = beginRect.y;
|
||||
int maxY = beginY + visRect.height;
|
||||
if (beginRect != null) {
|
||||
Rectangle visRect = tree.getVisibleRect();
|
||||
Rectangle testRect = beginRect;
|
||||
int beginY = beginRect.y;
|
||||
int maxY = beginY + visRect.height;
|
||||
|
||||
for(int counter = beginRow + 1; counter <= endRow; counter++) {
|
||||
testRect = getPathBounds(tree,
|
||||
getPathForRow(tree, counter));
|
||||
if((testRect.y + testRect.height) > maxY)
|
||||
counter = endRow;
|
||||
for(int counter = beginRow + 1; counter <= endRow; counter++) {
|
||||
testRect = getPathBounds(tree,
|
||||
getPathForRow(tree, counter));
|
||||
if((testRect.y + testRect.height) > maxY)
|
||||
counter = endRow;
|
||||
}
|
||||
tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1,
|
||||
testRect.y + testRect.height-
|
||||
beginY));
|
||||
}
|
||||
tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1,
|
||||
testRect.y + testRect.height-
|
||||
beginY));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3485,7 +3487,7 @@ public class BasicTreeUI extends TreeUI
|
||||
}
|
||||
|
||||
Rectangle bounds = getPathBounds(tree, path);
|
||||
if (y > (bounds.y + bounds.height)) {
|
||||
if (bounds == null || y > (bounds.y + bounds.height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user