Mercurial > hg > arm32-8
changeset 7317:61be834a44f0
Merge
author | asaha |
---|---|
date | Wed, 18 Feb 2015 13:34:14 -0800 |
parents | a5685a980b17 (diff) 35d8318de0b6 (current diff) |
children | 1b158020598d |
files | .hgtags make/hotspot_version src/share/vm/utilities/vmError.cpp |
diffstat | 44 files changed, 607 insertions(+), 135 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Feb 16 11:05:03 2015 -0800 +++ b/.hgtags Wed Feb 18 13:34:14 2015 -0800 @@ -601,3 +601,11 @@ 3afa9cc6e8d537ee456b8e12d1abb1da520b5ddc jdk8u45-b06 5871f3dd9b4a2c4b44e7da2184f4430323e0c04b jdk8u45-b07 35c7330b68e21d0dfaaedaaf74b794fd10606e9c jdk8u45-b08 +d9349fa8822336e0244da0a8448f3e6b2d62741d jdk8u60-b00 +d9349fa8822336e0244da0a8448f3e6b2d62741d hs25.60-b00 +ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01 +5fa73007ceb92a13742fc4a24ec935a6494f8045 hs25.60-b02 +702cc6067686acaa45f7b455b7490edc056c2ae0 jdk8u60-b01 +1f6ba0d2923dadba87aac4ed779dd1ed0161ec2b hs25.60-b03 +38f6080523831ae9a6907c780f2042b82f3213ca jdk8u60-b02 +9d6eb2757167744a17ea71f8b860430d70941eda jdk8u60-b03
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m Mon Feb 16 11:05:03 2015 -0800 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m Wed Feb 18 13:34:14 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -26,7 +26,7 @@ #import <Foundation/Foundation.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> -#include <JavaVM/jni.h> +#include <jni.h> #import <mach/mach.h> #import <mach/mach_types.h>
--- a/agent/src/os/bsd/Makefile Mon Feb 16 11:05:03 2015 -0800 +++ b/agent/src/os/bsd/Makefile Wed Feb 18 13:34:14 2015 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2015, 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 @@ -50,9 +50,9 @@ ps_core.c OBJS = $(SOURCES:.c=.o) OBJSPLUS = MacosxDebuggerLocal.o sadis.o $(OBJS) -EXTINCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers -I. +EXTINCLUDE = -I. EXTCFLAGS = -m64 -D__APPLE__ -framework JavaNativeFoundation -FOUNDATIONFLAGS = -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation +FOUNDATIONFLAGS = -framework Foundation -framework JavaNativeFoundation -framework Security -framework CoreFoundation LIBSA = $(ARCH)/libsaproc.dylib endif # Darwin
--- a/make/bsd/makefiles/saproc.make Mon Feb 16 11:05:03 2015 -0800 +++ b/make/bsd/makefiles/saproc.make Wed Feb 18 13:34:14 2015 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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 @@ -64,9 +64,22 @@ else ifeq ($(OS_VENDOR), Darwin) SASRCFILES = $(DARWIN_NON_STUB_SASRCFILES) - SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation + SALIBS = -g \ + -framework Foundation \ + -framework JavaNativeFoundation \ + -framework Security \ + -framework CoreFoundation #objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles? SAARCH = $(subst -march=i586,,$(ARCHFLAG)) + + # This is needed to locate JavaNativeFoundation.framework + # JDK 8 doesn't have SYSROOT_CFLAGS, so we'll cobble it together here + SA_SYSROOT_FLAGS= + ifneq ($(SDKPATH),) + SA_SYSROOT_FLAGS += -isysroot "$(SDKPATH)" -iframework"$(SDKPATH)/System/Library/Frameworks" + endif + # always needed, even if SDKPATH is empty + SA_SYSROOT_FLAGS += -F"$(SDKPATH)/System/Library/Frameworks/JavaVM.framework/Frameworks" else SASRCFILES = $(SASRCDIR)/StubDebuggerLocal.c SALIBS = @@ -100,14 +113,8 @@ endif SA_LFLAGS += $(LDFLAGS_HASH_STYLE) -ifeq ($(OS_VENDOR), Darwin) - BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \ - -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") \ - -I/System/Library/Frameworks/JavaVM.framework/Headers -else - BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \ - -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") -endif +BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \ + -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ @@ -116,6 +123,7 @@ fi @echo Making SA debugger back-end... $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + $(SA_SYSROOT_FLAGS) \ $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG) \ -I$(SASRCDIR) \ -I$(GENERATED) \
--- a/make/hotspot_version Mon Feb 16 11:05:03 2015 -0800 +++ b/make/hotspot_version Wed Feb 18 13:34:14 2015 -0800 @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015 HS_MAJOR_VER=25 -HS_MINOR_VER=45 -HS_BUILD_NUMBER=02 +HS_MINOR_VER=60 +HS_BUILD_NUMBER=03 JDK_MAJOR_VER=1 JDK_MINOR_VER=8
--- a/make/linux/makefiles/build_vm_def.sh Mon Feb 16 11:05:03 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#!/bin/sh - -# If we're cross compiling use that path for nm -if [ "$CROSS_COMPILE_ARCH" != "" ]; then -NM=$ALT_COMPILER_PATH/nm -else -NM=nm -fi - -$NM --defined-only $* \ - | awk '{ - if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" - if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" - if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";" - }' \ - | sort -u
--- a/make/linux/makefiles/vm.make Mon Feb 16 11:05:03 2015 -0800 +++ b/make/linux/makefiles/vm.make Wed Feb 18 13:34:14 2015 -0800 @@ -245,8 +245,14 @@ rm -f $@ cat $^ > $@ +VMDEF_PAT = ^_ZTV +VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT) +VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT) +VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT) + vm.def: $(Res_Files) $(Obj_Files) - sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@ + $(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \ + awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@ mapfile_ext: rm -f $@
--- a/src/cpu/ppc/vm/frame_ppc.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/ppc/vm/frame_ppc.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -318,3 +318,10 @@ // unused... but returns fp() to minimize changes introduced by 7087445 return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) { + find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp +} +#endif
--- a/src/cpu/sparc/vm/frame_sparc.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -342,7 +342,7 @@ // constructors // Construct an unpatchable, deficient frame -frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) { +void frame::init(intptr_t* sp, address pc, CodeBlob* cb) { #ifdef _LP64 assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp"); #endif @@ -364,6 +364,10 @@ #endif // ASSERT } +frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) { + init(sp, pc, cb); +} + frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) : _sp(sp), _younger_sp(younger_sp), @@ -418,6 +422,13 @@ } } +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + init((intptr_t*)sp, (address)pc, NULL); +} +#endif + bool frame::is_interpreted_frame() const { return Interpreter::contains(pc()); }
--- a/src/cpu/sparc/vm/frame_sparc.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/sparc/vm/frame_sparc.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -164,6 +164,8 @@ enum unpatchable_t { unpatchable }; frame(intptr_t* sp, unpatchable_t, address pc = NULL, CodeBlob* cb = NULL); + void init(intptr_t* sp, address pc, CodeBlob* cb); + // Walk from sp outward looking for old_sp, and return old_sp's predecessor // (i.e. return the sp from the frame where old_sp is the fp). // Register windows are assumed to be flushed for the stack in question.
--- a/src/cpu/x86/vm/frame_x86.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/x86/vm/frame_x86.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -717,3 +717,10 @@ assert(! is_compiled_frame(), "unknown compiled frame size"); return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + init((intptr_t*)sp, (intptr_t*)fp, (address)pc); +} +#endif
--- a/src/cpu/x86/vm/frame_x86.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/x86/vm/frame_x86.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -187,6 +187,8 @@ frame(intptr_t* sp, intptr_t* fp); + void init(intptr_t* sp, intptr_t* fp, address pc); + // accessors for the instance variables // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; }
--- a/src/cpu/x86/vm/frame_x86.inline.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -40,7 +40,7 @@ _deopt_state = unknown; } -inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { +inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = sp; _fp = fp; @@ -58,6 +58,10 @@ } } +inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { + init(sp, fp, pc); +} + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = unextended_sp;
--- a/src/cpu/x86/vm/vm_version_x86.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -570,10 +570,12 @@ static uint cores_per_cpu() { uint result = 1; if (is_intel()) { - if (supports_processor_topology()) { + bool supports_topology = supports_processor_topology(); + if (supports_topology) { result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus / _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus; - } else { + } + if (!supports_topology || result == 0) { result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1); } } else if (is_amd()) {
--- a/src/cpu/zero/vm/frame_zero.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/cpu/zero/vm/frame_zero.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -441,3 +441,10 @@ // unused... but returns fp() to minimize changes introduced by 7087445 return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + Unimplemented(); +} +#endif
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -264,7 +264,7 @@ CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(NULL, NULL, false); } else { return os::get_sender_for_C_frame(&myframe); }
--- a/src/share/vm/ci/ciTypeFlow.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/ci/ciTypeFlow.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -36,6 +36,7 @@ #include "interpreter/bytecodes.hpp" #include "memory/allocation.inline.hpp" #include "opto/compile.hpp" +#include "opto/node.hpp" #include "runtime/deoptimization.hpp" #include "utilities/growableArray.hpp"
--- a/src/share/vm/memory/tenuredGeneration.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/memory/tenuredGeneration.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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,7 +24,6 @@ #include "precompiled.hpp" #include "gc_implementation/shared/collectorCounters.hpp" -#include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/allocation.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" #include "memory/generation.inline.hpp" @@ -34,6 +33,9 @@ #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS +#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#endif TenuredGeneration::TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
--- a/src/share/vm/opto/chaitin.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/chaitin.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -575,6 +575,9 @@ // Peephole remove copies post_allocate_copy_removal(); + // Merge multidefs if multiple defs representing the same value are used in a single block. + merge_multidefs(); + #ifdef ASSERT // Veify the graph after RA. verify(&live_arena);
--- a/src/share/vm/opto/chaitin.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/chaitin.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -578,6 +578,32 @@ // Extend the node to LRG mapping void add_reference( const Node *node, const Node *old_node); + // Record the first use of a def in the block for a register. + class RegDefUse { + Node* _def; + Node* _first_use; + public: + RegDefUse() : _def(NULL), _first_use(NULL) { } + Node* def() const { return _def; } + Node* first_use() const { return _first_use; } + + void update(Node* def, Node* use) { + if (_def != def) { + _def = def; + _first_use = use; + } + } + void clear() { + _def = NULL; + _first_use = NULL; + } + }; + typedef GrowableArray<RegDefUse> RegToDefUseMap; + int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse); + + // Merge nodes that are a part of a multidef lrg and produce the same value within a block. + void merge_multidefs(); + private: static int _final_loads, _final_stores, _final_copies, _final_memoves;
--- a/src/share/vm/opto/escape.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/escape.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -205,6 +205,11 @@ _verify = false; } #endif + // Bytecode analyzer BCEscapeAnalyzer, used for Call nodes + // processing, calls to CI to resolve symbols (types, fields, methods) + // referenced in bytecode. During symbol resolution VM may throw + // an exception which CI cleans and converts to compilation failure. + if (C->failing()) return false; // 2. Finish Graph construction by propagating references to all // java objects through graph.
--- a/src/share/vm/opto/lcm.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/lcm.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -437,8 +437,15 @@ for (DUIterator_Last i2min, i2 = old_tst->last_outs(i2min); i2 >= i2min; --i2) old_tst->last_out(i2)->set_req(0, nul_chk); // Clean-up any dead code - for (uint i3 = 0; i3 < old_tst->req(); i3++) + for (uint i3 = 0; i3 < old_tst->req(); i3++) { + Node* in = old_tst->in(i3); old_tst->set_req(i3, NULL); + if (in->outcnt() == 0) { + // Remove dead input node + in->disconnect_inputs(NULL, C); + block->find_remove(in); + } + } latency_from_uses(nul_chk); latency_from_uses(best);
--- a/src/share/vm/opto/machnode.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/machnode.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -558,6 +558,29 @@ #endif }; +// MachMergeNode is similar to a PhiNode in a sense it merges multiple values, +// however it doesn't have a control input and is more like a MergeMem. +// It is inserted after the register allocation is done to ensure that nodes use single +// definition of a multidef lrg in a block. +class MachMergeNode : public MachIdealNode { +public: + MachMergeNode(Node *n1) { + init_class_id(Class_MachMerge); + add_req(NULL); + add_req(n1); + } + virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); } + virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); } + virtual const class Type *bottom_type() const { return in(1)->bottom_type(); } + virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); } + virtual uint oper_input_base() const { return 1; } + virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } + virtual uint size(PhaseRegAlloc *ra_) const { return 0; } +#ifndef PRODUCT + virtual const char *Name() const { return "MachMerge"; } +#endif +}; + //------------------------------MachBranchNode-------------------------------- // Abstract machine branch Node class MachBranchNode : public MachIdealNode {
--- a/src/share/vm/opto/node.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/node.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -98,6 +98,7 @@ class MachSafePointNode; class MachSpillCopyNode; class MachTempNode; +class MachMergeNode; class Matcher; class MemBarNode; class MemBarStoreStoreNode; @@ -591,6 +592,7 @@ DEFINE_CLASS_ID(MachTemp, Mach, 3) DEFINE_CLASS_ID(MachConstantBase, Mach, 4) DEFINE_CLASS_ID(MachConstant, Mach, 5) + DEFINE_CLASS_ID(MachMerge, Mach, 6) DEFINE_CLASS_ID(Type, Node, 2) DEFINE_CLASS_ID(Phi, Type, 0) @@ -761,6 +763,7 @@ DEFINE_CLASS_QUERY(MachSafePoint) DEFINE_CLASS_QUERY(MachSpillCopy) DEFINE_CLASS_QUERY(MachTemp) + DEFINE_CLASS_QUERY(MachMerge) DEFINE_CLASS_QUERY(Mem) DEFINE_CLASS_QUERY(MemBar) DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/src/share/vm/opto/output.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/output.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -2473,7 +2473,7 @@ if( iop == Op_Con ) continue; // Do not schedule Top if( iop == Op_Node && // Do not schedule PhiNodes, ProjNodes mach->pipeline() == MachNode::pipeline_class() && - !n->is_SpillCopy() ) // Breakpoints, Prolog, etc + !n->is_SpillCopy() && !n->is_MachMerge() ) // Breakpoints, Prolog, etc continue; break; // Funny loop structure to be sure... }
--- a/src/share/vm/opto/phase.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/phase.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -74,6 +74,7 @@ elapsedTimer Phase::_t_computeLive; elapsedTimer Phase::_t_regAllocSplit; elapsedTimer Phase::_t_postAllocCopyRemoval; +elapsedTimer Phase::_t_mergeMultidefs; elapsedTimer Phase::_t_fixupSpills; // Subtimers for _t_output @@ -136,11 +137,12 @@ tty->print_cr (" computeLive : %3.3f sec", Phase::_t_computeLive.seconds()); tty->print_cr (" regAllocSplit : %3.3f sec", Phase::_t_regAllocSplit.seconds()); tty->print_cr (" postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds()); + tty->print_cr (" mergeMultidefs: %3.3f sec", Phase::_t_mergeMultidefs.seconds()); tty->print_cr (" fixupSpills : %3.3f sec", Phase::_t_fixupSpills.seconds()); double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() + Phase::_t_buildIFGphysical.seconds() + Phase::_t_computeLive.seconds() + Phase::_t_regAllocSplit.seconds() + Phase::_t_fixupSpills.seconds() + - Phase::_t_postAllocCopyRemoval.seconds(); + Phase::_t_postAllocCopyRemoval.seconds() + Phase::_t_mergeMultidefs.seconds(); double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0)); tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc); }
--- a/src/share/vm/opto/phase.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/phase.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -109,6 +109,7 @@ static elapsedTimer _t_computeLive; static elapsedTimer _t_regAllocSplit; static elapsedTimer _t_postAllocCopyRemoval; + static elapsedTimer _t_mergeMultidefs; static elapsedTimer _t_fixupSpills; // Subtimers for _t_output
--- a/src/share/vm/opto/postaloc.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/postaloc.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -263,20 +263,6 @@ // intermediate copies might be illegal, i.e., value is stored down to stack // then reloaded BUT survives in a register the whole way. Node *val = skip_copies(n->in(k)); - - if (val == x && nk_idx != 0 && - regnd[nk_reg] != NULL && regnd[nk_reg] != x && - _lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) { - // When rematerialzing nodes and stretching lifetimes, the - // allocator will reuse the original def for multidef LRG instead - // of the current reaching def because it can't know it's safe to - // do so. After allocation completes if they are in the same LRG - // then it should use the current reaching def instead. - n->set_req(k, regnd[nk_reg]); - blk_adjust += yank_if_dead(val, current_block, &value, ®nd); - val = skip_copies(n->in(k)); - } - if (val == x) return blk_adjust; // No progress? int n_regs = RegMask::num_registers(val->ideal_reg()); @@ -382,6 +368,95 @@ return false; } +// The algorithms works as follows: +// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k +// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've +// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their +// current reaching definitions (we track only multidefs though). With each definition we also associate the first +// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the +// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute +// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg +// as they get encountered with the merge node and keep adding these defs to the merge inputs. +void PhaseChaitin::merge_multidefs() { + NOT_PRODUCT( Compile::TracePhase t3("mergeMultidefs", &_t_mergeMultidefs, TimeCompiler); ) + ResourceMark rm; + // Keep track of the defs seen in registers and collect their uses in the block. + RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse()); + for (uint i = 0; i < _cfg.number_of_blocks(); i++) { + Block* block = _cfg.get_block(i); + for (uint j = 1; j < block->number_of_nodes(); j++) { + Node* n = block->get_node(j); + if (n->is_Phi()) continue; + for (uint k = 1; k < n->req(); k++) { + j += possibly_merge_multidef(n, k, block, reg2defuse); + } + // Null out the value produced by the instruction itself, since we're only interested in defs + // implicitly defined by the uses. We are actually interested in tracking only redefinitions + // of the multidef lrgs in the same register. For that matter it's enough to track changes in + // the base register only and ignore other effects of multi-register lrgs and fat projections. + // It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of + // those our register is guaranteed to be used by another lrg and we won't attempt to merge it. + uint lrg = _lrg_map.live_range_id(n); + if (lrg > 0 && lrgs(lrg).is_multidef()) { + OptoReg::Name reg = lrgs(lrg).reg(); + reg2defuse.at(reg).clear(); + } + } + // Clear reg->def->use tracking for the next block + for (int j = 0; j < reg2defuse.length(); j++) { + reg2defuse.at(j).clear(); + } + } +} + +int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) { + int blk_adjust = 0; + + uint lrg = _lrg_map.live_range_id(n->in(k)); + if (lrg > 0 && lrgs(lrg).is_multidef()) { + OptoReg::Name reg = lrgs(lrg).reg(); + + Node* def = reg2defuse.at(reg).def(); + if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) { + // Same lrg but different node, we have to merge. + MachMergeNode* merge; + if (def->is_MachMerge()) { // is it already a merge? + merge = def->as_MachMerge(); + } else { + merge = new (C) MachMergeNode(def); + + // Insert the merge node into the block before the first use. + uint use_index = block->find_node(reg2defuse.at(reg).first_use()); + block->insert_node(merge, use_index++); + _cfg.map_node_to_block(merge, block); + + // Let the allocator know about the new node, use the same lrg + _lrg_map.extend(merge->_idx, lrg); + blk_adjust++; + + // Fixup all the uses (there is at least one) that happened between the first + // use and before the current one. + for (; use_index < block->number_of_nodes(); use_index++) { + Node* use = block->get_node(use_index); + if (use == n) { + break; + } + use->replace_edge(def, merge); + } + } + if (merge->find_edge(n->in(k)) == -1) { + merge->add_req(n->in(k)); + } + n->set_req(k, merge); + } + + // update the uses + reg2defuse.at(reg).update(n->in(k), n); + } + + return blk_adjust; +} + //------------------------------post_allocate_copy_removal--------------------- // Post-Allocation peephole copy removal. We do this in 1 pass over the
--- a/src/share/vm/opto/stringopts.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/opto/stringopts.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -1507,10 +1507,12 @@ } case StringConcat::StringMode: { const Type* type = kit.gvn().type(arg); + Node* count = NULL; if (type == TypePtr::NULL_PTR) { // replace the argument with the null checked version arg = null_string; sc->set_argument(argi, arg); + count = kit.load_String_length(kit.control(), arg); } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) { // s = s != null ? s : "null"; // length = length + (s.count - s.offset); @@ -1533,10 +1535,13 @@ // replace the argument with the null checked version arg = phi; sc->set_argument(argi, arg); + count = kit.load_String_length(kit.control(), arg); + } else { + // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP + // kit.control might be a different test, that can be hoisted above the actual nullcheck + // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck. + count = kit.load_String_length(NULL, arg); } - - Node* count = kit.load_String_length(kit.control(), arg); - length = __ AddI(length, count); string_sizes->init_req(argi, NULL); break;
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -68,11 +68,11 @@ ~JvmtiConstantPoolReconstituter() { if (_symmap != NULL) { - os::free(_symmap, mtClass); + delete _symmap; _symmap = NULL; } if (_classmap != NULL) { - os::free(_classmap, mtClass); + delete _classmap; _classmap = NULL; } }
--- a/src/share/vm/prims/jvmtiTagMap.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -1045,10 +1045,16 @@ { assert(str->klass() == SystemDictionary::String_klass(), "not a string"); + typeArrayOop s_value = java_lang_String::value(str); + + // JDK-6584008: the value field may be null if a String instance is + // partially constructed. + if (s_value == NULL) { + return 0; + } // get the string value and length // (string value may be offset from the base) int s_len = java_lang_String::length(str); - typeArrayOop s_value = java_lang_String::value(str); int s_offset = java_lang_String::offset(str); jchar* value; if (s_len > 0) {
--- a/src/share/vm/prims/unsafe.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/prims/unsafe.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -322,10 +322,33 @@ UNSAFE_END #ifndef SUPPORTS_NATIVE_CX8 -// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions -// Volatile long versions must use locks if !VM_Version::supports_cx8(). -// support_cx8 is a surrogate for 'supports atomic long memory ops'. +// VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. +// +// On platforms which do not support atomic compare-and-swap of jlong (8 byte) +// values we have to use a lock-based scheme to enforce atomicity. This has to be +// applied to all Unsafe operations that set the value of a jlong field. Even so +// the compareAndSwapLong operation will not be atomic with respect to direct stores +// to the field from Java code. It is important therefore that any Java code that +// utilizes these Unsafe jlong operations does not perform direct stores. To permit +// direct loads of the field from Java code we must also use Atomic::store within the +// locked regions. And for good measure, in case there are direct stores, we also +// employ Atomic::load within those regions. Note that the field in question must be +// volatile and so must have atomic load/store accesses applied at the Java level. +// +// The locking scheme could utilize a range of strategies for controlling the locking +// granularity: from a lock per-field through to a single global lock. The latter is +// the simplest and is used for the current implementation. Note that the Java object +// that contains the field, can not, in general, be used for locking. To do so can lead +// to deadlocks as we may introduce locking into what appears to the Java code to be a +// lock-free path. +// +// As all the locked-regions are very short and themselves non-blocking we can treat +// them as leaf routines and elide safepoint checks (ie we don't perform any thread +// state transitions even when blocking for the lock). Note that if we do choose to +// add safepoint checks and thread state transitions, we must ensure that we calculate +// the address of the field _after_ we have acquired the lock, else the object may have +// been moved by the GC UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetLongVolatile"); @@ -337,8 +360,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - jlong value = *addr; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong value = Atomic::load(addr); return value; } } @@ -353,8 +376,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - *addr = x; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } } UNSAFE_END @@ -463,8 +486,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - *addr = x; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } } #endif @@ -1213,14 +1236,19 @@ UnsafeWrapper("Unsafe_CompareAndSwapLong"); Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); +#ifdef SUPPORTS_NATIVE_CX8 + return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; +#else if (VM_Version::supports_cx8()) return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; else { jboolean success = false; - ObjectLocker ol(p, THREAD); - if (*addr == e) { *addr = x; success = true; } + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); + if (val == e) { Atomic::store(x, addr); success = true; } return success; } +#endif UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
--- a/src/share/vm/runtime/frame.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/runtime/frame.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -91,6 +91,15 @@ // Constructors frame(); +#ifndef PRODUCT + // This is a generic constructor which is only used by pns() in debug.cpp. + // pns (i.e. print native stack) uses this constructor to create a starting + // frame for stack walking. The implementation of this constructor is platform + // dependent (i.e. SPARC doesn't need an 'fp' argument an will ignore it) but + // we want to keep the signature generic because pns() is shared code. + frame(void* sp, void* fp, void* pc); +#endif + // Accessors // pc: Returns the pc at which this frame will continue normally.
--- a/src/share/vm/runtime/mutexLocker.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/runtime/mutexLocker.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -135,6 +135,10 @@ Mutex* JfrThreadGroups_lock = NULL; #endif +#ifndef SUPPORTS_NATIVE_CX8 +Mutex* UnsafeJlong_lock = NULL; +#endif + #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; static int _num_mutex; @@ -286,6 +290,9 @@ def(JfrStacktrace_lock , Mutex, special, true ); #endif +#ifndef SUPPORTS_NATIVE_CX8 + def(UnsafeJlong_lock , Mutex, special, false); +#endif } GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/src/share/vm/runtime/mutexLocker.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/runtime/mutexLocker.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -151,6 +151,10 @@ extern Mutex* JfrThreadGroups_lock; // protects JFR access to Thread Groups #endif +#ifndef SUPPORTS_NATIVE_CX8 +extern Mutex* UnsafeJlong_lock; // provides Unsafe atomic updates to jlongs on platforms that don't support cx8 +#endif + // 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 // an object lock, and the two do not interoperate. Do not use Mutex-based
--- a/src/share/vm/utilities/debug.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/utilities/debug.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -666,6 +666,13 @@ tty->print_cr(" pm(int pc) - print Method* given compiled PC"); tty->print_cr(" findm(intptr_t pc) - finds Method*"); tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); + tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g."); + tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or"); + tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or"); + tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or"); + tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC"); + tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()"); + tty->print_cr(" - in dbx do 'frame 1' before calling pns()"); tty->print_cr("misc."); tty->print_cr(" flush() - flushes the log file"); @@ -678,3 +685,56 @@ } #endif // !PRODUCT + +void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size) { + + // see if it's a valid frame + if (fr.pc()) { + st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); + + int count = 0; + while (count++ < StackPrintLimit) { + fr.print_on_error(st, buf, buf_size); + st->cr(); + // Compiled code may use EBP register on x86 so it looks like + // non-walkable C frame. Use frame.sender() for java frames. + if (t && t->is_Java_thread()) { + // Catch very first native frame by using stack address. + // For JavaThread stack_base and stack_size should be set. + if (!t->on_local_stack((address)(fr.real_fp() + 1))) { + break; + } + if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) { + RegisterMap map((JavaThread*)t, false); // No update + fr = fr.sender(&map); + } else { + fr = os::get_sender_for_C_frame(&fr); + } + } else { + // is_first_C_frame() does only simple checks for frame pointer, + // it will pass if java compiled code has a pointer in EBP. + if (os::is_first_C_frame(&fr)) break; + fr = os::get_sender_for_C_frame(&fr); + } + } + + if (count > StackPrintLimit) { + st->print_cr("...<more frames>..."); + } + + st->cr(); + } +} + +#ifndef PRODUCT + +extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack + Command c("pns"); + static char buf[O_BUFLEN]; + Thread* t = ThreadLocalStorage::get_thread_slow(); + // Call generic frame constructor (certain arguments may be ignored) + frame fr(sp, fp, pc); + print_native_stack(tty, fr, t, buf, sizeof(buf)); +} + +#endif // !PRODUCT
--- a/src/share/vm/utilities/debug.hpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/utilities/debug.hpp Wed Feb 18 13:34:14 2015 -0800 @@ -265,4 +265,7 @@ void pd_ps(frame f); void pd_obfuscate_location(char *buf, size_t buflen); +class outputStream; +void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size); + #endif // SHARE_VM_UTILITIES_DEBUG_HPP
--- a/src/share/vm/utilities/vmError.cpp Mon Feb 16 11:05:03 2015 -0800 +++ b/src/share/vm/utilities/vmError.cpp Wed Feb 18 13:34:14 2015 -0800 @@ -576,7 +576,7 @@ STEP(120, "(printing native stack)" ) - if (_verbose) { + if (_verbose) { if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) { // We have printed the native stack in platform-specific code // Windows/x64 needs special handling. @@ -584,43 +584,7 @@ frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); - // see if it's a valid frame - if (fr.pc()) { - st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - - - int count = 0; - while (count++ < StackPrintLimit) { - fr.print_on_error(st, buf, sizeof(buf)); - st->cr(); - // Compiled code may use EBP register on x86 so it looks like - // non-walkable C frame. Use frame.sender() for java frames. - if (_thread && _thread->is_Java_thread()) { - // Catch very first native frame by using stack address. - // For JavaThread stack_base and stack_size should be set. - if (!_thread->on_local_stack((address)(fr.sender_sp() + 1))) { - break; - } - if (fr.is_java_frame()) { - RegisterMap map((JavaThread*)_thread, false); // No update - fr = fr.sender(&map); - } else { - fr = os::get_sender_for_C_frame(&fr); - } - } else { - // is_first_C_frame() does only simple checks for frame pointer, - // it will pass if java compiled code has a pointer in EBP. - if (os::is_first_C_frame(&fr)) break; - fr = os::get_sender_for_C_frame(&fr); - } - } - - if (count > StackPrintLimit) { - st->print_cr("...<more frames>..."); - } - - st->cr(); - } + print_native_stack(st, fr, _thread, buf, sizeof(buf)); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/stringopts/TestOptimizeStringConcat.java Wed Feb 18 13:34:14 2015 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright 2015 SAP AG. 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. + */ + +/* + * @test + * @bug 8068909 + * @key regression + * @summary test that string optimizations produce code, that doesn't lead to a crash. + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat + * @author axel.siebenborn@sap.com + */ +public class TestOptimizeStringConcat { + + static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) { + String rc = null; + + int maxchar = 99999; + int minchar = 1; + if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) { + rc = "internal error"; + } else { + if (value == null) { + rc = "the value null is not allowed, it is missing"; + } else if (value != null && minchar > 0 && value.trim().equals("")) { + rc = "the value must not be empty"; + } else if (value != null) { + if (value.length() < minchar || value.length() > maxchar) { + if (rc == null) { + rc = "the value length must be between +minchar+ and +maxchar"; + } + } + char[] _value = value.toCharArray(); + boolean dotfound = false; + int i = 1; + if (_value[i] == '.' && !dotfound) { + dotfound = true; + } else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) { + if (rc == null) { + rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'"; + } else { + rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'"; + } + } else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) { + if (rc == null) { + rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'"; + } else { + rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'"; + } + } + } + } + + if (rc != null) { + System.out.println(logmsg + " ==> " + rc); + return false; + } + return true; + } + + public static void main(String[] args) { + boolean failed = false; + for (int i = 0; i < 10000; i++) { + failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition"); + failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition"); + failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition"); + } + System.out.println(failed); + } +}
--- a/test/runtime/6888954/vmerrors.sh Mon Feb 16 11:05:03 2015 -0800 +++ b/test/runtime/6888954/vmerrors.sh Wed Feb 18 13:34:14 2015 -0800 @@ -1,4 +1,4 @@ -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -61,11 +61,12 @@ # EXCEPTION_ACCESS_VIOLATION - Win-* # SIGBUS - Solaris SPARC-64 # SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-* +# SIGILL - Aix # # Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-* # gets its signal at a PC in test_error_handler(). # -bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=' +bad_func_ptr_re='(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc=' guarantee_re='guarantee[(](str|num).*failed: *' fatal_re='fatal error: *' tail_1='.*expected null'
--- a/test/serviceability/sa/jmap-hashcode/Test8028623.java Mon Feb 16 11:05:03 2015 -0800 +++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java Wed Feb 18 13:34:14 2015 -0800 @@ -33,20 +33,25 @@ import com.oracle.java.testlibrary.JDKToolLauncher; import com.oracle.java.testlibrary.OutputBuffer; +import com.oracle.java.testlibrary.Platform; import com.oracle.java.testlibrary.ProcessTools; import java.io.File; public class Test8028623 { - public static int à = 1; + public static int \u00CB = 1; public static String dumpFile = "heap.out"; public static void main (String[] args) { - System.out.println(Ã); + System.out.println(\u00CB); try { + if (!Platform.shouldSAAttach()) { + System.out.println("SA attach not expected to work - test skipped."); + return; + } int pid = ProcessTools.getProcessId(); JDKToolLauncher jmap = JDKToolLauncher.create("jmap") .addToolArg("-F")
--- a/test/test_env.sh Mon Feb 16 11:05:03 2015 -0800 +++ b/test/test_env.sh Wed Feb 18 13:34:14 2015 -0800 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2015, 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 @@ -53,7 +53,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux | Darwin ) + AIX | Darwin | Linux | SunOS ) NULL=/dev/null PS=":" FS="/" @@ -130,26 +130,31 @@ fi VM_OS="unknown" -grep "solaris" vm_version.out > ${NULL} +grep "aix" vm_version.out > ${NULL} if [ $? = 0 ] then - VM_OS="solaris" + VM_OS="aix" +fi +grep "bsd" vm_version.out > ${NULL} +if [ $? = 0 ] +then + VM_OS="bsd" fi grep "linux" vm_version.out > ${NULL} if [ $? = 0 ] then VM_OS="linux" fi +grep "solaris" vm_version.out > ${NULL} +if [ $? = 0 ] +then + VM_OS="solaris" +fi grep "windows" vm_version.out > ${NULL} if [ $? = 0 ] then VM_OS="windows" fi -grep "bsd" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_OS="bsd" -fi VM_CPU="unknown" grep "sparc" vm_version.out > ${NULL}
--- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Mon Feb 16 11:05:03 2015 -0800 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Wed Feb 18 13:34:14 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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,12 +23,15 @@ package com.oracle.java.testlibrary; +import com.oracle.java.testlibrary.Utils; + public class Platform { private static final String osName = System.getProperty("os.name"); private static final String dataModel = System.getProperty("sun.arch.data.model"); private static final String vmVersion = System.getProperty("java.vm.version"); private static final String osArch = System.getProperty("os.arch"); private static final String vmName = System.getProperty("java.vm.name"); + private static final String userName = System.getProperty("user.name"); public static boolean isClient() { return vmName.endsWith(" Client VM"); @@ -58,6 +61,18 @@ return dataModel.equals("64"); } + public static boolean isAix() { + return isOs("aix"); + } + + public static boolean isLinux() { + return isOs("linux"); + } + + public static boolean isOSX() { + return isOs("mac"); + } + public static boolean isSolaris() { return isOs("sunos"); } @@ -66,14 +81,6 @@ return isOs("win"); } - public static boolean isOSX() { - return isOs("mac"); - } - - public static boolean isLinux() { - return isOs("linux"); - } - private static boolean isOs(String osname) { return osName.toLowerCase().startsWith(osname.toLowerCase()); } @@ -121,4 +128,58 @@ return osArch; } + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. + */ + public static boolean shouldSAAttach() throws Exception { + + if (isAix()) { + return false; // SA not implemented. + } else if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". Then expect permission to attach + * if we are root, so return true. Then return false for an expected denial + * if "ptrace_scope" is 1, and true otherwise. + */ + public static boolean canPtraceAttachLinux() throws Exception { + + // SELinux deny_ptrace: + String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace"); + if (deny_ptrace != null && deny_ptrace.contains("1")) { + // ptrace will be denied: + return false; + } + + if (userName.equals("root")) { + return true; + } + + // ptrace_scope: + String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope"); + if (ptrace_scope != null && ptrace_scope.contains("1")) { + // ptrace will be denied: + return false; + } + + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + public static boolean canAttachOSX() throws Exception { + return userName.equals("root"); + } }
--- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java Mon Feb 16 11:05:03 2015 -0800 +++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java Wed Feb 18 13:34:14 2015 -0800 @@ -299,6 +299,35 @@ } /** + * Return the contents of the named file as a single String, + * or null if not found. + * @param filename name of the file to read + * @return String contents of file, or null if file not found. + */ + public static String fileAsString(String filename) { + StringBuilder result = new StringBuilder(); + try { + File file = new File(filename); + if (file.exists()) { + BufferedReader reader = new BufferedReader(new FileReader(file)); + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } + result.append(line).append("\n"); + } + } else { + // Does not exist: + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } + return result.toString(); + } + + /** * @return Unsafe instance. */ public static synchronized Unsafe getUnsafe() {