From be4035c60a4551e5a51ecca973b3dc42664cdee8 Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Mon, 26 Jan 2015 10:32:35 +0100 Subject: [PATCH 01/79] 8030646: track collection set membership in one place Reviewed-by: tschatzl, jwilhelm --- .../vm/gc_implementation/g1/g1CollectedHeap.cpp | 10 +++++----- .../vm/gc_implementation/g1/g1CollectedHeap.hpp | 17 ++++++++--------- .../g1/g1CollectedHeap.inline.hpp | 6 +++++- .../gc_implementation/g1/g1CollectorPolicy.cpp | 9 +++------ .../vm/gc_implementation/g1/g1InCSetState.hpp | 3 +++ .../vm/gc_implementation/g1/heapRegion.cpp | 3 +-- .../vm/gc_implementation/g1/heapRegion.hpp | 11 ++--------- .../gc_implementation/g1/heapRegion.inline.hpp | 4 ++++ 8 files changed, 31 insertions(+), 32 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index f694d18a7f2..18deaa19b1b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3538,7 +3538,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { r->rem_set()->clear_locked(); } assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty."); - g1h->register_humongous_region_with_in_cset_fast_test(region_idx); + g1h->register_humongous_region_with_cset(region_idx); _candidate_humongous++; } _total_humongous++; @@ -3552,7 +3552,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { void flush_rem_set_entries() { _dcq.flush(); } }; -void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { +void G1CollectedHeap::register_humongous_regions_with_cset() { if (!G1EagerReclaimHumongousObjects) { g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0); return; @@ -3859,7 +3859,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info); - register_humongous_regions_with_in_cset_fast_test(); + register_humongous_regions_with_cset(); assert(check_cset_fast_test(), "Inconsistency in the InCSetState table."); @@ -6077,7 +6077,7 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& e HeapRegion* next = cur->next_in_collection_set(); assert(cur->in_collection_set(), "bad CS"); cur->set_next_in_collection_set(NULL); - cur->set_in_collection_set(false); + clear_in_cset(cur); if (cur->is_young()) { int index = cur->young_index_in_cset(); @@ -6303,7 +6303,7 @@ void G1CollectedHeap::abandon_collection_set(HeapRegion* cs_head) { HeapRegion* next = cur->next_in_collection_set(); assert(cur->in_collection_set(), "bad CS"); cur->set_next_in_collection_set(NULL); - cur->set_in_collection_set(false); + clear_in_cset(cur); cur->set_young_index_in_cset(-1); cur = next; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 42a7229a9e0..edf78a141b7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -645,23 +645,21 @@ public: // is considered a candidate for eager reclamation. bool humongous_region_is_candidate(uint index); // Register the given region to be part of the collection set. - inline void register_humongous_region_with_in_cset_fast_test(uint index); + inline void register_humongous_region_with_cset(uint index); // Register regions with humongous objects (actually on the start region) in // the in_cset_fast_test table. - void register_humongous_regions_with_in_cset_fast_test(); + void register_humongous_regions_with_cset(); // We register a region with the fast "in collection set" test. We // simply set to true the array slot corresponding to this region. - void register_young_region_with_in_cset_fast_test(HeapRegion* r) { + void register_young_region_with_cset(HeapRegion* r) { _in_cset_fast_test.set_in_young(r->hrm_index()); } - void register_old_region_with_in_cset_fast_test(HeapRegion* r) { + void register_old_region_with_cset(HeapRegion* r) { _in_cset_fast_test.set_in_old(r->hrm_index()); } - - // This is a fast test on whether a reference points into the - // collection set or not. Assume that the reference - // points into the heap. - inline bool in_cset_fast_test(oop obj); + void clear_in_cset(const HeapRegion* hr) { + _in_cset_fast_test.clear(hr); + } void clear_cset_fast_test() { _in_cset_fast_test.clear(); @@ -1246,6 +1244,7 @@ public: // set. Slow implementation. inline bool obj_in_cs(oop obj); + inline bool is_in_cset(const HeapRegion *hr); inline bool is_in_cset(oop obj); inline bool is_in_cset_or_humongous(const oop obj); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index 1ca08b98851..d029e08a854 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -234,6 +234,10 @@ inline bool G1CollectedHeap::is_in_cset(oop obj) { return ret; } +bool G1CollectedHeap::is_in_cset(const HeapRegion* hr) { + return _in_cset_fast_test.is_in_cset(hr); +} + bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) { return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj); } @@ -242,7 +246,7 @@ InCSetState G1CollectedHeap::in_cset_state(const oop obj) { return _in_cset_fast_test.at((HeapWord*)obj); } -void G1CollectedHeap::register_humongous_region_with_in_cset_fast_test(uint index) { +void G1CollectedHeap::register_humongous_region_with_cset(uint index) { _in_cset_fast_test.set_humongous(index); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 21cbf9fb57e..fbb52ad85e4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1607,11 +1607,10 @@ void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) { assert(hr->is_old(), "the region should be old"); assert(!hr->in_collection_set(), "should not already be in the CSet"); - hr->set_in_collection_set(true); + _g1->register_old_region_with_cset(hr); hr->set_next_in_collection_set(_collection_set); _collection_set = hr; _collection_set_bytes_used_before += hr->used(); - _g1->register_old_region_with_in_cset_fast_test(hr); size_t rs_length = hr->rem_set()->occupied(); _recorded_rs_lengths += rs_length; _old_cset_region_length += 1; @@ -1741,10 +1740,8 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) { _inc_cset_max_finger = MAX2(_inc_cset_max_finger, hr_end); assert(!hr->in_collection_set(), "invariant"); - hr->set_in_collection_set(true); - assert( hr->next_in_collection_set() == NULL, "invariant"); - - _g1->register_young_region_with_in_cset_fast_test(hr); + _g1->register_young_region_with_cset(hr); + assert(hr->next_in_collection_set() == NULL, "invariant"); } // Add the region at the RHS of the incremental cset diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp index f13eaa0ae82..8cc45ad15e5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP +#include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/g1BiasedArray.hpp" #include "memory/allocation.hpp" @@ -125,8 +126,10 @@ class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArrayhrm_index()).is_in_cset(); } InCSetState at(HeapWord* addr) const { return get_by_address(addr); } void clear() { G1BiasedMappedArray::clear(); } + void clear(const HeapRegion* hr) { return set_by_index(hr->hrm_index(), InCSetState::NotInCSet); } }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 3ad7f190563..2eb23388ef5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -162,7 +162,7 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { "we should have already filtered out humongous regions"); assert(_end == orig_end(), "we should have already filtered out humongous regions"); - assert(!_in_collection_set, + assert(!in_collection_set(), err_msg("Should not clear heap region %u in the collection set", hrm_index())); set_allocation_context(AllocationContext::system()); @@ -262,7 +262,6 @@ HeapRegion::HeapRegion(uint hrm_index, _hrm_index(hrm_index), _allocation_context(AllocationContext::system()), _humongous_start_region(NULL), - _in_collection_set(false), _next_in_special_set(NULL), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index e7342cdacf4..1d78eae7adf 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -236,8 +236,6 @@ class HeapRegion: public G1OffsetTableContigSpace { // For a humongous region, region in which it starts. HeapRegion* _humongous_start_region; - // True iff the region is in current collection_set. - bool _in_collection_set; // True iff an attempt to evacuate an object in the region failed. bool _evacuation_failed; @@ -487,13 +485,8 @@ class HeapRegion: public G1OffsetTableContigSpace { return _rem_set; } - // True iff the region is in current collection_set. - bool in_collection_set() const { - return _in_collection_set; - } - void set_in_collection_set(bool b) { - _in_collection_set = b; - } + bool in_collection_set() const; + HeapRegion* next_in_collection_set() { assert(in_collection_set(), "should only invoke on member of CS."); assert(_next_in_special_set == NULL || diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp index 8dc6a417371..955b8489cc0 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp @@ -196,4 +196,8 @@ inline void HeapRegion::note_end_of_copying(bool during_initial_mark) { } } +inline bool HeapRegion::in_collection_set() const { + return G1CollectedHeap::heap()->is_in_cset(this); +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_INLINE_HPP From aa21fdd0c03ba465113a450b24b69d07cf9dbb39 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Tue, 24 Feb 2015 17:23:53 -0500 Subject: [PATCH 02/79] 8072383: resolve conflicts between open and closed ports Refactor close to remove references to closed ports Reviewed-by: kvn, simonis, dholmes --- hotspot/agent/src/os/linux/libproc.h | 4 +-- hotspot/make/defs.make | 11 +++--- hotspot/make/linux/makefiles/arm.make | 31 ---------------- hotspot/make/linux/makefiles/buildtree.make | 6 ++-- hotspot/make/linux/makefiles/defs.make | 14 +------- hotspot/make/linux/makefiles/gcc.make | 12 ++----- hotspot/make/linux/makefiles/ppc.make | 33 ----------------- hotspot/make/linux/makefiles/saproc.make | 8 +++-- hotspot/make/linux/makefiles/vm.make | 5 +-- hotspot/make/linux/platform_arm | 17 --------- hotspot/make/linux/platform_ppc | 17 --------- hotspot/src/os/linux/vm/os_linux.cpp | 28 ++------------- hotspot/src/share/vm/c1/c1_LIR.cpp | 7 +--- hotspot/src/share/vm/c1/c1_LIR.hpp | 11 ++++-- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 35 ++++++------------- hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 7 ++++ hotspot/src/share/vm/c1/c1_LinearScan.cpp | 6 ++-- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 4 +-- .../src/share/vm/interpreter/interp_masm.hpp | 24 +++++-------- .../share/vm/interpreter/templateTable.hpp | 27 +++++--------- hotspot/src/share/vm/memory/generation.hpp | 4 +-- hotspot/src/share/vm/opto/ad.hpp | 27 +++++--------- hotspot/src/share/vm/opto/chaitin.cpp | 4 +-- hotspot/src/share/vm/opto/optoreg.hpp | 27 +++++--------- hotspot/src/share/vm/runtime/stubRoutines.hpp | 28 +++++---------- hotspot/src/share/vm/runtime/vm_version.cpp | 12 ++----- .../vm/utilities/globalDefinitions_gcc.hpp | 4 +-- hotspot/src/share/vm/utilities/macros.hpp | 11 ++++-- 28 files changed, 119 insertions(+), 305 deletions(-) delete mode 100644 hotspot/make/linux/makefiles/arm.make delete mode 100644 hotspot/make/linux/makefiles/ppc.make delete mode 100644 hotspot/make/linux/platform_arm delete mode 100644 hotspot/make/linux/platform_ppc diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index f220e9df556..882169a3cee 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -30,7 +30,7 @@ #include #include "proc_service.h" -#if defined(arm) || defined(ppc) +#ifdef ALT_SASRCDIR #include "libproc_md.h" #endif diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index 5c4f00dc1d8..a1321d46e43 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -286,7 +286,7 @@ ifneq ($(OSNAME),windows) # Use uname output for SRCARCH, but deal with platform differences. If ARCH # is not explicitly listed below, it is treated as x86. - SRCARCH = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc ppc64 aarch64 zero,$(ARCH))) + SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc ppc64 aarch64 zero,$(ARCH))) ARCH/ = x86 ARCH/sparc = sparc ARCH/sparc64= sparc @@ -295,12 +295,11 @@ ifneq ($(OSNAME),windows) ARCH/x86_64 = x86 ARCH/ppc64 = ppc ARCH/ppc = ppc - ARCH/arm = arm ARCH/aarch64= aarch64 ARCH/zero = zero # BUILDARCH is usually the same as SRCARCH, except for sparcv9 - BUILDARCH = $(SRCARCH) + BUILDARCH ?= $(SRCARCH) ifeq ($(BUILDARCH), x86) ifdef LP64 BUILDARCH = amd64 @@ -320,7 +319,7 @@ ifneq ($(OSNAME),windows) endif # LIBARCH is 1:1 mapping from BUILDARCH - LIBARCH = $(LIBARCH/$(BUILDARCH)) + LIBARCH ?= $(LIBARCH/$(BUILDARCH)) LIBARCH/i486 = i386 LIBARCH/amd64 = amd64 LIBARCH/sparc = sparc @@ -328,8 +327,6 @@ ifneq ($(OSNAME),windows) LIBARCH/ia64 = ia64 LIBARCH/ppc64 = ppc64 LIBARCH/aarch64 = aarch64 - LIBARCH/ppc = ppc - LIBARCH/arm = arm LIBARCH/zero = $(ZERO_LIBARCH) LP64_ARCH = sparcv9 amd64 ia64 ppc64 aarch64 zero diff --git a/hotspot/make/linux/makefiles/arm.make b/hotspot/make/linux/makefiles/arm.make deleted file mode 100644 index ff8e3c519f9..00000000000 --- a/hotspot/make/linux/makefiles/arm.make +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (c) 2008, 2013, 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. -# -# - -Obj_Files += linux_arm.o - -ifneq ($(EXT_LIBS_PATH),) - LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a -endif - -CFLAGS += -DVM_LITTLE_ENDIAN diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index 6c03da02a0d..a5de1398e9b 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, 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 @@ -70,6 +70,8 @@ else PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc else PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) + ALT_PLATFORM_FILE = $(HS_ALT_MAKE)/$(OS_FAMILY)/platform_$(BUILDARCH) + PLATFORM_FILE := $(if $(wildcard $(ALT_PLATFORM_FILE)),$(ALT_PLATFORM_FILE),$(PLATFORM_FILE)) endif endif @@ -203,7 +205,7 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo; \ - echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ + echo "Platform_file = $(PLATFORM_FILE)" | sed -e 's|$(HS_ALT_MAKE)|$$(HS_ALT_MAKE)|' -e 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \ echo; \ echo "GAMMADIR = $(GAMMADIR)"; \ diff --git a/hotspot/make/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make index b46db737434..c85f1ed5522 100644 --- a/hotspot/make/linux/makefiles/defs.make +++ b/hotspot/make/linux/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -105,14 +105,6 @@ ifneq (,$(findstring $(ARCH), amd64 x86_64 i686 i586)) HS_ARCH = x86 endif -# ARM -ifeq ($(ARCH), arm) - ARCH_DATA_MODEL = 32 - PLATFORM = linux-arm - VM_PLATFORM = linux_arm - HS_ARCH = arm -endif - # PPC # Notice: after 8046471 ARCH will be 'ppc' for top-level ppc64 builds but # 'ppc64' for HotSpot-only ppc64 builds. Need to detect both variants here! @@ -121,10 +113,6 @@ ifneq (,$(findstring $(ARCH), ppc ppc64)) MAKE_ARGS += LP64=1 PLATFORM = linux-ppc64 VM_PLATFORM = linux_ppc64 - else - ARCH_DATA_MODEL = 32 - PLATFORM = linux-ppc - VM_PLATFORM = linux_ppc endif HS_ARCH = ppc diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index 41421f25443..d9007afe655 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -176,11 +176,7 @@ ARCHFLAG/aarch64 = ARCHFLAG/ia64 = ARCHFLAG/sparc = -m32 -mcpu=v9 ARCHFLAG/sparcv9 = -m64 -mcpu=v9 -ARCHFLAG/arm = -fsigned-char ARCHFLAG/zero = $(ZERO_ARCHFLAG) -ifndef E500V2 -ARCHFLAG/ppc = -mcpu=powerpc -endif ARCHFLAG/ppc64 = -m64 CFLAGS += $(ARCHFLAG) @@ -188,10 +184,6 @@ AOUT_FLAGS += $(ARCHFLAG) LFLAGS += $(ARCHFLAG) ASFLAGS += $(ARCHFLAG) -ifdef E500V2 -CFLAGS += -DE500V2 -endif - # Use C++ Interpreter ifdef CC_INTERP CFLAGS += -DCC_INTERP @@ -391,3 +383,5 @@ endif ifndef USE_SUNCC CFLAGS += -fno-omit-frame-pointer endif + +-include $(HS_ALT_MAKE)/linux/makefiles/gcc.make diff --git a/hotspot/make/linux/makefiles/ppc.make b/hotspot/make/linux/makefiles/ppc.make deleted file mode 100644 index 3364bd743b8..00000000000 --- a/hotspot/make/linux/makefiles/ppc.make +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2004, 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. -# -# - -# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized -OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) - -# Must also specify if CPU is big endian -CFLAGS += -DVM_BIG_ENDIAN - -ifdef E500V2 -ASFLAGS += -Wa,-mspe -Wa,--defsym -Wa,E500V2=1 -endif diff --git a/hotspot/make/linux/makefiles/saproc.make b/hotspot/make/linux/makefiles/saproc.make index 6c31c7bb4a2..15bdba1d396 100644 --- a/hotspot/make/linux/makefiles/saproc.make +++ b/hotspot/make/linux/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, 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 @@ -69,19 +69,21 @@ endif endif ifneq ($(ALT_SASRCDIR),) -ALT_SAINCDIR=-I$(ALT_SASRCDIR) +ALT_SAINCDIR=-I$(ALT_SASRCDIR) -DALT_SASRCDIR else ALT_SAINCDIR= endif SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) $(LDFLAGS_HASH_STYLE) +SAARCH ?= $(BUILDARCH) + $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ exit 1; \ fi @echo $(LOG_INFO) Making SA debugger back-end... - $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + $(QUIETLY) $(CC) -D$(SAARCH) -D_GNU_SOURCE \ -D_FILE_OFFSET_BITS=64 \ $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ -I$(SASRCDIR) \ diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index d0c31ca125c..25679bffff0 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -45,8 +45,9 @@ DEP_DIR = $(GENERATED)/dependencies ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) include $(MAKEFILES_DIR)/zeroshark.make else - include $(MAKEFILES_DIR)/$(BUILDARCH).make - -include $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make + BUILDARCH_MAKE = $(MAKEFILES_DIR)/$(BUILDARCH).make + ALT_BUILDARCH_MAKE = $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make + include $(if $(wildcard $(ALT_BUILDARCH_MAKE)),$(ALT_BUILDARCH_MAKE),$(BUILDARCH_MAKE)) endif # set VPATH so make knows where to look for source files diff --git a/hotspot/make/linux/platform_arm b/hotspot/make/linux/platform_arm deleted file mode 100644 index 13206d63738..00000000000 --- a/hotspot/make/linux/platform_arm +++ /dev/null @@ -1,17 +0,0 @@ -os_family = linux - -arch = arm - -arch_model = arm - -os_arch = linux_arm - -os_arch_model = linux_arm - -lib_arch = arm - -compiler = gcc - -gnu_dis_arch = arm - -sysdefs = -DLINUX -D_GNU_SOURCE -DARM diff --git a/hotspot/make/linux/platform_ppc b/hotspot/make/linux/platform_ppc deleted file mode 100644 index 809456b526b..00000000000 --- a/hotspot/make/linux/platform_ppc +++ /dev/null @@ -1,17 +0,0 @@ -os_family = linux - -arch = ppc - -arch_model = ppc_32 - -os_arch = linux_ppc - -os_arch_model = linux_ppc_32 - -lib_arch = ppc - -compiler = gcc - -gnu_dis_arch = ppc - -sysdefs = -DLINUX -D_GNU_SOURCE -DPPC32 diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3993178469f..a2a807aa003 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -227,31 +227,7 @@ bool os::have_special_privileges() { #endif // Cpu architecture string -#if defined(ZERO) -static char cpu_arch[] = ZERO_LIBARCH; -#elif defined(IA64) -static char cpu_arch[] = "ia64"; -#elif defined(IA32) -static char cpu_arch[] = "i386"; -#elif defined(AMD64) -static char cpu_arch[] = "amd64"; -#elif defined(ARM) -static char cpu_arch[] = "arm"; -#elif defined(PPC32) -static char cpu_arch[] = "ppc"; -#elif defined(PPC64) -static char cpu_arch[] = "ppc64"; -#elif defined(SPARC) - #ifdef _LP64 -static char cpu_arch[] = "sparcv9"; - #else -static char cpu_arch[] = "sparc"; - #endif -#elif defined(AARCH64) -static char cpu_arch[] = "aarch64"; -#else - #error Add appropriate cpu_arch setting -#endif +static char cpu_arch[] = HOTSPOT_LIB_ARCH; // pid_t gettid() @@ -3296,7 +3272,7 @@ size_t os::Linux::find_large_page_size() { #ifndef ZERO large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M) - ARM_ONLY(2 * M) PPC_ONLY(4 * M) AARCH64_ONLY(2 * M); + ARM32_ONLY(2 * M) PPC_ONLY(4 * M) AARCH64_ONLY(2 * M); #endif // ZERO FILE *fp = fopen("/proc/meminfo", "r"); diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index 92640ccc7ea..d58e3c85b42 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -142,16 +142,11 @@ LIR_Address::Scale LIR_Address::scale(BasicType type) { #ifndef PRODUCT -void LIR_Address::verify() const { +void LIR_Address::verify0() const { #if defined(SPARC) || defined(PPC) assert(scale() == times_1, "Scaled addressing mode not available on SPARC/PPC and should not be used"); assert(disp() == 0 || index()->is_illegal(), "can't have both"); #endif -#ifdef ARM - assert(disp() == 0 || index()->is_illegal(), "can't have both"); - // Note: offsets higher than 4096 must not be rejected here. They can - // be handled by the back-end or will be rejected if not. -#endif #ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); #ifndef AARCH64 diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 1b997a3f954..90a47c8b47e 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_C1_C1_LIR_HPP #define SHARE_VM_C1_C1_LIR_HPP +#include "c1/c1_Defs.hpp" #include "c1/c1_ValueType.hpp" #include "oops/method.hpp" @@ -561,7 +562,13 @@ class LIR_Address: public LIR_OprPtr { virtual BasicType type() const { return _type; } virtual void print_value_on(outputStream* out) const PRODUCT_RETURN; - void verify() const PRODUCT_RETURN; + void verify0() const PRODUCT_RETURN; +#if defined(LIR_ADDRESS_PD_VERIFY) && !defined(PRODUCT) + void pd_verify() const; + void verify() const { pd_verify(); } +#else + void verify() const { verify0(); } +#endif static Scale scale(BasicType type); }; @@ -610,7 +617,7 @@ class LIR_OprFact: public AllStatic { LIR_OprDesc::float_type | LIR_OprDesc::fpu_register | LIR_OprDesc::single_size); } -#if defined(ARM) +#if defined(ARM32) static LIR_Opr double_fpu(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::fpu_register | LIR_OprDesc::double_size); } static LIR_Opr single_softfp(int reg) { return (LIR_Opr)((reg << LIR_OprDesc::reg1_shift) | LIR_OprDesc::float_type | LIR_OprDesc::cpu_register | LIR_OprDesc::single_size); } static LIR_Opr double_softfp(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::cpu_register | LIR_OprDesc::double_size); } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index a606b7bf843..ea745dd60f1 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "c1/c1_Defs.hpp" #include "c1/c1_Compilation.hpp" #include "c1/c1_FrameMap.hpp" #include "c1/c1_Instruction.hpp" @@ -49,10 +50,7 @@ #define __ gen()->lir()-> #endif -// TODO: ARM - Use some recognizable constant which still fits architectural constraints -#ifdef ARM -#define PATCHED_ADDR (204) -#else +#ifndef PATCHED_ADDR #define PATCHED_ADDR (max_jint) #endif @@ -1600,24 +1598,9 @@ void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* } assert(addr->is_register(), "must be a register at this point"); -#ifdef ARM - // TODO: ARM - move to platform-dependent code - LIR_Opr tmp = FrameMap::R14_opr; - if (VM_Version::supports_movw()) { - __ move((LIR_Opr)card_table_base, tmp); - } else { - __ move(new LIR_Address(FrameMap::Rthread_opr, in_bytes(JavaThread::card_table_base_offset()), T_ADDRESS), tmp); - } - - LIR_Address *card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTableModRefBS::card_shift, 0, T_BYTE); - if(((int)ct->byte_map_base & 0xff) == 0) { - __ move(tmp, card_addr); - } else { - LIR_Opr tmp_zero = new_register(T_INT); - __ move(LIR_OprFact::intConst(0), tmp_zero); - __ move(tmp_zero, card_addr); - } -#else // ARM +#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER + CardTableModRef_post_barrier_helper(addr, card_table_base); +#else LIR_Opr tmp = new_pointer_register(); if (TwoOperandLIRForm) { __ move(addr, tmp); @@ -1633,7 +1616,7 @@ void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new LIR_Address(tmp, load_constant(card_table_base), T_BYTE)); } -#endif // ARM +#endif } @@ -2123,7 +2106,7 @@ void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { } else { #ifdef X86 addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type); -#elif defined(ARM) +#elif defined(GENERATE_ADDRESS_IS_PREFERRED) addr = generate_address(base_op, index_op, log2_scale, 0, dst_type); #else if (index_op->is_illegal() || log2_scale == 0) { @@ -2177,6 +2160,9 @@ void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { LIR_Opr base_op = base.result(); LIR_Opr index_op = idx.result(); +#ifdef GENERATE_ADDRESS_IS_PREFERRED + LIR_Address* addr = generate_address(base_op, index_op, log2_scale, 0, x->basic_type()); +#else #ifndef _LP64 if (base_op->type() == T_LONG) { base_op = new_register(T_INT); @@ -2210,6 +2196,7 @@ void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { } LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); +#endif // !GENERATE_ADDRESS_IS_PREFERRED __ move(value.result(), addr); } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index 5095af782c9..7f8d45f81da 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -275,6 +275,9 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); void CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); +#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER + void CardTableModRef_post_barrier_helper(LIR_OprDesc* addr, LIR_Const* card_table_base); +#endif static LIR_Opr result_register_for(ValueType* type, bool callee = false); @@ -546,6 +549,10 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { #ifdef ASSERT virtual void do_Assert (Assert* x); #endif + +#ifdef C1_LIRGENERATOR_MD_HPP +#include C1_LIRGENERATOR_MD_HPP +#endif }; diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index 833b357d2e4..9ed4a551a45 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -2123,7 +2123,7 @@ LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) { assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register"); assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even"); LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg); -#elif defined(ARM) +#elif defined(ARM32) assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register"); assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register"); assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even"); @@ -2712,7 +2712,7 @@ int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArrayfpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)"); #endif -#ifdef ARM +#ifdef ARM32 assert(opr->fpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)"); #endif #ifdef PPC diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 7e3ab821025..1775d5baff2 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1120,7 +1120,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i #ifdef ARM if((load_klass_or_mirror_patch_id || stub_id == Runtime1::load_appendix_patching_id) && - !VM_Version::supports_movw()) { + nativeMovConstReg_at(copy_buff)->is_pc_relative()) { nmethod* nm = CodeCache::find_nmethod(instr_pc); address addr = NULL; assert(nm != NULL, "invalid nmethod_pc"); diff --git a/hotspot/src/share/vm/interpreter/interp_masm.hpp b/hotspot/src/share/vm/interpreter/interp_masm.hpp index f2599106465..dddbbe5d6ac 100644 --- a/hotspot/src/share/vm/interpreter/interp_masm.hpp +++ b/hotspot/src/share/vm/interpreter/interp_masm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -27,25 +27,17 @@ #include "asm/macroAssembler.hpp" -#ifdef TARGET_ARCH_x86 +#if defined INTERP_MASM_MD_HPP +# include INTERP_MASM_MD_HPP +#elif defined TARGET_ARCH_x86 # include "interp_masm_x86.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "interp_masm_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "interp_masm_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "interp_masm_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "interp_masm_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "interp_masm_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "interp_masm_aarch64.hpp" #endif diff --git a/hotspot/src/share/vm/interpreter/templateTable.hpp b/hotspot/src/share/vm/interpreter/templateTable.hpp index 4b1541806a0..6ead5074082 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.hpp +++ b/hotspot/src/share/vm/interpreter/templateTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -341,28 +341,19 @@ class TemplateTable: AllStatic { static Template* template_for_wide(Bytecodes::Code code) { Bytecodes::wide_check(code); return &_template_table_wide[code]; } // Platform specifics -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined TEMPLATETABLE_MD_HPP +# include TEMPLATETABLE_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "templateTable_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "templateTable_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "templateTable_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "templateTable_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "templateTable_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "templateTable_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "templateTable_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "templateTable_aarch64.hpp" #endif diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index 058f757de01..a2e15a08895 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -139,7 +139,7 @@ class Generation: public CHeapObj { // GenGrain. // Note: on ARM we add 1 bit for card_table_base to be properly aligned // (we expect its low byte to be zero - see implementation of post_barrier) - LogOfGenGrain = 16 ARM_ONLY(+1), + LogOfGenGrain = 16 ARM32_ONLY(+1), GenGrain = 1 << LogOfGenGrain }; diff --git a/hotspot/src/share/vm/opto/ad.hpp b/hotspot/src/share/vm/opto/ad.hpp index c307b80c930..7bd84ebeb1c 100644 --- a/hotspot/src/share/vm/opto/ad.hpp +++ b/hotspot/src/share/vm/opto/ad.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -25,28 +25,19 @@ #ifndef SHARE_VM_OPTO_AD_HPP #define SHARE_VM_OPTO_AD_HPP -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined AD_MD_HPP +# include AD_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "adfiles/ad_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "adfiles/ad_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "adfiles/ad_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "adfiles/ad_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "adfiles/ad_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "adfiles/ad_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "adfiles/ad_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "adfiles/ad_aarch64.hpp" #endif diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 106e22879b7..7b1290dd36a 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -847,7 +847,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { case Op_RegD: lrg.set_num_regs(2); // Define platform specific register pressure -#if defined(SPARC) || defined(ARM) +#if defined(SPARC) || defined(ARM32) lrg.set_reg_pressure(2); #elif defined(IA32) if( ireg == Op_RegL ) { diff --git a/hotspot/src/share/vm/opto/optoreg.hpp b/hotspot/src/share/vm/opto/optoreg.hpp index 5657a9b48c0..28c74f5f548 100644 --- a/hotspot/src/share/vm/opto/optoreg.hpp +++ b/hotspot/src/share/vm/opto/optoreg.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -27,28 +27,19 @@ // AdGlobals contains c2 specific register handling code as specified // in the .ad files. -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined ADGLOBALS_MD_HPP +# include ADGLOBALS_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "adfiles/adGlobals_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "adfiles/adGlobals_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "adfiles/adGlobals_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "adfiles/adGlobals_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "adfiles/adGlobals_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "adfiles/adGlobals_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "adfiles/adGlobals_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "adfiles/adGlobals_aarch64.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index a040396a74c..88865661908 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -84,32 +84,22 @@ class StubRoutines: AllStatic { // Dependencies friend class StubGenerator; -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined STUBROUTINES_MD_HPP +# include STUBROUTINES_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "stubRoutines_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "stubRoutines_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "stubRoutines_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "stubRoutines_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "stubRoutines_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "stubRoutines_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "stubRoutines_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "stubRoutines_aarch64.hpp" #endif - static jint _verify_oop_count; static address _verify_oop_subroutine_entry; diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 46a8628a3c5..4c3189424be 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -187,18 +187,18 @@ const char* Abstract_VM_Version::jre_release_version() { AIX_ONLY("aix") \ BSD_ONLY("bsd") +#ifndef CPU #ifdef ZERO #define CPU ZERO_LIBARCH #else #define CPU IA32_ONLY("x86") \ IA64_ONLY("ia64") \ AMD64_ONLY("amd64") \ - ARM_ONLY("arm") \ - PPC32_ONLY("ppc") \ PPC64_ONLY("ppc64") \ AARCH64_ONLY("aarch64") \ SPARC_ONLY("sparc") #endif // ZERO +#endif const char *Abstract_VM_Version::vm_platform_string() { return OS "-" CPU; @@ -251,12 +251,6 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #ifndef FLOAT_ARCH #if defined(__SOFTFP__) #define FLOAT_ARCH_STR "-sflt" - #elif defined(E500V2) - #define FLOAT_ARCH_STR "-e500v2" - #elif defined(ARM) - #define FLOAT_ARCH_STR "-vfp" - #elif defined(PPC32) - #define FLOAT_ARCH_STR "-hflt" #else #define FLOAT_ARCH_STR "" #endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp index 9a00b912048..8d78eef4f9b 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -220,7 +220,7 @@ extern "C" { #define DEBUG_EXCEPTION ::abort(); -#ifdef ARM +#ifdef ARM32 #ifdef SOLARIS #define BREAKPOINT __asm__ volatile (".long 0xe1200070") #else diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index cb147277a6f..b44b2ccf418 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -392,7 +392,6 @@ #define NOT_E500V2(code) code #endif - #ifdef ARM #define ARM_ONLY(code) code #define NOT_ARM(code) @@ -401,6 +400,14 @@ #define NOT_ARM(code) code #endif +#ifdef ARM32 +#define ARM32_ONLY(code) code +#define NOT_ARM32(code) +#else +#define ARM32_ONLY(code) +#define NOT_ARM32(code) code +#endif + #ifdef AARCH64 #define AARCH64_ONLY(code) code #define NOT_AARCH64(code) From c2a4574760cb93bb4e46dca8eb15b72ef39ad5b7 Mon Sep 17 00:00:00 2001 From: Erik Osterlund Date: Tue, 3 Mar 2015 19:20:26 -0500 Subject: [PATCH 03/79] 7143664: Clean up OrderAccess implementations and usage Clarify and correct the abstract model for memory barriers provided by the orderAccess class. Refactor the implementations using template specialization to allow the bulk of the code to be shared, with platform specific customizations applied as needed. Reviewed-by: acorn, dcubed, dholmes, dlong, goetz, kbarrett, sgehwolf --- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 2 - .../aix_ppc/vm/orderAccess_aix_ppc.inline.hpp | 87 ++---- .../bsd_x86/vm/orderAccess_bsd_x86.inline.hpp | 182 +++--------- .../vm/orderAccess_bsd_zero.inline.hpp | 126 +-------- .../vm/orderAccess_linux_ppc.inline.hpp | 88 ++---- .../vm/orderAccess_linux_sparc.inline.hpp | 84 +----- .../vm/orderAccess_linux_x86.inline.hpp | 171 ++---------- .../vm/orderAccess_linux_zero.inline.hpp | 124 +------- .../vm/orderAccess_solaris_sparc.inline.hpp | 109 ++------ .../os_cpu/solaris_sparc/vm/solaris_sparc.il | 41 +-- .../vm/orderAccess_solaris_x86.inline.hpp | 111 ++------ .../os_cpu/solaris_x86/vm/solaris_x86_32.il | 29 +- .../os_cpu/solaris_x86/vm/solaris_x86_64.il | 29 +- .../vm/orderAccess_windows_x86.inline.hpp | 188 +++---------- hotspot/src/share/vm/runtime/orderAccess.hpp | 264 ++++++++++-------- .../share/vm/runtime/orderAccess.inline.hpp | 91 +++++- 16 files changed, 494 insertions(+), 1232 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 7c90c1decda..c76408f6af7 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -3947,12 +3947,10 @@ void LIR_Assembler::membar() { void LIR_Assembler::membar_acquire() { // No x86 machines currently require load fences - // __ load_fence(); } void LIR_Assembler::membar_release() { // No x86 machines currently require store fences - // __ store_fence(); } void LIR_Assembler::membar_loadload() { diff --git a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp index 36ca820a6bd..71eb6ac9536 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +28,9 @@ #include "runtime/orderAccess.hpp" +// Compiler version last used for testing: xlc 12 +// Please update this information when this file changes + // Implementation of class OrderAccess. // @@ -61,86 +64,30 @@ #define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); #define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); #define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); -#define inlasm_release() inlasm_lwsync(); -#define inlasm_acquire() inlasm_lwsync(); // Use twi-isync for load_acquire (faster than lwsync). // ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"): // #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); #define inlasm_acquire_reg(X) inlasm_lwsync(); -#define inlasm_fence() inlasm_sync(); -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_fence(); } +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_sync(); } -inline void OrderAccess::acquire() { inlasm_acquire(); } -inline void OrderAccess::release() { inlasm_release(); } -inline void OrderAccess::fence() { inlasm_fence(); } +inline void OrderAccess::acquire() { inlasm_lwsync(); } +inline void OrderAccess::release() { inlasm_lwsync(); } +inline void OrderAccess::fence() { inlasm_sync(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } -inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } -inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } +template<> inline jbyte OrderAccess::specialized_load_acquire (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jshort OrderAccess::specialized_load_acquire(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jint OrderAccess::specialized_load_acquire (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jlong OrderAccess::specialized_load_acquire (volatile jlong* p) { register jlong t = load(p); inlasm_acquire_reg(t); return t; } #undef inlasm_sync #undef inlasm_lwsync #undef inlasm_eieio #undef inlasm_isync -#undef inlasm_release -#undef inlasm_acquire -#undef inlasm_fence + +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp index 834efd2bbf7..bc28eb2b2d4 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,27 +29,27 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: clang 5.1 +// Please update this information when this file changes + +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +static inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); +} + +// x86 is TSO and hence only needs a fence for storeload +// However, a compiler barrier is still needed to prevent reordering +// between volatile and non-volatile memory accesses. + // Implementation of class OrderAccess. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { - volatile intptr_t local_dummy; -#ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); -#else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 -} - -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { @@ -60,156 +60,50 @@ inline void OrderAccess::fence() { __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); #endif } + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm__ volatile ( "xchgb (%2),%0" : "=q" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm__ volatile ( "xchgw (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jint* p, jint v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm__ volatile ( "xchgl (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { #ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - *p = v; fence(); -#endif // AMD64 -} - -// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the -// compiler does the inlining this is simpler. -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { - __asm__ volatile ( "xchgb (%2),%0" - : "=q" (v) - : "0" (v), "r" (p) - : "memory"); -} -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { - __asm__ volatile ( "xchgw (%2),%0" +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jlong* p, jlong v) { + __asm__ volatile ( "xchgq (%2), %0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { - __asm__ volatile ( "xchgl (%2),%0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -} - -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store(p, v); fence(); #endif // AMD64 + +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); +} +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } - -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP diff --git a/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp b/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp index ecc4c752777..fb3017ce9d1 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,8 +40,7 @@ typedef void (__kernel_dmb_t) (void); #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) #define FULL_MEM_BARRIER __kernel_dmb() -#define READ_MEM_BARRIER __kernel_dmb() -#define WRITE_MEM_BARRIER __kernel_dmb() +#define LIGHT_MEM_BARRIER __kernel_dmb() #else // ARM @@ -50,126 +49,31 @@ typedef void (__kernel_dmb_t) (void); #ifdef PPC #ifdef __NO_LWSYNC__ -#define READ_MEM_BARRIER __asm __volatile ("sync":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("sync":::"memory") #else -#define READ_MEM_BARRIER __asm __volatile ("lwsync":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("lwsync":::"memory") #endif #else // PPC -#define READ_MEM_BARRIER __asm __volatile ("":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("":::"memory") #endif // PPC #endif // ARM +// Note: What is meant by LIGHT_MEM_BARRIER is a barrier which is sufficient +// to provide TSO semantics, i.e. StoreStore | LoadLoad | LoadStore. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storestore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::loadstore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storeload() { FULL_MEM_BARRIER; } -inline void OrderAccess::acquire() { - READ_MEM_BARRIER; -} +inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::release() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::fence() { FULL_MEM_BARRIER; } -inline void OrderAccess::release() { - WRITE_MEM_BARRIER; -} - -inline void OrderAccess::fence() { - FULL_MEM_BARRIER; -} - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { - jlong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; } -inline julong OrderAccess::load_acquire(volatile julong* p) { - julong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { - jdouble tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { - intptr_t data = *p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { - void *data = *(void* volatile *)p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { - void *data = *(void* const volatile *)p; - acquire(); - return data; -} - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) -{ release(); os::atomic_copy64(&v, p); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) -{ release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp index dff21c6bf6a..9e414dcd805 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +32,9 @@ #error "OrderAccess currently only implemented for PPC64" #endif +// Compiler version last used for testing: gcc 4.1.2 +// Please update this information when this file changes + // Implementation of class OrderAccess. // @@ -65,84 +68,29 @@ #define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); #define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); #define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); -#define inlasm_release() inlasm_lwsync(); -#define inlasm_acquire() inlasm_lwsync(); // Use twi-isync for load_acquire (faster than lwsync). #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); -#define inlasm_fence() inlasm_sync(); -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_fence(); } +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_sync(); } -inline void OrderAccess::acquire() { inlasm_acquire(); } -inline void OrderAccess::release() { inlasm_release(); } -inline void OrderAccess::fence() { inlasm_fence(); } +inline void OrderAccess::acquire() { inlasm_lwsync(); } +inline void OrderAccess::release() { inlasm_lwsync(); } +inline void OrderAccess::fence() { inlasm_sync(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } -inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } -inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } +template<> inline jbyte OrderAccess::specialized_load_acquire (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jshort OrderAccess::specialized_load_acquire(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jint OrderAccess::specialized_load_acquire (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jlong OrderAccess::specialized_load_acquire (volatile jlong* p) { register jlong t = load(p); inlasm_acquire_reg(t); return t; } #undef inlasm_sync #undef inlasm_lwsync #undef inlasm_eieio #undef inlasm_isync -#undef inlasm_release -#undef inlasm_acquire -#undef inlasm_fence +#undef inlasm_acquire_reg + +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_PPC_VM_ORDERACCESS_LINUX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp index f5215f187e8..fd6078fcd31 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,81 +29,25 @@ // Implementation of class OrderAccess. +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +static inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); +} + // Assume TSO. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { - __asm__ volatile ("nop" : : :); -} - -inline void OrderAccess::release() { - jint* local_dummy = (jint*)&local_dummy; - __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory"); -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { - __asm__ volatile ("membar #StoreLoad" : : :); + __asm__ volatile ("membar #StoreLoad" : : : "memory"); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_SPARC_VM_ORDERACCESS_LINUX_SPARC_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp index d391baf8095..b4aceaf5a91 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,6 +29,9 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: gcc 4.8.2 +// Please update this information when this file changes + // Implementation of class OrderAccess. // A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions @@ -36,23 +39,13 @@ static inline void compiler_barrier() { __asm__ volatile ("" : : : "memory"); } -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { - volatile intptr_t local_dummy; -#ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); -#else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 -} - -inline void OrderAccess::release() { - compiler_barrier(); -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { @@ -63,156 +56,50 @@ inline void OrderAccess::fence() { __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); #endif } + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte v = *p; compiler_barrier(); return v; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort v = *p; compiler_barrier(); return v; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint v = *p; compiler_barrier(); return v; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { jlong v = Atomic::load(p); compiler_barrier(); return v; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte v = *p; compiler_barrier(); return v; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort v = *p; compiler_barrier(); return v; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint v = *p; compiler_barrier(); return v; } -inline julong OrderAccess::load_acquire(volatile julong* p) { julong v = Atomic::load((volatile jlong*)p); compiler_barrier(); return v; } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat v = *p; compiler_barrier(); return v; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { jdouble v = jdouble_cast(Atomic::load((volatile jlong*)p)); compiler_barrier(); return v; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { intptr_t v = *p; compiler_barrier(); return v; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { void* v = *(void* volatile *)p; compiler_barrier(); return v; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { void* v = *(void* const volatile *)p; compiler_barrier(); return v; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { compiler_barrier(); Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { compiler_barrier(); Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong *)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { compiler_barrier(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm__ volatile ( "xchgb (%2),%0" : "=q" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm__ volatile ( "xchgw (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jint* p, jint v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm__ volatile ( "xchgl (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { #ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - *p = v; fence(); -#endif // AMD64 -} - -// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the -// compiler does the inlining this is simpler. -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { store_fence((jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { - __asm__ volatile ( "xchgb (%2),%0" - : "=q" (v) - : "0" (v), "r" (p) - : "memory"); -} -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { - __asm__ volatile ( "xchgw (%2),%0" +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jlong* p, jlong v) { + __asm__ volatile ( "xchgq (%2), %0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { - __asm__ volatile ( "xchgl (%2),%0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -} - -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store(p, v); fence(); #endif // AMD64 + +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); +} +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } - -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp b/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp index e15041e76a7..20d851c9234 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,8 +40,7 @@ typedef void (__kernel_dmb_t) (void); #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) #define FULL_MEM_BARRIER __kernel_dmb() -#define READ_MEM_BARRIER __kernel_dmb() -#define WRITE_MEM_BARRIER __kernel_dmb() +#define LIGHT_MEM_BARRIER __kernel_dmb() #else // ARM @@ -49,126 +48,33 @@ typedef void (__kernel_dmb_t) (void); #ifdef PPC -#define READ_MEM_BARRIER __asm __volatile ("isync":::"memory") #ifdef __NO_LWSYNC__ -#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("sync":::"memory") #else -#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("lwsync":::"memory") #endif #else // PPC -#define READ_MEM_BARRIER __asm __volatile ("":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("":::"memory") #endif // PPC #endif // ARM +// Note: What is meant by LIGHT_MEM_BARRIER is a barrier which is sufficient +// to provide TSO semantics, i.e. StoreStore | LoadLoad | LoadStore. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storestore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::loadstore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storeload() { FULL_MEM_BARRIER; } -inline void OrderAccess::acquire() { - READ_MEM_BARRIER; -} +inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::release() { LIGHT_MEM_BARRIER; } -inline void OrderAccess::release() { - WRITE_MEM_BARRIER; -} +inline void OrderAccess::fence() { FULL_MEM_BARRIER; } -inline void OrderAccess::fence() { - FULL_MEM_BARRIER; -} - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { - jlong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; } -inline julong OrderAccess::load_acquire(volatile julong* p) { - julong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { - jdouble tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { - intptr_t data = *p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { - void *data = *(void* volatile *)p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { - void *data = *(void* const volatile *)p; - acquire(); - return data; -} - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) -{ release(); os::atomic_copy64(&v, p); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) -{ release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_ZERO_VM_ORDERACCESS_LINUX_ZERO_INLINE_HPP diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp index f9321f2bac2..4bf5833a458 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -28,107 +28,30 @@ #include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" +// Compiler version last used for testing: solaris studio 12u3 +// Please update this information when this file changes + // Implementation of class OrderAccess. // Assume TSO. -// In solaris_sparc.il -extern "C" void _OrderAccess_acquire(); -extern "C" void _OrderAccess_fence(); - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -#ifdef _GNU_SOURCE - -inline void OrderAccess::acquire() { - __asm__ volatile ("nop" : : :); +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); } -inline void OrderAccess::release() { - jint* local_dummy = (jint*)&local_dummy; - __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory"); -} +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { - __asm__ volatile ("membar #StoreLoad" : : :); + __asm__ volatile ("membar #StoreLoad" : : : "memory"); } -#else // _GNU_SOURCE - -inline void OrderAccess::acquire() { - _OrderAccess_acquire(); -} - -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} - -inline void OrderAccess::fence() { - _OrderAccess_fence(); -} - -#endif // _GNU_SOURCE - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il index 16bd6902a3e..3a93cec49ff 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il +++ b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il @@ -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 @@ -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. -// +// // // Get the raw thread ID from %g7 @@ -35,11 +35,11 @@ // Clear SPARC fprs.FEF DU and DL bits -- // allows the kernel to avoid saving FPU state at context-switch time. // Use for state-transition points (into _thread_blocked) or when - // parking. - + // parking. + .inline _mark_fpu_nosave, 0 .volatile - wr %g0, 0, %fprs + wr %g0, 0, %fprs .nonvolatile .end @@ -85,7 +85,7 @@ // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint* dest, + // volatile jint* dest, // jint compare_value) // // Arguments: @@ -103,8 +103,8 @@ .end - // Support for intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, - // volatile intptr_t* dest, + // Support for intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, + // volatile intptr_t* dest, // intptr_t compare_value) // // 64-bit @@ -124,8 +124,8 @@ .end - // Support for jlong Atomic::cmpxchg(jlong exchange_value, - // volatile jlong* dest, + // Support for jlong Atomic::cmpxchg(jlong exchange_value, + // volatile jlong* dest, // jlong compare_value) // // 32-bit calling conventions @@ -221,27 +221,6 @@ .end - // Support for void OrderAccess::acquire() - // The method is intentionally empty. - // It exists for the sole purpose of generating - // a C/C++ sequence point over which the compiler won't - // reorder code. - - .inline _OrderAccess_acquire,0 - .volatile - .nonvolatile - .end - - - // Support for void OrderAccess::fence() - - .inline _OrderAccess_fence,0 - .volatile - membar #StoreLoad - .nonvolatile - .end - - // Support for void Prefetch::read(void *loc, intx interval) // // Prefetch for several reads. diff --git a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp index e211c060552..af4e2e29337 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,110 +29,35 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: solaris studio 12u3 +// Please update this information when this file changes + // Implementation of class OrderAccess. -// For Sun Studio - implementation is in solaris_i486.il. -// For gcc - implementation is just below. -extern "C" void _OrderAccess_acquire(); -extern "C" void _OrderAccess_fence(); - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -inline void OrderAccess::acquire() { - _OrderAccess_acquire(); - +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); } -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { - _OrderAccess_fence(); - } -} - -#ifdef _GNU_SOURCE - -extern "C" { - inline void _OrderAccess_acquire() { - volatile intptr_t local_dummy; #ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); #else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 - } - inline void _OrderAccess_fence() { - // Always use locked addl since mfence is sometimes expensive __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); +#endif } - + compiler_barrier(); } -#endif // GNU_SOURCE - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store((jlong *)p, (jlong)v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP diff --git a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il index f6d289e725c..c03dd64a91c 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 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 @@ -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. -// +// // @@ -34,19 +34,19 @@ // Get the raw thread ID from %gs:0 .inline _raw_thread_id,0 - movl %gs:0, %eax + movl %gs:0, %eax .end // Get current sp .inline _get_current_sp,0 .volatile - movl %esp, %eax + movl %esp, %eax .end // Get current fp .inline _get_current_fp,0 .volatile - movl %ebp, %eax + movl %ebp, %eax .end // Support for os::rdtsc() @@ -76,8 +76,8 @@ xchgl (%ecx), %eax .end - // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, - // volatile jbyte *dest, + // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, + // volatile jbyte *dest, // jbyte compare_value) // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg_byte,4 @@ -93,8 +93,8 @@ 2: .end - // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint *dest, + // Support for jint Atomic::cmpxchg(jint exchange_value, + // volatile jint *dest, // jint compare_value) // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg,4 @@ -141,17 +141,6 @@ fistpll (%eax) .end - // Support for OrderAccess::acquire() - .inline _OrderAccess_acquire,0 - movl 0(%esp), %eax - .end - - // Support for OrderAccess::fence() - .inline _OrderAccess_fence,0 - lock - addl $0, (%esp) - .end - // Support for u2 Bytes::swap_u2(u2 x) .inline _raw_swap_u2,1 movl 0(%esp), %eax diff --git a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il index bf0335f7f17..ebee3109a6d 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il @@ -1,5 +1,5 @@ // -// Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2004, 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 @@ -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. -// +// // // The argument size of each inline directive is ignored by the compiler @@ -27,19 +27,19 @@ // Get the raw thread ID from %gs:0 .inline _raw_thread_id,0 - movq %fs:0, %rax + movq %fs:0, %rax .end // Get current sp .inline _get_current_sp,0 .volatile - movq %rsp, %rax + movq %rsp, %rax .end // Get current fp .inline _get_current_fp,0 .volatile - movq %rbp, %rax + movq %rbp, %rax .end // Support for os::rdtsc() @@ -77,8 +77,8 @@ movq %rdi, %rax .end - // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, - // volatile jbyte *dest, + // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, + // volatile jbyte *dest, // jbyte compare_value) .inline _Atomic_cmpxchg_byte,3 movb %dl, %al // compare_value @@ -86,8 +86,8 @@ cmpxchgb %dil, (%rsi) .end - // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint *dest, + // Support for jint Atomic::cmpxchg(jint exchange_value, + // volatile jint *dest, // jint compare_value) .inline _Atomic_cmpxchg,3 movl %edx, %eax // compare_value @@ -104,17 +104,6 @@ cmpxchgq %rdi, (%rsi) .end - // Support for OrderAccess::acquire() - .inline _OrderAccess_acquire,0 - movl 0(%rsp), %eax - .end - - // Support for OrderAccess::fence() - .inline _OrderAccess_fence,0 - lock - addl $0, (%rsp) - .end - // Support for u2 Bytes::swap_u2(u2 x) .inline _raw_swap_u2,1 movw %di, %ax diff --git a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp index 37e5126e066..8481bd93f30 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,29 +25,39 @@ #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP +#include #include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: Microsoft Visual Studio 2010 +// Please update this information when this file changes + // Implementation of class OrderAccess. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + _ReadWriteBarrier(); +} + +// Note that in MSVC, volatile memory accesses are explicitly +// guaranteed to have acquire release semantics (w.r.t. compiler +// reordering) and therefore does not even need a compiler barrier +// for normal acquire release accesses. And all generalized +// bound calls like release_store go through OrderAccess::load +// and OrderAccess::store which do volatile memory accesses. +template<> inline void ScopedFence::postfix() { } +template<> inline void ScopedFence::prefix() { } +template<> inline void ScopedFence::prefix() { } +template<> inline void ScopedFence::postfix() { OrderAccess::fence(); } + +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { -#ifndef AMD64 - __asm { - mov eax, dword ptr [esp]; - } -#endif // !AMD64 -} - -inline void OrderAccess::release() { - // A volatile store has release semantics. - volatile jint local_dummy = 0; -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { #ifdef AMD64 @@ -59,157 +69,47 @@ inline void OrderAccess::fence() { } } #endif // AMD64 + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { -#ifdef AMD64 - *p = v; fence(); -#else +#ifndef AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm { mov edx, p; mov al, v; xchg al, byte ptr [edx]; } -#endif // AMD64 } -inline void OrderAccess::store_fence(jshort* p, jshort v) { -#ifdef AMD64 - *p = v; fence(); -#else +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm { mov edx, p; mov ax, v; xchg ax, word ptr [edx]; } -#endif // AMD64 } -inline void OrderAccess::store_fence(jint* p, jint v) { -#ifdef AMD64 - *p = v; fence(); -#else +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm { mov edx, p; mov eax, v; xchg eax, dword ptr [edx]; } +} #endif // AMD64 + +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); +} +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - *p = v; fence(); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - *p = v; fence(); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov al, v; - xchg al, byte ptr [edx]; - } -#endif // AMD64 -} - -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov ax, v; - xchg ax, word ptr [edx]; - } -#endif // AMD64 -} - -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov eax, v; - xchg eax, dword ptr [edx]; - } -#endif // AMD64 -} - -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - *p = v; fence(); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - *(void* volatile *)p = v; fence(); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP diff --git a/hotspot/src/share/vm/runtime/orderAccess.hpp b/hotspot/src/share/vm/runtime/orderAccess.hpp index faf8d2a50c9..43a64ba4bb5 100644 --- a/hotspot/src/share/vm/runtime/orderAccess.hpp +++ b/hotspot/src/share/vm/runtime/orderAccess.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,11 +29,7 @@ // Memory Access Ordering Model // -// This interface is based on the JSR-133 Cookbook for Compiler Writers -// and on the IA64 memory model. It is the dynamic equivalent of the -// C/C++ volatile specifier. I.e., volatility restricts compile-time -// memory access reordering in a way similar to what we want to occur -// at runtime. +// This interface is based on the JSR-133 Cookbook for Compiler Writers. // // In the following, the terms 'previous', 'subsequent', 'before', // 'after', 'preceding' and 'succeeding' refer to program order. The @@ -41,7 +37,6 @@ // relative to program order, while 'up' and 'above' refer to backward // motion. // -// // We define four primitive memory barrier operations. // // LoadLoad: Load1(s); LoadLoad; Load2 @@ -69,86 +64,88 @@ // operations. Stores before Store1 may *not* float below Load2 and any // subsequent load operations. // +// We define two further barriers: acquire and release. // -// We define two further operations, 'release' and 'acquire'. They are -// mirror images of each other. +// Conceptually, acquire/release semantics form unidirectional and +// asynchronous barriers w.r.t. a synchronizing load(X) and store(X) pair. +// They should always be used in pairs to publish (release store) and +// access (load acquire) some implicitly understood shared data between +// threads in a relatively cheap fashion not requiring storeload. If not +// used in such a pair, it is advised to use a membar instead: +// acquire/release only make sense as pairs. // -// Execution by a processor of release makes the effect of all memory -// accesses issued by it previous to the release visible to all -// processors *before* the release completes. The effect of subsequent -// memory accesses issued by it *may* be made visible *before* the -// release. I.e., subsequent memory accesses may float above the -// release, but prior ones may not float below it. +// T1: access_shared_data +// T1: ]release +// T1: (...) +// T1: store(X) // -// Execution by a processor of acquire makes the effect of all memory -// accesses issued by it subsequent to the acquire visible to all -// processors *after* the acquire completes. The effect of prior memory -// accesses issued by it *may* be made visible *after* the acquire. -// I.e., prior memory accesses may float below the acquire, but -// subsequent ones may not float above it. +// T2: load(X) +// T2: (...) +// T2: acquire[ +// T2: access_shared_data // -// Finally, we define a 'fence' operation, which conceptually is a -// release combined with an acquire. In the real world these operations -// require one or more machine instructions which can float above and -// below the release or acquire, so we usually can't just issue the -// release-acquire back-to-back. All machines we know of implement some -// sort of memory fence instruction. +// It is guaranteed that if T2: load(X) synchronizes with (observes the +// value written by) T1: store(X), then the memory accesses before the T1: +// ]release happen before the memory accesses after the T2: acquire[. +// +// Total Store Order (TSO) machines can be seen as machines issuing a +// release store for each store and a load acquire for each load. Therefore +// there is an inherent resemblence between TSO and acquire/release +// semantics. TSO can be seen as an abstract machine where loads are +// executed immediately when encountered (hence loadload reordering not +// happening) but enqueues stores in a FIFO queue +// for asynchronous serialization (neither storestore or loadstore +// reordering happening). The only reordering happening is storeload due to +// the queue asynchronously serializing stores (yet in order). +// +// Acquire/release semantics essentially exploits this asynchronicity: when +// the load(X) acquire[ observes the store of ]release store(X), the +// accesses before the release must have happened before the accesses after +// acquire. +// +// The API offers both stand-alone acquire() and release() as well as bound +// load_acquire() and release_store(). It is guaranteed that these are +// semantically equivalent w.r.t. the defined model. However, since +// stand-alone acquire()/release() does not know which previous +// load/subsequent store is considered the synchronizing load/store, they +// may be more conservative in implementations. We advise using the bound +// variants whenever possible. +// +// Finally, we define a "fence" operation, as a bidirectional barrier. +// It guarantees that any memory access preceding the fence is not +// reordered w.r.t. any memory accesses subsequent to the fence in program +// order. This may be used to prevent sequences of loads from floating up +// above sequences of stores. +// +// The following table shows the implementations on some architectures: +// +// Constraint x86 sparc TSO ppc +// --------------------------------------------------------------------------- +// fence LoadStore | lock membar #StoreLoad sync +// StoreStore | addl 0,(sp) +// LoadLoad | +// StoreLoad +// +// release LoadStore | lwsync +// StoreStore +// +// acquire LoadLoad | lwsync +// LoadStore +// +// release_store lwsync +// +// +// release_store_fence xchg lwsync +// membar #StoreLoad +// sync // // -// The standalone implementations of release and acquire need an associated -// dummy volatile store or load respectively. To avoid redundant operations, -// we can define the composite operators: 'release_store', 'store_fence' and -// 'load_acquire'. Here's a summary of the machine instructions corresponding -// to each operation. +// load_acquire +// lwsync // -// sparc RMO ia64 x86 -// --------------------------------------------------------------------- -// fence membar #LoadStore | mf lock addl 0,(sp) -// #StoreStore | -// #LoadLoad | -// #StoreLoad -// -// release membar #LoadStore | st.rel [sp]=r0 movl $0, -// #StoreStore -// st %g0,[] -// -// acquire ld [%sp],%g0 ld.acq =[sp] movl (sp), -// membar #LoadLoad | -// #LoadStore -// -// release_store membar #LoadStore | st.rel -// #StoreStore -// st -// -// store_fence st st lock xchg -// fence mf -// -// load_acquire ld ld.acq -// membar #LoadLoad | -// #LoadStore -// -// Using only release_store and load_acquire, we can implement the -// following ordered sequences. -// -// 1. load, load == load_acquire, load -// or load_acquire, load_acquire -// 2. load, store == load, release_store -// or load_acquire, store -// or load_acquire, release_store -// 3. store, store == store, release_store -// or release_store, release_store -// -// These require no membar instructions for sparc-TSO and no extra -// instructions for ia64. -// -// Ordering a load relative to preceding stores requires a store_fence, +// Ordering a load relative to preceding stores requires a StoreLoad, // which implies a membar #StoreLoad between the store and load under -// sparc-TSO. A fence is required by ia64. On x86, we use locked xchg. -// -// 4. store, load == store_fence, load -// -// Use store_fence to make sure all stores done in an 'interesting' -// region are made visible prior to both subsequent loads and stores. +// sparc-TSO. On x86, we use explicitly locked add. // // Conventional usage is to issue a load_acquire for ordered loads. Use // release_store for ordered stores when you care only that prior stores @@ -157,27 +154,19 @@ // release_store_fence to update values like the thread state, where we // don't want the current thread to continue until all our prior memory // accesses (including the new thread state) are visible to other threads. +// This is equivalent to the volatile semantics of the Java Memory Model. // +// C++ Volatile Semantics // -// C++ Volatility -// -// C++ guarantees ordering at operations termed 'sequence points' (defined -// to be volatile accesses and calls to library I/O functions). 'Side -// effects' (defined as volatile accesses, calls to library I/O functions -// and object modification) previous to a sequence point must be visible -// at that sequence point. See the C++ standard, section 1.9, titled -// "Program Execution". This means that all barrier implementations, -// including standalone loadload, storestore, loadstore, storeload, acquire -// and release must include a sequence point, usually via a volatile memory -// access. Other ways to guarantee a sequence point are, e.g., use of -// indirect calls and linux's __asm__ volatile. -// Note: as of 6973570, we have replaced the originally static "dummy" field -// (see above) by a volatile store to the stack. All of the versions of the -// compilers that we currently use (SunStudio, gcc and VC++) respect the -// semantics of volatile here. If you build HotSpot using other -// compilers, you may need to verify that no compiler reordering occurs -// across the sequence point represented by the volatile access. -// +// C++ volatile semantics prevent compiler re-ordering between +// volatile memory accesses. However, reordering between non-volatile +// and volatile memory accesses is in general undefined. For compiler +// reordering constraints taking non-volatile memory accesses into +// consideration, a compiler barrier has to be used instead. Some +// compiler implementations may choose to enforce additional +// constraints beyond those required by the language. Note also that +// both volatile semantics and compiler barrier do not prevent +// hardware reordering. // // os::is_MP Considered Redundant // @@ -240,8 +229,32 @@ // order. If their implementations change such that these assumptions // are violated, a whole lot of code will break. +enum ScopedFenceType { + X_ACQUIRE + , RELEASE_X + , RELEASE_X_FENCE +}; + +template +class ScopedFenceGeneral: public StackObj { + public: + void prefix() {} + void postfix() {} +}; + +template +class ScopedFence : public ScopedFenceGeneral { + void *const _field; + public: + ScopedFence(void *const field) : _field(field) { prefix(); } + ~ScopedFence() { postfix(); } + void prefix() { ScopedFenceGeneral::prefix(); } + void postfix() { ScopedFenceGeneral::postfix(); } +}; + class OrderAccess : AllStatic { public: + // barriers static void loadload(); static void storestore(); static void loadstore(); @@ -280,20 +293,6 @@ class OrderAccess : AllStatic { static void release_store_ptr(volatile intptr_t* p, intptr_t v); static void release_store_ptr(volatile void* p, void* v); - static void store_fence(jbyte* p, jbyte v); - static void store_fence(jshort* p, jshort v); - static void store_fence(jint* p, jint v); - static void store_fence(jlong* p, jlong v); - static void store_fence(jubyte* p, jubyte v); - static void store_fence(jushort* p, jushort v); - static void store_fence(juint* p, juint v); - static void store_fence(julong* p, julong v); - static void store_fence(jfloat* p, jfloat v); - static void store_fence(jdouble* p, jdouble v); - - static void store_ptr_fence(intptr_t* p, intptr_t v); - static void store_ptr_fence(void** p, void* v); - static void release_store_fence(volatile jbyte* p, jbyte v); static void release_store_fence(volatile jshort* p, jshort v); static void release_store_fence(volatile jint* p, jint v); @@ -313,6 +312,47 @@ class OrderAccess : AllStatic { // routine if it exists, It should only be used by platforms that // don't have another way to do the inline assembly. static void StubRoutines_fence(); + + // Give platforms a variation point to specialize. + template static T specialized_load_acquire (volatile T* p ); + template static void specialized_release_store (volatile T* p, T v); + template static void specialized_release_store_fence(volatile T* p, T v); + + template + static void ordered_store(volatile FieldType* p, FieldType v); + + template + static FieldType ordered_load(volatile FieldType* p); + + static void store(volatile jbyte* p, jbyte v); + static void store(volatile jshort* p, jshort v); + static void store(volatile jint* p, jint v); + static void store(volatile jlong* p, jlong v); + static void store(volatile jdouble* p, jdouble v); + static void store(volatile jfloat* p, jfloat v); + + static jbyte load (volatile jbyte* p); + static jshort load (volatile jshort* p); + static jint load (volatile jint* p); + static jlong load (volatile jlong* p); + static jdouble load (volatile jdouble* p); + static jfloat load (volatile jfloat* p); + + // The following store_fence methods are deprecated and will be removed + // when all repos conform to the new generalized OrderAccess. + static void store_fence(jbyte* p, jbyte v); + static void store_fence(jshort* p, jshort v); + static void store_fence(jint* p, jint v); + static void store_fence(jlong* p, jlong v); + static void store_fence(jubyte* p, jubyte v); + static void store_fence(jushort* p, jushort v); + static void store_fence(juint* p, juint v); + static void store_fence(julong* p, julong v); + static void store_fence(jfloat* p, jfloat v); + static void store_fence(jdouble* p, jdouble v); + + static void store_ptr_fence(intptr_t* p, intptr_t v); + static void store_ptr_fence(void** p, void* v); }; #endif // SHARE_VM_RUNTIME_ORDERACCESS_HPP diff --git a/hotspot/src/share/vm/runtime/orderAccess.inline.hpp b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp index 4fdd50d4fe8..bb17185cc02 100644 --- a/hotspot/src/share/vm/runtime/orderAccess.inline.hpp +++ b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ #ifndef SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP #define SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" // Linux @@ -71,4 +72,92 @@ # include "orderAccess_bsd_zero.inline.hpp" #endif +#ifdef VM_HAS_GENERALIZED_ORDER_ACCESS + +template<> inline void ScopedFenceGeneral::postfix() { OrderAccess::acquire(); } +template<> inline void ScopedFenceGeneral::prefix() { OrderAccess::release(); } +template<> inline void ScopedFenceGeneral::prefix() { OrderAccess::release(); } +template<> inline void ScopedFenceGeneral::postfix() { OrderAccess::fence(); } + + +template +inline void OrderAccess::ordered_store(volatile FieldType* p, FieldType v) { + ScopedFence f((void*)p); + store(p, v); +} + +template +inline FieldType OrderAccess::ordered_load(volatile FieldType* p) { + ScopedFence f((void*)p); + return load(p); +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return specialized_load_acquire(p); } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { return specialized_load_acquire(p); } +inline jint OrderAccess::load_acquire(volatile jint* p) { return specialized_load_acquire(p); } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return specialized_load_acquire(p); } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return specialized_load_acquire(p); } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return specialized_load_acquire(p); } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return (jubyte) specialized_load_acquire((volatile jbyte*)p); } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { return (jushort)specialized_load_acquire((volatile jshort*)p); } +inline juint OrderAccess::load_acquire(volatile juint* p) { return (juint) specialized_load_acquire((volatile jint*)p); } +inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong) specialized_load_acquire((volatile jlong*)p); } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)specialized_load_acquire(p); } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*)specialized_load_acquire((volatile intptr_t*)p); } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*)specialized_load_acquire((volatile intptr_t*)p); } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jint* p, jint v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { specialized_release_store((volatile jbyte*) p, (jbyte) v); } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { specialized_release_store((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store(volatile juint* p, juint v) { specialized_release_store((volatile jint*) p, (jint) v); } +inline void OrderAccess::release_store(volatile julong* p, julong v) { specialized_release_store((volatile jlong*) p, (jlong) v); } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { specialized_release_store((volatile intptr_t*)p, (intptr_t)v); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { specialized_release_store_fence((volatile jbyte*) p, (jbyte) v); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { specialized_release_store_fence((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { specialized_release_store_fence((volatile jint*) p, (jint) v); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { specialized_release_store_fence((volatile jlong*) p, (jlong) v); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { specialized_release_store_fence((volatile intptr_t*)p, (intptr_t)v); } + +// The following methods can be specialized using simple template specialization +// in the platform specific files for optimization purposes. Otherwise the +// generalized variant is used. +template inline T OrderAccess::specialized_load_acquire (volatile T* p) { return ordered_load(p); } +template inline void OrderAccess::specialized_release_store (volatile T* p, T v) { ordered_store(p, v); } +template inline void OrderAccess::specialized_release_store_fence(volatile T* p, T v) { ordered_store(p, v); } + +// Generalized atomic volatile accesses valid in OrderAccess +// All other types can be expressed in terms of these. +inline void OrderAccess::store(volatile jbyte* p, jbyte v) { *p = v; } +inline void OrderAccess::store(volatile jshort* p, jshort v) { *p = v; } +inline void OrderAccess::store(volatile jint* p, jint v) { *p = v; } +inline void OrderAccess::store(volatile jlong* p, jlong v) { Atomic::store(v, p); } +inline void OrderAccess::store(volatile jdouble* p, jdouble v) { Atomic::store(jlong_cast(v), (volatile jlong*)p); } +inline void OrderAccess::store(volatile jfloat* p, jfloat v) { *p = v; } + +inline jbyte OrderAccess::load(volatile jbyte* p) { return *p; } +inline jshort OrderAccess::load(volatile jshort* p) { return *p; } +inline jint OrderAccess::load(volatile jint* p) { return *p; } +inline jlong OrderAccess::load(volatile jlong* p) { return Atomic::load(p); } +inline jdouble OrderAccess::load(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } +inline jfloat OrderAccess::load(volatile jfloat* p) { return *p; } + +#endif // VM_HAS_GENERALIZED_ORDER_ACCESS + #endif // SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP From e616017fc8342b88504bc651e9be228ccb9b87cb Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 3 Mar 2015 19:42:09 +0000 Subject: [PATCH 04/79] 8073688: Infinite loop reading types during jmap attach Reviewed-by: dsamersoff, sla --- .../sun/jvm/hotspot/HotSpotTypeDataBase.java | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java index 2b9a7bc72ee..1097fb4dfcc 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @@ -51,6 +51,9 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { private static final int C_INT32_SIZE = 4; private static final int C_INT64_SIZE = 8; private static int pointerSize = UNINITIALIZED_SIZE; + // Counter to ensure read loops terminate: + private static final int MAX_DUPLICATE_DEFINITIONS = 100; + private int duplicateDefCount = 0; private static final boolean DEBUG; static { @@ -166,6 +169,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); + if (typeEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Start iterating down it until we find an entry with no name Address typeNameAddr = null; do { @@ -192,7 +199,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { } entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); - } while (typeNameAddr != null); + } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void initializePrimitiveTypes() { @@ -395,6 +406,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); + if (structEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMStructEntry* Address entryAddr = lookupInProcess("gHotSpotVMStructs"); // Dereference this once to get the pointer to the first VMStructEntry @@ -472,6 +487,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); + if (intConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + + // Fetch the address of the VMIntConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); // Dereference this once to get the pointer to the first VMIntConstantEntry @@ -501,12 +521,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { } else { System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void readVMLongConstants() { @@ -519,6 +544,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); + if (longConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMLongConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); // Dereference this once to get the pointer to the first VMLongConstantEntry @@ -548,12 +577,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { } else { System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions."); + } } private BasicType lookupOrFail(String typeName) { @@ -740,9 +774,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { } if (!typeNameIsPointerType(typeName)) { - System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + - "had its size declared as " + size + " twice. Continuing."); - } + System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + + "had its size declared as " + size + " twice. Continuing."); + duplicateDefCount++; + } } } From 9fae485daba05a89dc14c9c0e62dd69c3864e3c9 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 4 Mar 2015 16:35:58 -0500 Subject: [PATCH 05/79] 8073861: Unused VM Options in JDK9 HotSpot Reviewed-by: dholmes, lfoltan --- hotspot/src/share/vm/runtime/arguments.cpp | 2 ++ hotspot/src/share/vm/runtime/globals.hpp | 15 --------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index b0e6f6357a9..9f0821181b9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -321,6 +321,8 @@ static ObsoleteFlag obsolete_jvm_flags[] = { { "UseFastEmptyMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) }, #endif // ZERO { "UseCompilerSafepoints", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "AdaptiveSizePausePolicy", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { NULL, JDK_Version(0), JDK_Version(0) } }; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index ca86916aaff..a3daefa87a9 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1068,9 +1068,6 @@ class CommandLineFlags { notproduct(bool, ProfilerCheckIntervals, false, \ "Collect and print information on spacing of profiler ticks") \ \ - develop(bool, PrintJVMWarnings, false, \ - "Print warnings for unimplemented JVM functions") \ - \ product(bool, PrintWarnings, true, \ "Print JVM warnings to output stream") \ \ @@ -1195,10 +1192,6 @@ class CommandLineFlags { "Use pthread-based instead of libthread-based synchronization " \ "(SPARC only)") \ \ - product(bool, AdjustConcurrency, false, \ - "Call thr_setconcurrency at thread creation time to avoid " \ - "LWP starvation on MP systems (for Solaris Only)") \ - \ product(bool, ReduceSignalUsage, false, \ "Reduce the use of OS signals in Java and/or the VM") \ \ @@ -1545,11 +1538,6 @@ class CommandLineFlags { product(uintx, ParallelGCBufferWastePct, 10, \ "Wasted fraction of parallel allocation buffer") \ \ - diagnostic(bool, ParallelGCRetainPLAB, false, \ - "Retain parallel allocation buffers across scavenges; " \ - "it is disabled because this currently conflicts with " \ - "parallel card scanning under certain conditions.") \ - \ product(uintx, TargetPLABWastePct, 10, \ "Target wasted space in last buffer as percent of overall " \ "allocation") \ @@ -2089,9 +2077,6 @@ class CommandLineFlags { product(uintx, AdaptiveSizeThroughPutPolicy, 0, \ "Policy for changing generation size for throughput goals") \ \ - product(uintx, AdaptiveSizePausePolicy, 0, \ - "Policy for changing generation size for pause goals") \ - \ develop(bool, PSAdjustTenuredGenForMinorPause, false, \ "Adjust tenured generation to achieve a minor pause goal") \ \ From c4df8e24bcef4bdd87e4b03e63ca9c6e618693fa Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Thu, 5 Mar 2015 11:39:15 +0100 Subject: [PATCH 06/79] 8058470: [jconsole] VM Summary Tab is blank for JDK9's jconsole Reviewed-by: erikj --- make/common/JavaCompilation.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk index 41f1f0745da..d2bad5e88de 100644 --- a/make/common/JavaCompilation.gmk +++ b/make/common/JavaCompilation.gmk @@ -393,7 +393,7 @@ define add_file_to_clean $(MKDIR) -p $$(@D) export LC_ALL=C ; ( $(CAT) $$< && $(ECHO) "" ) \ | $(SED) -e 's/\([^\\]\):/\1\\:/g' -e 's/\([^\\]\)=/\1\\=/g' \ - -e 's/\([^\\]\)!/\1\\!/g' -e 's/#.*/#/g' \ + -e 's/\([^\\]\)!/\1\\!/g' -e 's/^[ ]*#.*/#/g' \ | $(SED) -f "$(SRC_ROOT)/make/common/support/unicode2x.sed" \ | $(SED) -e '/^#/d' -e '/^$$$$/d' \ -e :a -e '/\\$$$$/N; s/\\\n//; ta' \ From 8fe1e48f0c389d7d43621d94b226cdd479a03b61 Mon Sep 17 00:00:00 2001 From: David Lindholm Date: Thu, 5 Mar 2015 16:43:26 +0100 Subject: [PATCH 07/79] 8073545: Use shorter and more descriptive names for GC worker threads Reviewed-by: ehelin, jwilhelm --- .../concurrentMarkSweep/concurrentMarkSweepGeneration.cpp | 2 +- .../concurrentMarkSweep/concurrentMarkSweepThread.cpp | 2 +- .../vm/gc_implementation/g1/concurrentG1RefineThread.cpp | 2 +- hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp | 2 +- .../share/vm/gc_implementation/g1/concurrentMarkThread.cpp | 4 ++-- .../src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp | 4 ++-- .../vm/gc_implementation/parallelScavenge/gcTaskThread.cpp | 2 +- hotspot/src/share/vm/memory/sharedHeap.cpp | 4 ++-- hotspot/src/share/vm/utilities/workgroup.cpp | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index c4a3ac44c48..c89cbedda29 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -549,7 +549,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4); } if (ConcGCThreads > 1) { - _conc_workers = new YieldingFlexibleWorkGang("Parallel CMS Threads", + _conc_workers = new YieldingFlexibleWorkGang("CMS Thread", ConcGCThreads, true); if (_conc_workers == NULL) { warning("GC/CMS: _conc_workers allocation failure: " diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp index 73f265a4028..41b9e377453 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp @@ -65,7 +65,7 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) assert(_collector == NULL, "Collector already set"); _collector = collector; - set_name("Concurrent Mark-Sweep GC Thread"); + set_name("CMS Main Thread"); if (os::create_thread(this, os::cgc_thread)) { // An old comment here said: "Priority should be just less diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp index 56ae3c2a7f2..092bd536456 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @@ -61,7 +61,7 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex create_and_start(); // set name - set_name("G1 Concurrent Refinement Thread#%d", worker_id); + set_name("G1 Refine#%d", worker_id); } void ConcurrentG1RefineThread::initialize() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index bdd5e551016..5b7239d6536 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -687,7 +687,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); #endif - _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", + _parallel_workers = new FlexibleWorkGang("G1 Marker", _max_parallel_marking_threads, false, true); if (_parallel_workers == NULL) { vm_exit_during_initialization("Failed necessary allocation."); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index 5b51a6f4675..f67d8fe5635 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -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 @@ -48,7 +48,7 @@ ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : _vtime_accum(0.0), _vtime_mark_accum(0.0) { - set_name("G1 Main Concurrent Mark GC Thread"); + set_name("G1 Main Marker"); create_and_start(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp index 3069770313e..905dda74815 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -34,7 +34,7 @@ G1StringDedupThread* G1StringDedupThread::_thread = NULL; G1StringDedupThread::G1StringDedupThread() : ConcurrentGCThread() { - set_name("String Deduplication Thread"); + set_name("G1 StrDedup"); create_and_start(); } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp index ff58762c20e..91f23612a56 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp @@ -53,7 +53,7 @@ GCTaskThread::GCTaskThread(GCTaskManager* manager, guarantee(_time_stamps != NULL, "Sanity"); } set_id(which); - set_name("GC task thread#%d (ParallelGC)", which); + set_name("ParGC Thread#%d", which); } GCTaskThread::~GCTaskThread() { diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index 7450cc92879..d6617af237e 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -68,7 +68,7 @@ SharedHeap::SharedHeap(CollectorPolicy* policy_) : } _sh = this; // ch is static, should be set only once. if (UseConcMarkSweepGC || UseG1GC) { - _workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads, + _workers = new FlexibleWorkGang("GC Thread", ParallelGCThreads, /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false); if (_workers == NULL) { diff --git a/hotspot/src/share/vm/utilities/workgroup.cpp b/hotspot/src/share/vm/utilities/workgroup.cpp index 3f20f36ce7e..dc260422adf 100644 --- a/hotspot/src/share/vm/utilities/workgroup.cpp +++ b/hotspot/src/share/vm/utilities/workgroup.cpp @@ -236,7 +236,7 @@ void AbstractWorkGang::threads_do(ThreadClosure* tc) const { GangWorker::GangWorker(AbstractWorkGang* gang, uint id) { _gang = gang; set_id(id); - set_name("Gang worker#%d (%s)", id, gang->name()); + set_name("%s#%d", gang->name(), id); } void GangWorker::run() { From 67fddc10a68ac593ee45f846d3c032d8e7105e60 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Fri, 6 Mar 2015 09:07:33 +0100 Subject: [PATCH 08/79] 8031538: G1 eden usage is sometimes higher than target eden (printed Eden size) When recalculating the number of target eden size, correctly consider the amount of existing eden regions in the target calculation. Reviewed-by: tschatzl --- .../vm/gc_implementation/g1/g1CollectedHeap.hpp | 3 ++- .../gc_implementation/g1/g1CollectorPolicy.cpp | 17 +++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index c47a8516a63..42a7229a9e0 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -110,6 +110,7 @@ public: void empty_list(); bool is_empty() { return _length == 0; } uint length() { return _length; } + uint eden_length() { return length() - survivor_length(); } uint survivor_length() { return _survivor_length; } // Currently we do not keep track of the used byte sum for the @@ -119,7 +120,7 @@ public: // we'll report the more accurate information then. size_t eden_used_bytes() { assert(length() >= survivor_length(), "invariant"); - return (size_t) (length() - survivor_length()) * HeapRegion::GrainBytes; + return (size_t) eden_length() * HeapRegion::GrainBytes; } size_t survivor_used_bytes() { return (size_t) survivor_length() * HeapRegion::GrainBytes; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 2507d4e3e28..21cbf9fb57e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -537,15 +537,12 @@ void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { // This is how many young regions we already have (currently: the survivors). uint base_min_length = recorded_survivor_regions(); - // This is the absolute minimum young length, which ensures that we - // can allocate one eden region in the worst-case. - uint absolute_min_length = base_min_length + 1; - uint desired_min_length = - calculate_young_list_desired_min_length(base_min_length); - if (desired_min_length < absolute_min_length) { - desired_min_length = absolute_min_length; - } - + uint desired_min_length = calculate_young_list_desired_min_length(base_min_length); + // This is the absolute minimum young length. Ensure that we + // will at least have one eden region available for allocation. + uint absolute_min_length = base_min_length + MAX2(_g1->young_list()->eden_length(), (uint)1); + // If we shrank the young list target it should not shrink below the current size. + desired_min_length = MAX2(desired_min_length, absolute_min_length); // Calculate the absolute and desired max bounds. // We will try our best not to "eat" into the reserve. @@ -1925,7 +1922,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInf // [Newly Young Regions ++ Survivors from last pause]. uint survivor_region_length = young_list->survivor_length(); - uint eden_region_length = young_list->length() - survivor_region_length; + uint eden_region_length = young_list->eden_length(); init_cset_region_lengths(eden_region_length, survivor_region_length); HeapRegion* hr = young_list->first_survivor_region(); From d0650dcdae661507c6fb5413416a5525777d4d39 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 6 Mar 2015 14:53:00 +0100 Subject: [PATCH 09/79] 8074554: Create custom hook for running after AC_OUTPUT Reviewed-by: erikj --- common/autoconf/configure.ac | 2 ++ common/autoconf/generated-configure.sh | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 902ba475684..193b768437f 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -54,6 +54,7 @@ m4_include([toolchain_windows.m4]) AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK]) AC_DEFUN_ONCE([CUSTOM_LATE_HOOK]) +AC_DEFUN_ONCE([CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK]) AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK]) # This line needs to be here, verbatim, after all includes and the dummy hook @@ -264,6 +265,7 @@ CONFIG_STATUS="$OUTPUT_ROOT/config.status" # Create the actual output files. Now the main work of configure is done. AC_OUTPUT +CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK # Try to move the config.log file to the output directory. if test -e ./config.log; then diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 6029574b757..7ae33d1de08 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4387,13 +4387,14 @@ VS_SDK_PLATFORM_NAME_2013= + # This line needs to be here, verbatim, after all includes and the dummy hook # definitions. It is replaced with custom functionality when building # custom sources. #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1424976950 +DATE_WHEN_GENERATED=1425649598 ############################################################################### # @@ -53396,6 +53397,7 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi + # Try to move the config.log file to the output directory. if test -e ./config.log; then $MV -f ./config.log "$OUTPUT_ROOT/config.log" 2> /dev/null From 179f7eb9ff9bda86314bd41e5c03c5015918f014 Mon Sep 17 00:00:00 2001 From: Andrey Zakharov Date: Fri, 6 Mar 2015 16:12:54 +0100 Subject: [PATCH 10/79] 8051984: @ignore should be placed after @test As ignore reason has been fixed (by adding @requires) @ignore removed Reviewed-by: kbarrett, brutisso --- hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java index d029b45e0bb..4c9e8c53122 100644 --- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java +++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -22,7 +22,6 @@ */ /** - * @ignore 8019361 * @test TestDynShrinkHeap * @bug 8016479 * @requires vm.gc=="Parallel" | vm.gc=="null" @@ -35,7 +34,7 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.util.ArrayList; import sun.management.ManagementFactoryHelper; -import static com.oracle.java.testlibrary.Asserts.*; +import static com.oracle.java.testlibrary.Asserts.assertLessThan; public class TestDynShrinkHeap { From d0d14d12cac04880d006cd40562eaeba17c064f5 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 9 Mar 2015 08:22:34 +0100 Subject: [PATCH 11/79] 8074543: Missing symbol "objArrayOopDesc::obj_at" when buiding with CPP Interpreter Reviewed-by: stefank --- hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 5ec7ec89dbe..991aca1a357 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -34,6 +34,7 @@ #include "memory/resourceArea.hpp" #include "oops/methodCounters.hpp" #include "oops/objArrayKlass.hpp" +#include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" From 1a8c9118812c56f0044a4fa6b1e3c7082db4534b Mon Sep 17 00:00:00 2001 From: Axel Siebenborn Date: Fri, 6 Mar 2015 16:47:46 +0100 Subject: [PATCH 12/79] 8074561: Wrong volatile qualifier for field ClassLoaderDataGraphKlassIteratorAtomic::_next_klass Reviewed-by: mgerdin, stefank --- hotspot/src/share/vm/classfile/classLoaderData.cpp | 2 +- hotspot/src/share/vm/classfile/classLoaderData.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index cc201714142..f937cf381de 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -902,7 +902,7 @@ Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) } Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() { - Klass* head = (Klass*)_next_klass; + Klass* head = _next_klass; while (head != NULL) { Klass* next = next_klass_in_cldg(head); diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index a9ccaf81fe2..450afb425d2 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -315,7 +315,7 @@ class ClassLoaderData : public CHeapObj { // An iterator that distributes Klasses to parallel worker threads. class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj { - volatile Klass* _next_klass; + Klass* volatile _next_klass; public: ClassLoaderDataGraphKlassIteratorAtomic(); Klass* next_klass(); From 808f9cab051a0ed5681fd8d7d17967814b54d7b5 Mon Sep 17 00:00:00 2001 From: Gerald Thornbrugh Date: Fri, 6 Mar 2015 17:19:08 -0800 Subject: [PATCH 13/79] 8071501: perfMemory_solaris.cpp failing to compile with "Error: dd_fd is not a member of DIR." Force all Solaris builds to use the same version of the DIR structure. Reviewed-by: dcubed, dholmes, kvn --- hotspot/src/os/solaris/vm/jvm_solaris.h | 4 +++- .../src/share/vm/utilities/globalDefinitions_sparcWorks.hpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hotspot/src/os/solaris/vm/jvm_solaris.h b/hotspot/src/os/solaris/vm/jvm_solaris.h index 57b32ac1658..f1fa075bc88 100644 --- a/hotspot/src/os/solaris/vm/jvm_solaris.h +++ b/hotspot/src/os/solaris/vm/jvm_solaris.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -41,7 +41,9 @@ * JNI conversion, which should be sorted out later. */ +#define __USE_LEGACY_PROTOTYPES__ #include /* For DIR */ +#undef __USE_LEGACY_PROTOTYPES__ #include /* For MAXPATHLEN */ #include /* For socklen_t */ #include /* For F_OK, R_OK, W_OK */ diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp index 352d2c709f7..b42a22e7004 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -33,7 +33,9 @@ # include +#define __USE_LEGACY_PROTOTYPES__ # include +#undef __USE_LEGACY_PROTOTYPES__ # include # include // for bsd'isms # include From 1a4c355bbcf3819a45a724297080b7dbc6852c6b Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Mon, 9 Mar 2015 09:30:16 -0700 Subject: [PATCH 14/79] 8073654: Marking statistics should use size_t Change data type from int to size_t to avoid overflows Reviewed-by: jwilhelm, drwhite, tschatzl --- .../gc_implementation/g1/concurrentMark.cpp | 44 ++++++++--------- .../gc_implementation/g1/concurrentMark.hpp | 48 +++++++++---------- .../g1/concurrentMark.inline.hpp | 4 +- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 5b7239d6536..6d7197c060a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -3561,6 +3561,15 @@ void CMTask::reset(CMBitMap* nextMarkBitMap) { _termination_start_time_ms = 0.0; #if _MARKING_STATS_ + _aborted = 0; + _aborted_overflow = 0; + _aborted_cm_aborted = 0; + _aborted_yield = 0; + _aborted_timed_out = 0; + _aborted_satb = 0; + _aborted_termination = 0; + _steal_attempts = 0; + _steals = 0; _local_pushes = 0; _local_pops = 0; _local_max_size = 0; @@ -3573,15 +3582,6 @@ void CMTask::reset(CMBitMap* nextMarkBitMap) { _regions_claimed = 0; _objs_found_on_bitmap = 0; _satb_buffers_processed = 0; - _steal_attempts = 0; - _steals = 0; - _aborted = 0; - _aborted_overflow = 0; - _aborted_cm_aborted = 0; - _aborted_yield = 0; - _aborted_timed_out = 0; - _aborted_satb = 0; - _aborted_termination = 0; #endif // _MARKING_STATS_ } @@ -3742,7 +3742,7 @@ void CMTask::move_entries_to_global_stack() { gclog_or_tty->print_cr("[%u] pushed %d entries to the global stack", _worker_id, n); } - statsOnly( int tmp_size = _cm->mark_stack_size(); + statsOnly( size_t tmp_size = _cm->mark_stack_size(); if (tmp_size > _global_max_size) { _global_max_size = tmp_size; } @@ -3777,7 +3777,7 @@ void CMTask::get_entries_from_global_stack() { assert(success, "invariant"); } - statsOnly( int tmp_size = _task_queue->size(); + statsOnly( size_t tmp_size = (size_t)_task_queue->size(); if (tmp_size > _local_max_size) { _local_max_size = tmp_size; } @@ -3934,24 +3934,24 @@ void CMTask::print_stats() { gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", _all_clock_intervals_ms.maximum(), _all_clock_intervals_ms.sum()); - gclog_or_tty->print_cr(" Clock Causes (cum): scanning = %d, marking = %d", + gclog_or_tty->print_cr(" Clock Causes (cum): scanning = " SIZE_FORMAT ", marking = " SIZE_FORMAT, _clock_due_to_scanning, _clock_due_to_marking); - gclog_or_tty->print_cr(" Objects: scanned = %d, found on the bitmap = %d", + gclog_or_tty->print_cr(" Objects: scanned = " SIZE_FORMAT ", found on the bitmap = " SIZE_FORMAT, _objs_scanned, _objs_found_on_bitmap); - gclog_or_tty->print_cr(" Local Queue: pushes = %d, pops = %d, max size = %d", + gclog_or_tty->print_cr(" Local Queue: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, _local_pushes, _local_pops, _local_max_size); - gclog_or_tty->print_cr(" Global Stack: pushes = %d, pops = %d, max size = %d", + gclog_or_tty->print_cr(" Global Stack: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, _global_pushes, _global_pops, _global_max_size); - gclog_or_tty->print_cr(" transfers to = %d, transfers from = %d", + gclog_or_tty->print_cr(" transfers to = " SIZE_FORMAT ", transfers from = " SIZE_FORMAT, _global_transfers_to,_global_transfers_from); - gclog_or_tty->print_cr(" Regions: claimed = %d", _regions_claimed); - gclog_or_tty->print_cr(" SATB buffers: processed = %d", _satb_buffers_processed); - gclog_or_tty->print_cr(" Steals: attempts = %d, successes = %d", + gclog_or_tty->print_cr(" Regions: claimed = " SIZE_FORMAT, _regions_claimed); + gclog_or_tty->print_cr(" SATB buffers: processed = " SIZE_FORMAT, _satb_buffers_processed); + gclog_or_tty->print_cr(" Steals: attempts = " SIZE_FORMAT ", successes = " SIZE_FORMAT, _steal_attempts, _steals); - gclog_or_tty->print_cr(" Aborted: %d, due to", _aborted); - gclog_or_tty->print_cr(" overflow: %d, global abort: %d, yield: %d", + gclog_or_tty->print_cr(" Aborted: " SIZE_FORMAT ", due to", _aborted); + gclog_or_tty->print_cr(" overflow: " SIZE_FORMAT ", global abort: " SIZE_FORMAT ", yield: " SIZE_FORMAT, _aborted_overflow, _aborted_cm_aborted, _aborted_yield); - gclog_or_tty->print_cr(" time out: %d, SATB: %d, termination: %d", + gclog_or_tty->print_cr(" time out: " SIZE_FORMAT ", SATB: " SIZE_FORMAT ", termination: " SIZE_FORMAT, _aborted_timed_out, _aborted_satb, _aborted_termination); #endif // _MARKING_STATS_ } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 6e18c011336..03b98366f36 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -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 @@ -1039,36 +1039,36 @@ private: NumberSeq _all_clock_intervals_ms; double _interval_start_time_ms; - int _aborted; - int _aborted_overflow; - int _aborted_cm_aborted; - int _aborted_yield; - int _aborted_timed_out; - int _aborted_satb; - int _aborted_termination; + size_t _aborted; + size_t _aborted_overflow; + size_t _aborted_cm_aborted; + size_t _aborted_yield; + size_t _aborted_timed_out; + size_t _aborted_satb; + size_t _aborted_termination; - int _steal_attempts; - int _steals; + size_t _steal_attempts; + size_t _steals; - int _clock_due_to_marking; - int _clock_due_to_scanning; + size_t _clock_due_to_marking; + size_t _clock_due_to_scanning; - int _local_pushes; - int _local_pops; - int _local_max_size; - int _objs_scanned; + size_t _local_pushes; + size_t _local_pops; + size_t _local_max_size; + size_t _objs_scanned; - int _global_pushes; - int _global_pops; - int _global_max_size; + size_t _global_pushes; + size_t _global_pops; + size_t _global_max_size; - int _global_transfers_to; - int _global_transfers_from; + size_t _global_transfers_to; + size_t _global_transfers_from; - int _regions_claimed; - int _objs_found_on_bitmap; + size_t _regions_claimed; + size_t _objs_found_on_bitmap; - int _satb_buffers_processed; + size_t _satb_buffers_processed; #endif // _MARKING_STATS_ // it updates the local fields after this task has claimed diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp index c705eaea33b..0b32d13a167 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, 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 @@ -252,7 +252,7 @@ inline void CMTask::push(oop obj) { assert(success, "invariant"); } - statsOnly( int tmp_size = _task_queue->size(); + statsOnly( size_t tmp_size = (size_t)_task_queue->size(); if (tmp_size > _local_max_size) { _local_max_size = tmp_size; } From ca4b73ad278bafdf718a3237a88b60816d95b05b Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 9 Mar 2015 13:39:24 -0400 Subject: [PATCH 15/79] 8013393: Merge template interpreter files for x86 _32 and _64 The 32 and 64 bit versions of templateTable_x86 have been merged. Reviewed-by: twisti, jrose, coleenp --- ...Table_x86_64.cpp => templateTable_x86.cpp} | 1434 ++++--- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 3668 ----------------- 2 files changed, 964 insertions(+), 4138 deletions(-) rename hotspot/src/cpu/x86/vm/{templateTable_x86_64.cpp => templateTable_x86.cpp} (73%) delete mode 100644 hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp similarity index 73% rename from hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp rename to hotspot/src/cpu/x86/vm/templateTable_x86.cpp index acb4e146415..7b6696efeed 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -42,22 +42,30 @@ #define __ _masm-> -// Platform-dependent initialization +// Global Register Names +Register rbcp = LP64_ONLY(r13) NOT_LP64(rsi); +Register rlocals = LP64_ONLY(r14) NOT_LP64(rdi); +// Platform-dependent initialization void TemplateTable::pd_initialize() { - // No amd64 specific initialization + // No x86 specific initialization } -// Address computation: local variables - +// Address Computation: local variables static inline Address iaddress(int n) { - return Address(r14, Interpreter::local_offset_in_bytes(n)); + return Address(rlocals, Interpreter::local_offset_in_bytes(n)); } static inline Address laddress(int n) { return iaddress(n + 1); } +#ifndef _LP64 +static inline Address haddress(int n) { + return iaddress(n + 0); +} +#endif + static inline Address faddress(int n) { return iaddress(n); } @@ -71,13 +79,19 @@ static inline Address aaddress(int n) { } static inline Address iaddress(Register r) { - return Address(r14, r, Address::times_8); + return Address(rlocals, r, Address::times_ptr); } static inline Address laddress(Register r) { - return Address(r14, r, Address::times_8, Interpreter::local_offset_in_bytes(1)); + return Address(rlocals, r, Address::times_ptr, Interpreter::local_offset_in_bytes(1)); } +#ifndef _LP64 +static inline Address haddress(Register r) { + return Address(rlocals, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(0)); +} +#endif + static inline Address faddress(Register r) { return iaddress(r); } @@ -90,7 +104,12 @@ static inline Address aaddress(Register r) { return iaddress(r); } -static inline Address at_rsp() { + +// expression stack +// (Note: Must not use symmetric equivalents at_rsp_m1/2 since they store +// data beyond the rsp which is potentially unsafe in an MT environment; +// an interrupt may overwrite that data.) +static inline Address at_rsp () { return Address(rsp, 0); } @@ -123,10 +142,12 @@ static Assembler::Condition j_not(TemplateTable::Condition cc) { } + // Miscelaneous helper routines // Store an oop (or NULL) at the address described by obj. // If val == noreg this means store a NULL + static void do_oop_store(InterpreterMacroAssembler* _masm, Address obj, Register val, @@ -139,17 +160,25 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, case BarrierSet::G1SATBCTLogging: { // flatten object address if needed + // We do it regardless of precise because we need the registers if (obj.index() == noreg && obj.disp() == 0) { if (obj.base() != rdx) { - __ movq(rdx, obj.base()); + __ movptr(rdx, obj.base()); } } else { - __ leaq(rdx, obj); + __ lea(rdx, obj); } + + Register rtmp = LP64_ONLY(r8) NOT_LP64(rsi); + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + + NOT_LP64(__ get_thread(rcx)); + NOT_LP64(__ save_bcp()); + __ g1_write_barrier_pre(rdx /* obj */, rbx /* pre_val */, - r15_thread /* thread */, - r8 /* tmp */, + rthread /* thread */, + rtmp /* tmp */, val != noreg /* tosca_live */, false /* expand_call */); if (val == noreg) { @@ -164,10 +193,11 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, __ store_heap_oop(Address(rdx, 0), val); __ g1_write_barrier_post(rdx /* store_adr */, new_val /* new_val */, - r15_thread /* thread */, - r8 /* tmp */, + rthread /* thread */, + rtmp /* tmp */, rbx /* tmp2 */); } + NOT_LP64( __ restore_bcp()); } break; #endif // INCLUDE_ALL_GCS @@ -182,7 +212,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, if (!precise || (obj.index() == noreg && obj.disp() == 0)) { __ store_check(obj.base()); } else { - __ leaq(rdx, obj); + __ lea(rdx, obj); __ store_check(rdx); } } @@ -203,9 +233,10 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, Address TemplateTable::at_bcp(int offset) { assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); - return Address(r13, offset); + return Address(rbcp, offset); } + void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg/*=true*/, int byte_no) { @@ -251,7 +282,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ jcc(Assembler::notEqual, L_fast_patch); __ get_method(temp_reg); // Let breakpoint table handling rewrite to quicker bytecode - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, r13, bc_reg); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, rbcp, bc_reg); #ifndef ASSERT __ jmpb(L_patch_done); #else @@ -275,10 +306,9 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ movb(at_bcp(0), bc_reg); __ bind(L_patch_done); } - - // Individual instructions + void TemplateTable::nop() { transition(vtos, vtos); // nothing to do @@ -310,10 +340,17 @@ void TemplateTable::lconst(int value) { } else { __ movl(rax, value); } +#ifndef _LP64 + assert(value >= 0, "check this code"); + __ xorptr(rdx, rdx); +#endif } + + void TemplateTable::fconst(int value) { transition(vtos, ftos); +#ifdef _LP64 static float one = 1.0f, two = 2.0f; switch (value) { case 0: @@ -329,10 +366,18 @@ void TemplateTable::fconst(int value) { ShouldNotReachHere(); break; } +#else + if (value == 0) { __ fldz(); + } else if (value == 1) { __ fld1(); + } else if (value == 2) { __ fld1(); __ fld1(); __ faddp(); // should do a better solution here + } else { ShouldNotReachHere(); + } +#endif } void TemplateTable::dconst(int value) { transition(vtos, dtos); +#ifdef _LP64 static double one = 1.0; switch (value) { case 0: @@ -345,6 +390,13 @@ void TemplateTable::dconst(int value) { ShouldNotReachHere(); break; } + +#else + if (value == 0) { __ fldz(); + } else if (value == 1) { __ fld1(); + } else { ShouldNotReachHere(); + } +#endif } void TemplateTable::bipush() { @@ -361,6 +413,7 @@ void TemplateTable::sipush() { void TemplateTable::ldc(bool wide) { transition(vtos, vtos); + Register rarg = NOT_LP64(rcx) LP64_ONLY(c_rarg1); Label call_ldc, notFloat, notClass, Done; if (wide) { @@ -390,18 +443,21 @@ void TemplateTable::ldc(bool wide) { __ jcc(Assembler::notEqual, notClass); __ bind(call_ldc); - __ movl(c_rarg1, wide); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), c_rarg1); - __ push_ptr(rax); - __ verify_oop(rax); + + __ movl(rarg, wide); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), rarg); + + __ push(atos); __ jmp(Done); __ bind(notClass); __ cmpl(rdx, JVM_CONSTANT_Float); __ jccb(Assembler::notEqual, notFloat); + // ftos - __ movflt(xmm0, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_f(); + LP64_ONLY(__ movflt(xmm0, Address(rcx, rbx, Address::times_8, base_offset))); + NOT_LP64(__ fld_s( Address(rcx, rbx, Address::times_ptr, base_offset))); + __ push(ftos); __ jmp(Done); __ bind(notFloat); @@ -416,8 +472,8 @@ void TemplateTable::ldc(bool wide) { } #endif // itos JVM_CONSTANT_Integer only - __ movl(rax, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_i(rax); + __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset)); + __ push(itos); __ bind(Done); } @@ -465,15 +521,19 @@ void TemplateTable::ldc2_w() { __ cmpb(Address(rax, rbx, Address::times_1, tags_offset), JVM_CONSTANT_Double); __ jccb(Assembler::notEqual, Long); - // dtos - __ movdbl(xmm0, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_d(); - __ jmpb(Done); + // dtos + LP64_ONLY(__ movdbl(xmm0, Address(rcx, rbx, Address::times_8, base_offset))); + NOT_LP64(__ fld_d( Address(rcx, rbx, Address::times_ptr, base_offset))); + __ push(dtos); + + __ jmpb(Done); __ bind(Long); + // ltos - __ movq(rax, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_l(); + __ movptr(rax, Address(rcx, rbx, Address::times_ptr, base_offset + 0 * wordSize)); + NOT_LP64(__ movptr(rdx, Address(rcx, rbx, Address::times_ptr, base_offset + 1 * wordSize))); + __ push(ltos); __ bind(Done); } @@ -487,8 +547,8 @@ void TemplateTable::iload() { transition(vtos, itos); if (RewriteFrequentPairs) { Label rewrite, done; - const Register bc = c_rarg3; - assert(rbx != bc, "register damaged"); + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + LP64_ONLY(assert(rbx != bc, "register damaged")); // get next byte __ load_unsigned_byte(rbx, @@ -502,6 +562,7 @@ void TemplateTable::iload() { __ cmpl(rbx, Bytecodes::_fast_iload); __ movl(bc, Bytecodes::_fast_iload2); + __ jccb(Assembler::equal, rewrite); // if _caload, rewrite to fast_icaload @@ -542,19 +603,22 @@ void TemplateTable::fast_iload() { void TemplateTable::lload() { transition(vtos, ltos); locals_index(rbx); - __ movq(rax, laddress(rbx)); + __ movptr(rax, laddress(rbx)); + NOT_LP64(__ movl(rdx, haddress(rbx))); } void TemplateTable::fload() { transition(vtos, ftos); locals_index(rbx); - __ movflt(xmm0, faddress(rbx)); + LP64_ONLY(__ movflt(xmm0, faddress(rbx))); + NOT_LP64(__ fld_s(faddress(rbx))); } void TemplateTable::dload() { transition(vtos, dtos); locals_index(rbx); - __ movdbl(xmm0, daddress(rbx)); + LP64_ONLY(__ movdbl(xmm0, daddress(rbx))); + NOT_LP64(__ fld_d(daddress(rbx))); } void TemplateTable::aload() { @@ -579,19 +643,22 @@ void TemplateTable::wide_iload() { void TemplateTable::wide_lload() { transition(vtos, ltos); locals_index_wide(rbx); - __ movq(rax, laddress(rbx)); + __ movptr(rax, laddress(rbx)); + NOT_LP64(__ movl(rdx, haddress(rbx))); } void TemplateTable::wide_fload() { transition(vtos, ftos); locals_index_wide(rbx); - __ movflt(xmm0, faddress(rbx)); + LP64_ONLY(__ movflt(xmm0, faddress(rbx))); + NOT_LP64(__ fld_s(faddress(rbx))); } void TemplateTable::wide_dload() { transition(vtos, dtos); locals_index_wide(rbx); - __ movdbl(xmm0, daddress(rbx)); + LP64_ONLY(__ movdbl(xmm0, daddress(rbx))); + NOT_LP64(__ fld_d(daddress(rbx))); } void TemplateTable::wide_aload() { @@ -601,6 +668,12 @@ void TemplateTable::wide_aload() { } void TemplateTable::index_check(Register array, Register index) { + // Pop ptr into array + __ pop_ptr(array); + index_check_without_pop(array, index); +} + +void TemplateTable::index_check_without_pop(Register array, Register index) { // destroys rbx // check array __ null_check(array, arrayOopDesc::length_offset_in_bytes()); @@ -609,7 +682,7 @@ void TemplateTable::index_check(Register array, Register index) { // check index __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes())); if (index != rbx) { - // ??? convention: move aberrant index into ebx for exception message + // ??? convention: move aberrant index into rbx for exception message assert(rbx != array, "different registers"); __ movl(rbx, index); } @@ -617,10 +690,10 @@ void TemplateTable::index_check(Register array, Register index) { ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); } + void TemplateTable::iaload() { transition(itos, itos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx __ movl(rax, Address(rdx, rax, @@ -630,70 +703,63 @@ void TemplateTable::iaload() { void TemplateTable::laload() { transition(itos, ltos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ movq(rax, Address(rdx, rbx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_LONG))); + NOT_LP64(__ mov(rbx, rax)); + // rbx,: index + __ movptr(rax, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize)); + NOT_LP64(__ movl(rdx, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize))); } + + void TemplateTable::faload() { transition(itos, ftos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ movflt(xmm0, Address(rdx, rax, + LP64_ONLY(__ movflt(xmm0, Address(rdx, rax, Address::times_4, - arrayOopDesc::base_offset_in_bytes(T_FLOAT))); + arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); + NOT_LP64(__ fld_s(Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); } void TemplateTable::daload() { transition(itos, dtos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ movdbl(xmm0, Address(rdx, rax, + LP64_ONLY(__ movdbl(xmm0, Address(rdx, rax, Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); + arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); + NOT_LP64(__ fld_d(Address(rdx, rax, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); } void TemplateTable::aaload() { transition(itos, atos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx __ load_heap_oop(rax, Address(rdx, rax, - UseCompressedOops ? Address::times_4 : Address::times_8, + UseCompressedOops ? Address::times_4 : Address::times_ptr, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } void TemplateTable::baload() { transition(itos, itos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ load_signed_byte(rax, - Address(rdx, rax, - Address::times_1, - arrayOopDesc::base_offset_in_bytes(T_BYTE))); + __ load_signed_byte(rax, Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE))); } void TemplateTable::caload() { transition(itos, itos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ load_unsigned_short(rax, - Address(rdx, rax, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_CHAR))); + __ load_unsigned_short(rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); } // iload followed by caload frequent pair @@ -703,9 +769,8 @@ void TemplateTable::fast_icaload() { locals_index(rbx); __ movl(rax, iaddress(rbx)); - // eax: index + // rax: index // rdx: array - __ pop_ptr(rdx); index_check(rdx, rax); // kills rbx __ load_unsigned_short(rax, Address(rdx, rax, @@ -713,16 +778,13 @@ void TemplateTable::fast_icaload() { arrayOopDesc::base_offset_in_bytes(T_CHAR))); } + void TemplateTable::saload() { transition(itos, itos); - __ pop_ptr(rdx); - // eax: index + // rax: index // rdx: array index_check(rdx, rax); // kills rbx - __ load_signed_short(rax, - Address(rdx, rax, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_SHORT))); + __ load_signed_short(rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); } void TemplateTable::iload(int n) { @@ -732,17 +794,20 @@ void TemplateTable::iload(int n) { void TemplateTable::lload(int n) { transition(vtos, ltos); - __ movq(rax, laddress(n)); + __ movptr(rax, laddress(n)); + NOT_LP64(__ movptr(rdx, haddress(n))); } void TemplateTable::fload(int n) { transition(vtos, ftos); - __ movflt(xmm0, faddress(n)); + LP64_ONLY(__ movflt(xmm0, faddress(n))); + NOT_LP64(__ fld_s(faddress(n))); } void TemplateTable::dload(int n) { transition(vtos, dtos); - __ movdbl(xmm0, daddress(n)); + LP64_ONLY(__ movdbl(xmm0, daddress(n))); + NOT_LP64(__ fld_d(daddress(n))); } void TemplateTable::aload(int n) { @@ -775,11 +840,12 @@ void TemplateTable::aload_0() { // to rewrite if (RewriteFrequentPairs) { Label rewrite, done; - const Register bc = c_rarg3; - assert(rbx != bc, "register damaged"); + + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + LP64_ONLY(assert(rbx != bc, "register damaged")); + // get next byte - __ load_unsigned_byte(rbx, - at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); + __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); // do actual aload_0 aload(0); @@ -789,33 +855,25 @@ void TemplateTable::aload_0() { __ jcc(Assembler::equal, done); // if _igetfield then reqrite to _fast_iaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); + assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); __ cmpl(rbx, Bytecodes::_fast_igetfield); __ movl(bc, Bytecodes::_fast_iaccess_0); __ jccb(Assembler::equal, rewrite); // if _agetfield then reqrite to _fast_aaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); + assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); __ cmpl(rbx, Bytecodes::_fast_agetfield); __ movl(bc, Bytecodes::_fast_aaccess_0); __ jccb(Assembler::equal, rewrite); // if _fgetfield then reqrite to _fast_faccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); + assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); __ cmpl(rbx, Bytecodes::_fast_fgetfield); __ movl(bc, Bytecodes::_fast_faccess_0); __ jccb(Assembler::equal, rewrite); // else rewrite to _fast_aload0 - assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); + assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition"); __ movl(bc, Bytecodes::_fast_aload_0); // rewrite @@ -835,22 +893,26 @@ void TemplateTable::istore() { __ movl(iaddress(rbx), rax); } + void TemplateTable::lstore() { transition(ltos, vtos); locals_index(rbx); - __ movq(laddress(rbx), rax); + __ movptr(laddress(rbx), rax); + NOT_LP64(__ movptr(haddress(rbx), rdx)); } void TemplateTable::fstore() { transition(ftos, vtos); locals_index(rbx); - __ movflt(faddress(rbx), xmm0); + LP64_ONLY(__ movflt(faddress(rbx), xmm0)); + NOT_LP64(__ fstp_s(faddress(rbx))); } void TemplateTable::dstore() { transition(dtos, vtos); locals_index(rbx); - __ movdbl(daddress(rbx), xmm0); + LP64_ONLY(__ movdbl(daddress(rbx), xmm0)); + NOT_LP64(__ fstp_d(daddress(rbx))); } void TemplateTable::astore() { @@ -869,23 +931,33 @@ void TemplateTable::wide_istore() { void TemplateTable::wide_lstore() { transition(vtos, vtos); - __ pop_l(); + NOT_LP64(__ pop_l(rax, rdx)); + LP64_ONLY(__ pop_l()); locals_index_wide(rbx); - __ movq(laddress(rbx), rax); + __ movptr(laddress(rbx), rax); + NOT_LP64(__ movl(haddress(rbx), rdx)); } void TemplateTable::wide_fstore() { +#ifdef _LP64 transition(vtos, vtos); __ pop_f(); locals_index_wide(rbx); __ movflt(faddress(rbx), xmm0); +#else + wide_istore(); +#endif } void TemplateTable::wide_dstore() { +#ifdef _LP64 transition(vtos, vtos); __ pop_d(); locals_index_wide(rbx); __ movdbl(daddress(rbx), xmm0); +#else + wide_lstore(); +#endif } void TemplateTable::wide_astore() { @@ -898,11 +970,10 @@ void TemplateTable::wide_astore() { void TemplateTable::iastore() { transition(itos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index + // rax: value + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in ebx + index_check(rdx, rbx); // prefer index in rbx __ movl(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), @@ -912,43 +983,42 @@ void TemplateTable::iastore() { void TemplateTable::lastore() { transition(ltos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); - // rax: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movq(Address(rdx, rbx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_LONG)), - rax); + // rax,: low(value) + // rcx: array + // rdx: high(value) + index_check(rcx, rbx); // prefer index in rbx, + // rbx,: index + __ movptr(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize), rax); + NOT_LP64(__ movl(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize), rdx)); } + void TemplateTable::fastore() { transition(ftos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); // xmm0: value - // ebx: index + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movflt(Address(rdx, rbx, + index_check(rdx, rbx); // prefer index in rbx + LP64_ONLY(__ movflt(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)), - xmm0); + xmm0)); + NOT_LP64(__ fstp_s(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); } void TemplateTable::dastore() { transition(dtos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); // xmm0: value - // ebx: index + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movdbl(Address(rdx, rbx, + index_check(rdx, rbx); // prefer index in rbx + LP64_ONLY(__ movdbl(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), - xmm0); + xmm0)); + NOT_LP64(__ fstp_d(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); } void TemplateTable::aastore() { @@ -960,11 +1030,10 @@ void TemplateTable::aastore() { __ movptr(rdx, at_tos_p2()); // array Address element_address(rdx, rcx, - UseCompressedOops? Address::times_4 : Address::times_8, + UseCompressedOops? Address::times_4 : Address::times_ptr, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - index_check(rdx, rcx); // kills rbx - // do array store check - check for NULL value first + index_check_without_pop(rdx, rcx); // kills rbx __ testptr(rax, rax); __ jcc(Assembler::zero, is_null); @@ -1009,11 +1078,10 @@ void TemplateTable::aastore() { void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index + // rax: value + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in ebx + index_check(rdx, rbx); // prefer index in rbx __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -1023,17 +1091,17 @@ void TemplateTable::bastore() { void TemplateTable::castore() { transition(itos, vtos); __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index + // rax: value + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in ebx + index_check(rdx, rbx); // prefer index in rbx __ movw(Address(rdx, rbx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), rax); } + void TemplateTable::sastore() { castore(); } @@ -1045,19 +1113,23 @@ void TemplateTable::istore(int n) { void TemplateTable::lstore(int n) { transition(ltos, vtos); - __ movq(laddress(n), rax); + __ movptr(laddress(n), rax); + NOT_LP64(__ movptr(haddress(n), rdx)); } void TemplateTable::fstore(int n) { transition(ftos, vtos); - __ movflt(faddress(n), xmm0); + LP64_ONLY(__ movflt(faddress(n), xmm0)); + NOT_LP64(__ fstp_s(faddress(n))); } void TemplateTable::dstore(int n) { transition(dtos, vtos); - __ movdbl(daddress(n), xmm0); + LP64_ONLY(__ movdbl(daddress(n), xmm0)); + NOT_LP64(__ fstp_d(daddress(n))); } + void TemplateTable::astore(int n) { transition(vtos, vtos); __ pop_ptr(rax); @@ -1074,6 +1146,7 @@ void TemplateTable::pop2() { __ addptr(rsp, 2 * Interpreter::stackElementSize); } + void TemplateTable::dup() { transition(vtos, vtos); __ load_ptr(0, rax); @@ -1117,6 +1190,7 @@ void TemplateTable::dup2() { // stack: ..., a, b, a, b } + void TemplateTable::dup2_x1() { transition(vtos, vtos); // stack: ..., a, b, c @@ -1181,6 +1255,7 @@ void TemplateTable::iop2(Operation op) { void TemplateTable::lop2(Operation op) { transition(ltos, ltos); +#ifdef _LP64 switch (op) { case add : __ pop_l(rdx); __ addptr(rax, rdx); break; case sub : __ mov(rdx, rax); __ pop_l(rax); __ subptr(rax, rdx); break; @@ -1189,13 +1264,25 @@ void TemplateTable::lop2(Operation op) { case _xor : __ pop_l(rdx); __ xorptr(rax, rdx); break; default : ShouldNotReachHere(); } +#else + __ pop_l(rbx, rcx); + switch (op) { + case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; + case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); + __ mov (rax, rbx); __ mov (rdx, rcx); break; + case _and : __ andl(rax, rbx); __ andl(rdx, rcx); break; + case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; + case _xor : __ xorl(rax, rbx); __ xorl(rdx, rcx); break; + default : ShouldNotReachHere(); + } +#endif } void TemplateTable::idiv() { transition(itos, itos); __ movl(rcx, rax); __ pop_i(rax); - // Note: could xor eax and ecx and compare with (-1 ^ min_int). If + // Note: could xor rax and ecx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. // (see also JVM spec., p.243 & p.271) @@ -1206,7 +1293,7 @@ void TemplateTable::irem() { transition(itos, itos); __ movl(rcx, rax); __ pop_i(rax); - // Note: could xor eax and ecx and compare with (-1 ^ min_int). If + // Note: could xor rax and ecx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. // (see also JVM spec., p.243 & p.271) @@ -1216,12 +1303,21 @@ void TemplateTable::irem() { void TemplateTable::lmul() { transition(ltos, ltos); +#ifdef _LP64 __ pop_l(rdx); __ imulq(rax, rdx); +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + __ lmul(2 * wordSize, 0); + __ addptr(rsp, 4 * wordSize); // take off temporaries +#endif } void TemplateTable::ldiv() { transition(ltos, ltos); +#ifdef _LP64 __ mov(rcx, rax); __ pop_l(rax); // generate explicit div0 check @@ -1233,10 +1329,22 @@ void TemplateTable::ldiv() { // needed), which may speed up this implementation for the common case. // (see also JVM spec., p.243 & p.271) __ corrected_idivq(rcx); // kills rbx +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + // check if y = 0 + __ orl(rax, rdx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); + __ addptr(rsp, 4 * wordSize); // take off temporaries +#endif } void TemplateTable::lrem() { transition(ltos, ltos); +#ifdef _LP64 __ mov(rcx, rax); __ pop_l(rax); __ testq(rcx, rcx); @@ -1248,31 +1356,61 @@ void TemplateTable::lrem() { // (see also JVM spec., p.243 & p.271) __ corrected_idivq(rcx); // kills rbx __ mov(rax, rdx); +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + // check if y = 0 + __ orl(rax, rdx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); + __ addptr(rsp, 4 * wordSize); +#endif } void TemplateTable::lshl() { transition(itos, ltos); __ movl(rcx, rax); // get shift count + #ifdef _LP64 __ pop_l(rax); // get shift value __ shlq(rax); +#else + __ pop_l(rax, rdx); // get shift value + __ lshl(rdx, rax); +#endif } void TemplateTable::lshr() { +#ifdef _LP64 transition(itos, ltos); __ movl(rcx, rax); // get shift count __ pop_l(rax); // get shift value __ sarq(rax); +#else + transition(itos, ltos); + __ mov(rcx, rax); // get shift count + __ pop_l(rax, rdx); // get shift value + __ lshr(rdx, rax, true); +#endif } void TemplateTable::lushr() { transition(itos, ltos); +#ifdef _LP64 __ movl(rcx, rax); // get shift count __ pop_l(rax); // get shift value __ shrq(rax); +#else + __ mov(rcx, rax); // get shift count + __ pop_l(rax, rdx); // get shift value + __ lshr(rdx, rax); +#endif } void TemplateTable::fop2(Operation op) { transition(ftos, ftos); +#ifdef _LP64 switch (op) { case add: __ addss(xmm0, at_rsp()); @@ -1301,10 +1439,23 @@ void TemplateTable::fop2(Operation op) { ShouldNotReachHere(); break; } +#else + switch (op) { + case add: __ fadd_s (at_rsp()); break; + case sub: __ fsubr_s(at_rsp()); break; + case mul: __ fmul_s (at_rsp()); break; + case div: __ fdivr_s(at_rsp()); break; + case rem: __ fld_s (at_rsp()); __ fremr(rax); break; + default : ShouldNotReachHere(); + } + __ f2ieee(); + __ pop(rax); // pop float thing off +#endif } void TemplateTable::dop2(Operation op) { transition(dtos, dtos); +#ifdef _LP64 switch (op) { case add: __ addsd(xmm0, at_rsp()); @@ -1333,6 +1484,56 @@ void TemplateTable::dop2(Operation op) { ShouldNotReachHere(); break; } +#else + switch (op) { + case add: __ fadd_d (at_rsp()); break; + case sub: __ fsubr_d(at_rsp()); break; + case mul: { + Label L_strict; + Label L_join; + const Address access_flags (rcx, Method::access_flags_offset()); + __ get_method(rcx); + __ movl(rcx, access_flags); + __ testl(rcx, JVM_ACC_STRICT); + __ jccb(Assembler::notZero, L_strict); + __ fmul_d (at_rsp()); + __ jmpb(L_join); + __ bind(L_strict); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); + __ fmulp(); + __ fmul_d (at_rsp()); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); + __ fmulp(); + __ bind(L_join); + break; + } + case div: { + Label L_strict; + Label L_join; + const Address access_flags (rcx, Method::access_flags_offset()); + __ get_method(rcx); + __ movl(rcx, access_flags); + __ testl(rcx, JVM_ACC_STRICT); + __ jccb(Assembler::notZero, L_strict); + __ fdivr_d(at_rsp()); + __ jmp(L_join); + __ bind(L_strict); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); + __ fmul_d (at_rsp()); + __ fdivrp(); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); + __ fmulp(); + __ bind(L_join); + break; + } + case rem: __ fld_d (at_rsp()); __ fremr(rax); break; + default : ShouldNotReachHere(); + } + __ d2ieee(); + // Pop double precision number from rsp. + __ pop(rax); + __ pop(rdx); +#endif } void TemplateTable::ineg() { @@ -1342,9 +1543,11 @@ void TemplateTable::ineg() { void TemplateTable::lneg() { transition(ltos, ltos); - __ negq(rax); + LP64_ONLY(__ negq(rax)); + NOT_LP64(__ lneg(rdx, rax)); } +#ifdef _LP64 // Note: 'double' and 'long long' have 32-bits alignment on x86. static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { // Use the expression (adr)&(~0xF) to provide 128-bits aligned address @@ -1359,17 +1562,26 @@ static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { // Buffer for 128-bits masks used by SSE instructions. static jlong float_signflip_pool[2*2]; static jlong double_signflip_pool[2*2]; +#endif void TemplateTable::fneg() { transition(ftos, ftos); +#ifdef _LP64 static jlong *float_signflip = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000); __ xorps(xmm0, ExternalAddress((address) float_signflip)); +#else + __ fchs(); +#endif } void TemplateTable::dneg() { transition(dtos, dtos); +#ifdef _LP64 static jlong *double_signflip = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000); __ xorpd(xmm0, ExternalAddress((address) double_signflip)); +#else + __ fchs(); +#endif } void TemplateTable::iinc() { @@ -1391,6 +1603,7 @@ void TemplateTable::wide_iinc() { } void TemplateTable::convert() { +#ifdef _LP64 // Checking #ifdef ASSERT { @@ -1518,10 +1731,143 @@ void TemplateTable::convert() { default: ShouldNotReachHere(); } +#else + // Checking +#ifdef ASSERT + { TosState tos_in = ilgl; + TosState tos_out = ilgl; + switch (bytecode()) { + case Bytecodes::_i2l: // fall through + case Bytecodes::_i2f: // fall through + case Bytecodes::_i2d: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_in = itos; break; + case Bytecodes::_l2i: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_l2d: tos_in = ltos; break; + case Bytecodes::_f2i: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_f2d: tos_in = ftos; break; + case Bytecodes::_d2i: // fall through + case Bytecodes::_d2l: // fall through + case Bytecodes::_d2f: tos_in = dtos; break; + default : ShouldNotReachHere(); + } + switch (bytecode()) { + case Bytecodes::_l2i: // fall through + case Bytecodes::_f2i: // fall through + case Bytecodes::_d2i: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_out = itos; break; + case Bytecodes::_i2l: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_d2l: tos_out = ltos; break; + case Bytecodes::_i2f: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_d2f: tos_out = ftos; break; + case Bytecodes::_i2d: // fall through + case Bytecodes::_l2d: // fall through + case Bytecodes::_f2d: tos_out = dtos; break; + default : ShouldNotReachHere(); + } + transition(tos_in, tos_out); + } +#endif // ASSERT + + // Conversion + // (Note: use push(rcx)/pop(rcx) for 1/2-word stack-ptr manipulation) + switch (bytecode()) { + case Bytecodes::_i2l: + __ extend_sign(rdx, rax); + break; + case Bytecodes::_i2f: + __ push(rax); // store int on tos + __ fild_s(at_rsp()); // load int to ST0 + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + break; + case Bytecodes::_i2d: + __ push(rax); // add one slot for d2ieee() + __ push(rax); // store int on tos + __ fild_s(at_rsp()); // load int to ST0 + __ d2ieee(); // truncate to double size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_i2b: + __ shll(rax, 24); // truncate upper 24 bits + __ sarl(rax, 24); // and sign-extend byte + LP64_ONLY(__ movsbl(rax, rax)); + break; + case Bytecodes::_i2c: + __ andl(rax, 0xFFFF); // truncate upper 16 bits + LP64_ONLY(__ movzwl(rax, rax)); + break; + case Bytecodes::_i2s: + __ shll(rax, 16); // truncate upper 16 bits + __ sarl(rax, 16); // and sign-extend short + LP64_ONLY(__ movswl(rax, rax)); + break; + case Bytecodes::_l2i: + /* nothing to do */ + break; + case Bytecodes::_l2f: + __ push(rdx); // store long on tos + __ push(rax); + __ fild_d(at_rsp()); // load long to ST0 + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_l2d: + __ push(rdx); // store long on tos + __ push(rax); + __ fild_d(at_rsp()); // load long to ST0 + __ d2ieee(); // truncate to double size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_f2i: + __ push(rcx); // reserve space for argument + __ fstp_s(at_rsp()); // pass float argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); + break; + case Bytecodes::_f2l: + __ push(rcx); // reserve space for argument + __ fstp_s(at_rsp()); // pass float argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); + break; + case Bytecodes::_f2d: + /* nothing to do */ + break; + case Bytecodes::_d2i: + __ push(rcx); // reserve space for argument + __ push(rcx); + __ fstp_d(at_rsp()); // pass double argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 2); + break; + case Bytecodes::_d2l: + __ push(rcx); // reserve space for argument + __ push(rcx); + __ fstp_d(at_rsp()); // pass double argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 2); + break; + case Bytecodes::_d2f: + __ push(rcx); // reserve space for f2ieee() + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + break; + default : + ShouldNotReachHere(); + } +#endif } void TemplateTable::lcmp() { transition(ltos, itos); +#ifdef _LP64 Label done; __ pop_l(rdx); __ cmpq(rdx, rax); @@ -1530,9 +1876,17 @@ void TemplateTable::lcmp() { __ setb(Assembler::notEqual, rax); __ movzbl(rax, rax); __ bind(done); +#else + + // y = rdx:rax + __ pop_l(rbx, rcx); // get x = rcx:rbx + __ lcmp2int(rcx, rbx, rdx, rax);// rcx := cmp(x, y) + __ mov(rax, rcx); +#endif } void TemplateTable::float_cmp(bool is_float, int unordered_result) { +#ifdef _LP64 Label done; if (is_float) { // XXX get rid of pop here, use ... reg, mem32 @@ -1558,6 +1912,16 @@ void TemplateTable::float_cmp(bool is_float, int unordered_result) { __ decrementl(rax); } __ bind(done); +#else + if (is_float) { + __ fld_s(at_rsp()); + } else { + __ fld_d(at_rsp()); + __ pop(rdx); + } + __ pop(rcx); + __ fcmp2int(rax, unordered_result < 0); +#endif } void TemplateTable::branch(bool is_jsr, bool is_wide) { @@ -1581,21 +1945,21 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { if (!is_wide) { __ sarl(rdx, 16); } - __ movl2ptr(rdx, rdx); + LP64_ONLY(__ movl2ptr(rdx, rdx)); // Handle all the JSR stuff here, then exit. // It's much shorter and cleaner than intermingling with the non-JSR // normal-branch stuff occurring below. if (is_jsr) { // Pre-load the next target bytecode into rbx - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0)); + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1, 0)); // compute return address as bci in rax __ lea(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(ConstMethod::codes_offset()))); __ subptr(rax, Address(rcx, Method::const_offset())); // Adjust the bcp in r13 by the displacement in rdx - __ addptr(r13, rdx); + __ addptr(rbcp, rdx); // jsr returns atos that is not an oop __ push_i(rax); __ dispatch_only(vtos); @@ -1605,7 +1969,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // Normal (non-jsr) branch handling // Adjust the bcp in r13 by the displacement in rdx - __ addptr(r13, rdx); + __ addptr(rbcp, rdx); assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters"); @@ -1615,7 +1979,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { if (UseLoopCounter) { // increment backedge counter for backward branches // rax: MDO - // ebx: MDO bumped taken-count + // rbx: MDO bumped taken-count // rcx: method // rdx: target offset // r13: target bcp @@ -1657,7 +2021,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ bind(no_mdo); // Increment backedge counter in MethodCounters* __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); + const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, rax, false, Assembler::zero, &backedge_counter_overflow); } else { // not TieredCompilation @@ -1681,7 +2045,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ test_method_data_pointer(rax, profile_method); if (UseOnStackReplacement) { - // check for overflow against ebx which is the MDO taken count + // check for overflow against rbx which is the MDO taken count __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); __ jcc(Assembler::below, dispatch); @@ -1698,7 +2062,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { } } else { if (UseOnStackReplacement) { - // check for overflow against eax, which is the sum of the + // check for overflow against rax, which is the sum of the // counters __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); __ jcc(Assembler::aboveEqual, backedge_counter_overflow); @@ -1710,11 +2074,11 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { } // Pre-load the next target bytecode into rbx - __ load_unsigned_byte(rbx, Address(r13, 0)); + __ load_unsigned_byte(rbx, Address(rbcp, 0)); // continue with the bytecode @ target - // eax: return bci for jsr's, unused otherwise - // ebx: target bytecode + // rax: return bci for jsr's, unused otherwise + // rbx: target bytecode // r13: target bcp __ dispatch_only(vtos); @@ -1723,7 +2087,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // Out-of-line code to allocate method data oop. __ bind(profile_method); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); - __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode + __ load_unsigned_byte(rbx, Address(rbcp, 0)); // restore target bytecode __ set_method_data_pointer_for_bcp(); __ jmp(dispatch); } @@ -1732,16 +2096,16 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // invocation counter overflow __ bind(backedge_counter_overflow); __ negptr(rdx); - __ addptr(rdx, r13); // branch bcp + __ addptr(rdx, rbcp); // branch bcp // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx); - __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode + __ load_unsigned_byte(rbx, Address(rbcp, 0)); // restore target bytecode // rax: osr nmethod (osr ok) or NULL (osr not possible) - // ebx: target bytecode + // rbx: target bytecode // rdx: scratch // r14: locals pointer // r13: bcp @@ -1751,23 +2115,26 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use); __ jcc(Assembler::notEqual, dispatch); - // We have the address of an on stack replacement routine in eax + // We have the address of an on stack replacement routine in rax // We need to prepare to execute the OSR method. First we must // migrate the locals and monitors off of the stack. - __ mov(r13, rax); // save the nmethod + LP64_ONLY(__ mov(r13, rax)); // save the nmethod + NOT_LP64(__ mov(rbx, rax)); // save the nmethod + NOT_LP64(__ get_thread(rcx)); call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); - // eax is OSR buffer, move it to expected parameter location - __ mov(j_rarg0, rax); - + // rax is OSR buffer, move it to expected parameter location + LP64_ONLY(__ mov(j_rarg0, rax)); + NOT_LP64(__ mov(rcx, rax)); // We use j_rarg definitions here so that registers don't conflict as parameter // registers change across platforms as we are in the midst of a calling // sequence to the OSR nmethod and we don't want collision. These are NOT parameters. - const Register retaddr = j_rarg2; - const Register sender_sp = j_rarg1; + const Register retaddr = LP64_ONLY(j_rarg2) NOT_LP64(rdi); + const Register sender_sp = LP64_ONLY(j_rarg1) NOT_LP64(rdx); + // pop the interpreter frame __ movptr(sender_sp, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp @@ -1784,12 +2151,12 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ push(retaddr); // and begin the OSR nmethod - __ jmp(Address(r13, nmethod::osr_entry_point_offset())); + LP64_ONLY(__ jmp(Address(r13, nmethod::osr_entry_point_offset()))); + NOT_LP64(__ jmp(Address(rbx, nmethod::osr_entry_point_offset()))); } } } - void TemplateTable::if_0cmp(Condition cc) { transition(itos, vtos); // assume branch is more often taken than not (loops use backward branches) @@ -1839,11 +2206,12 @@ void TemplateTable::if_acmp(Condition cc) { void TemplateTable::ret() { transition(vtos, vtos); locals_index(rbx); - __ movslq(rbx, iaddress(rbx)); // get return bci, compute return bcp + LP64_ONLY(__ movslq(rbx, iaddress(rbx))); // get return bci, compute return bcp + NOT_LP64(__ movptr(rbx, iaddress(rbx))); __ profile_ret(rbx, rcx); __ get_method(rax); - __ movptr(r13, Address(rax, Method::const_offset())); - __ lea(r13, Address(r13, rbx, Address::times_1, + __ movptr(rbcp, Address(rax, Method::const_offset())); + __ lea(rbcp, Address(rbcp, rbx, Address::times_1, ConstMethod::codes_offset())); __ dispatch_next(vtos); } @@ -1854,15 +2222,16 @@ void TemplateTable::wide_ret() { __ movptr(rbx, aaddress(rbx)); // get return bci, compute return bcp __ profile_ret(rbx, rcx); __ get_method(rax); - __ movptr(r13, Address(rax, Method::const_offset())); - __ lea(r13, Address(r13, rbx, Address::times_1, ConstMethod::codes_offset())); + __ movptr(rbcp, Address(rax, Method::const_offset())); + __ lea(rbcp, Address(rbcp, rbx, Address::times_1, ConstMethod::codes_offset())); __ dispatch_next(vtos); } void TemplateTable::tableswitch() { Label default_case, continue_execution; transition(itos, vtos); - // align r13 + + // align r13/rsi __ lea(rbx, at_bcp(BytesPerInt)); __ andptr(rbx, -BytesPerInt); // load lo & hi @@ -1882,9 +2251,9 @@ void TemplateTable::tableswitch() { // continue execution __ bind(continue_execution); __ bswapl(rdx); - __ movl2ptr(rdx, rdx); - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1)); - __ addptr(r13, rdx); + LP64_ONLY(__ movl2ptr(rdx, rdx)); + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1)); + __ addptr(rbcp, rdx); __ dispatch_only(vtos); // handle default __ bind(default_case); @@ -1931,8 +2300,8 @@ void TemplateTable::fast_linearswitch() { __ bind(continue_execution); __ bswapl(rdx); __ movl2ptr(rdx, rdx); - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1)); - __ addptr(r13, rdx); + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1)); + __ addptr(rbcp, rdx); __ dispatch_only(vtos); } @@ -1972,6 +2341,8 @@ void TemplateTable::fast_binaryswitch() { const Register temp = rsi; // Find array start + NOT_LP64(__ save_bcp()); + __ lea(array, at_bcp(3 * BytesPerInt)); // btw: should be able to // get rid of this // instruction (change @@ -2006,9 +2377,9 @@ void TemplateTable::fast_binaryswitch() { __ bswapl(temp); __ cmpl(key, temp); // j = h if (key < array[h].fast_match()) - __ cmovl(Assembler::less, j, h); + __ cmov32(Assembler::less, j, h); // i = h if (key >= array[h].fast_match()) - __ cmovl(Assembler::greaterEqual, i, h); + __ cmov32(Assembler::greaterEqual, i, h); // while (i+1 < j) __ bind(entry); __ leal(h, Address(i, 1)); // i+1 @@ -2028,9 +2399,13 @@ void TemplateTable::fast_binaryswitch() { __ movl(j , Address(array, i, Address::times_8, BytesPerInt)); __ profile_switch_case(i, key, array); __ bswapl(j); - __ movl2ptr(j, j); - __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1)); - __ addptr(r13, j); + LP64_ONLY(__ movslq(j, j)); + + NOT_LP64(__ restore_bcp()); + NOT_LP64(__ restore_locals()); // restore rdi + + __ load_unsigned_byte(rbx, Address(rbcp, j, Address::times_1)); + __ addptr(rbcp, j); __ dispatch_only(vtos); // default case -> j = default offset @@ -2038,34 +2413,40 @@ void TemplateTable::fast_binaryswitch() { __ profile_switch_default(i); __ movl(j, Address(array, -2 * BytesPerInt)); __ bswapl(j); - __ movl2ptr(j, j); - __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1)); - __ addptr(r13, j); + LP64_ONLY(__ movslq(j, j)); + + NOT_LP64(__ restore_bcp()); + NOT_LP64(__ restore_locals()); + + __ load_unsigned_byte(rbx, Address(rbcp, j, Address::times_1)); + __ addptr(rbcp, j); __ dispatch_only(vtos); } - void TemplateTable::_return(TosState state) { transition(state, state); + + Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); + assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { assert(state == vtos, "only valid state"); - __ movptr(c_rarg1, aaddress(0)); - __ load_klass(rdi, c_rarg1); + __ movptr(robj, aaddress(0)); + __ load_klass(rdi, robj); __ movl(rdi, Address(rdi, Klass::access_flags_offset())); __ testl(rdi, JVM_ACC_HAS_FINALIZER); Label skip_register_finalizer; __ jcc(Assembler::zero, skip_register_finalizer); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), c_rarg1); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), robj); __ bind(skip_register_finalizer); } - __ remove_activation(state, r13); - __ jmp(r13); + __ remove_activation(state, rbcp); + __ jmp(rbcp); } // ---------------------------------------------------------------------------- @@ -2096,12 +2477,11 @@ void TemplateTable::_return(TosState state) { // volatile-store-volatile-load case. This final case is placed after // volatile-stores although it could just as well go before // volatile-loads. -void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits - order_constraint) { + +void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint ) { // Helper function to insert a is-volatile test and memory barrier - if (os::is_MP()) { // Not needed on single CPU - __ membar(order_constraint); - } + if(!os::is_MP()) return; // Not needed on single CPU + __ membar(order_constraint); } void TemplateTable::resolve_cache_and_index(int byte_no, @@ -2120,31 +2500,22 @@ void TemplateTable::resolve_cache_and_index(int byte_no, // resolve first time through address entry; switch (bytecode()) { - case Bytecodes::_getstatic: - case Bytecodes::_putstatic: - case Bytecodes::_getfield: - case Bytecodes::_putfield: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); - break; - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: - case Bytecodes::_invokestatic: - case Bytecodes::_invokeinterface: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); - break; - case Bytecodes::_invokehandle: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); - break; - case Bytecodes::_invokedynamic: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); - break; - default: - fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); - break; + case Bytecodes::_getstatic : // fall through + case Bytecodes::_putstatic : // fall through + case Bytecodes::_getfield : // fall through + case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; + case Bytecodes::_invokevirtual : // fall through + case Bytecodes::_invokespecial : // fall through + case Bytecodes::_invokestatic : // fall through + case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; + case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break; + case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; + default: + fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); + break; } - __ movl(temp, (int) bytecode()); + __ movl(temp, (int)bytecode()); __ call_VM(noreg, entry, temp); - // Update registers with resolved info __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); __ bind(resolved); @@ -2217,39 +2588,36 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no, __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); } +// The registers cache and index expected to be set before call. // Correct values of the cache and index registers are preserved. -void TemplateTable::jvmti_post_field_access(Register cache, Register index, - bool is_static, bool has_tos) { - // do the JVMTI work here to avoid disturbing the register state below - // We use c_rarg registers here because we want to use the register used in - // the call to the VM +void TemplateTable::jvmti_post_field_access(Register cache, + Register index, + bool is_static, + bool has_tos) { if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we - // take the time to call into the VM. + // Check to see if a field access watch has been set before we take + // the time to call into the VM. Label L1; assert_different_registers(cache, index, rax); __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rax, rax); + __ testl(rax,rax); __ jcc(Assembler::zero, L1); - __ get_cache_and_index_at_bcp(c_rarg2, c_rarg3, 1); - // cache entry pointer - __ addptr(c_rarg2, in_bytes(ConstantPoolCache::base_offset())); - __ shll(c_rarg3, LogBytesPerWord); - __ addptr(c_rarg2, c_rarg3); + __ addptr(cache, in_bytes(ConstantPoolCache::base_offset())); + __ shll(index, LogBytesPerWord); + __ addptr(cache, index); if (is_static) { - __ xorl(c_rarg1, c_rarg1); // NULL object reference + __ xorptr(rax, rax); // NULL object reference } else { - __ movptr(c_rarg1, at_tos()); // get object pointer without popping it - __ verify_oop(c_rarg1); + __ pop(atos); // Get the object + __ verify_oop(rax); + __ push(atos); // Restore stack state } - // c_rarg1: object pointer or NULL - // c_rarg2: cache entry pointer - // c_rarg3: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_access), - c_rarg1, c_rarg2, c_rarg3); + // rax,: object pointer or NULL + // cache: cache entry pointer + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), + rax, cache); __ get_cache_and_index_at_bcp(cache, index, 1); __ bind(L1); } @@ -2266,30 +2634,28 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { const Register cache = rcx; const Register index = rdx; - const Register obj = c_rarg3; + const Register obj = LP64_ONLY(c_rarg3) NOT_LP64(rcx); const Register off = rbx; const Register flags = rax; - const Register bc = c_rarg3; // uses same reg as obj, so don't mix them + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // uses same reg as obj, so don't mix them resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); jvmti_post_field_access(cache, index, is_static, false); load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - if (!is_static) { - // obj is on the stack - pop_and_check_object(obj); - } + if (!is_static) pop_and_check_object(obj); - const Address field(obj, off, Address::times_1); + const Address field(obj, off, Address::times_1, 0*wordSize); + NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize)); - Label Done, notByte, notInt, notShort, notChar, - notLong, notFloat, notObj, notDouble; + Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); // Make sure we don't need to mask edx after the above shift assert(btos == 0, "change code, btos != 0"); __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); + __ jcc(Assembler::notZero, notByte); // btos __ load_signed_byte(rax, field); @@ -2351,19 +2717,31 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { __ cmpl(flags, ltos); __ jcc(Assembler::notEqual, notLong); // ltos + +#ifndef _LP64 + // Generate code as if volatile. There just aren't enough registers to + // save that information and this code is faster than the test. + __ fild_d(field); // Must load atomically + __ subptr(rsp,2*wordSize); // Make space for store + __ fistp_d(Address(rsp,0)); + __ pop(rax); + __ pop(rdx); +#else __ movq(rax, field); +#endif + __ push(ltos); // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx); - } + LP64_ONLY(if (!is_static) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx)); __ jmp(Done); __ bind(notLong); __ cmpl(flags, ftos); __ jcc(Assembler::notEqual, notFloat); // ftos - __ movflt(xmm0, field); + + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); __ push(ftos); // Rewrite bytecode to be faster if (!is_static) { @@ -2377,7 +2755,8 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { __ jcc(Assembler::notEqual, notDouble); #endif // dtos - __ movdbl(xmm0, field); + LP64_ONLY(__ movdbl(xmm0, field)); + NOT_LP64(__ fld_d(field)); __ push(dtos); // Rewrite bytecode to be faster if (!is_static) { @@ -2386,6 +2765,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { #ifdef ASSERT __ jmp(Done); + __ bind(notDouble); __ stop("Bad state"); #endif @@ -2396,7 +2776,6 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { // Assembler::LoadStore)); } - void TemplateTable::getfield(int byte_no) { getfield_or_static(byte_no, false); } @@ -2405,10 +2784,15 @@ void TemplateTable::getstatic(int byte_no) { getfield_or_static(byte_no, true); } + // The registers cache and index expected to be set before call. // The function may destroy various registers, just not the cache and index registers. void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { - transition(vtos, vtos); + + const Register robj = LP64_ONLY(c_rarg2) NOT_LP64(rax); + const Register RBX = LP64_ONLY(c_rarg1) NOT_LP64(rbx); + const Register RCX = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + const Register RDX = LP64_ONLY(rscratch1) NOT_LP64(rdx); ByteSize cp_base_offset = ConstantPoolCache::base_offset(); @@ -2421,23 +2805,31 @@ void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is __ testl(rax, rax); __ jcc(Assembler::zero, L1); - __ get_cache_and_index_at_bcp(c_rarg2, rscratch1, 1); + __ get_cache_and_index_at_bcp(robj, RDX, 1); + if (is_static) { // Life is simple. Null out the object pointer. - __ xorl(c_rarg1, c_rarg1); + __ xorl(RBX, RBX); + } else { // Life is harder. The stack holds the value on top, followed by // the object. We don't know the size of the value, though; it // could be one or two words depending on its type. As a result, // we must find the type to determine where the object is. - __ movl(c_rarg3, Address(c_rarg2, rscratch1, - Address::times_8, +#ifndef _LP64 + Label two_word, valsize_known; +#endif + __ movl(RCX, Address(robj, RDX, + Address::times_ptr, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()))); - __ shrl(c_rarg3, ConstantPoolCacheEntry::tos_state_shift); + NOT_LP64(__ mov(rbx, rsp)); + __ shrl(RCX, ConstantPoolCacheEntry::tos_state_shift); + // Make sure we don't need to mask rcx after the above shift ConstantPoolCacheEntry::verify_tos_state_shift(); +#ifdef _LP64 __ movptr(c_rarg1, at_tos_p1()); // initially assume a one word jvalue __ cmpl(c_rarg3, ltos); __ cmovptr(Assembler::equal, @@ -2445,20 +2837,35 @@ void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is __ cmpl(c_rarg3, dtos); __ cmovptr(Assembler::equal, c_rarg1, at_tos_p2()); // dtos (two word jvalue) +#else + __ cmpl(rcx, ltos); + __ jccb(Assembler::equal, two_word); + __ cmpl(rcx, dtos); + __ jccb(Assembler::equal, two_word); + __ addptr(rbx, Interpreter::expr_offset_in_bytes(1)); // one word jvalue (not ltos, dtos) + __ jmpb(valsize_known); + + __ bind(two_word); + __ addptr(rbx, Interpreter::expr_offset_in_bytes(2)); // two words jvalue + + __ bind(valsize_known); + // setup object pointer + __ movptr(rbx, Address(rbx, 0)); +#endif } // cache entry pointer - __ addptr(c_rarg2, in_bytes(cp_base_offset)); - __ shll(rscratch1, LogBytesPerWord); - __ addptr(c_rarg2, rscratch1); + __ addptr(robj, in_bytes(cp_base_offset)); + __ shll(RDX, LogBytesPerWord); + __ addptr(robj, RDX); // object (tos) - __ mov(c_rarg3, rsp); + __ mov(RCX, rsp); // c_rarg1: object pointer set up above (NULL if static) // c_rarg2: cache entry pointer // c_rarg3: jvalue object on the stack __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), - c_rarg1, c_rarg2, c_rarg3); + RBX, robj, RCX); __ get_cache_and_index_at_bcp(cache, index, 1); __ bind(L1); } @@ -2472,7 +2879,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { const Register obj = rcx; const Register off = rbx; const Register flags = rax; - const Register bc = c_rarg3; + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); jvmti_post_field_mod(cache, index, is_static); @@ -2487,8 +2894,9 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); __ andl(rdx, 0x1); - // field address - const Address field(obj, off, Address::times_1); + // field addresses + const Address field(obj, off, Address::times_1, 0*wordSize); + NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);) Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; @@ -2576,6 +2984,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { __ jcc(Assembler::notEqual, notLong); // ltos +#ifdef _LP64 { __ pop(ltos); if (!is_static) pop_and_check_object(obj); @@ -2585,6 +2994,37 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { } __ jmp(Done); } +#else + { + Label notVolatileLong; + __ testl(rdx, rdx); + __ jcc(Assembler::zero, notVolatileLong); + + __ pop(ltos); // overwrites rdx, do this after testing volatile. + if (!is_static) pop_and_check_object(obj); + + // Replace with real volatile test + __ push(rdx); + __ push(rax); // Must update atomically with FIST + __ fild_d(Address(rsp,0)); // So load into FPU register + __ fistp_d(field); // and put into memory atomically + __ addptr(rsp, 2*wordSize); + // volatile_barrier(); + volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | + Assembler::StoreStore)); + // Don't rewrite volatile version + __ jmp(notVolatile); + + __ bind(notVolatileLong); + + __ pop(ltos); // overwrites rdx + if (!is_static) pop_and_check_object(obj); + __ movptr(hi, rdx); + __ movptr(field, rax); + // Don't rewrite to _fast_lputfield for potential volatile case. + __ jmp(notVolatile); + } +#endif // _LP64 __ bind(notLong); __ cmpl(flags, ftos); @@ -2594,7 +3034,8 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { { __ pop(ftos); if (!is_static) pop_and_check_object(obj); - __ movflt(field, xmm0); + NOT_LP64( __ fstp_s(field);) + LP64_ONLY( __ movflt(field, xmm0);) if (!is_static) { patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no); } @@ -2611,7 +3052,8 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { { __ pop(dtos); if (!is_static) pop_and_check_object(obj); - __ movdbl(field, xmm0); + NOT_LP64( __ fstp_d(field);) + LP64_ONLY( __ movdbl(field, xmm0);) if (!is_static) { patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no); } @@ -2643,12 +3085,15 @@ void TemplateTable::putstatic(int byte_no) { } void TemplateTable::jvmti_post_fast_field_mod() { + + const Register scratch = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + if (JvmtiExport::can_post_field_modification()) { // Check to see if a field modification watch has been set before // we take the time to call into the VM. Label L2; - __ mov32(c_rarg3, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(c_rarg3, c_rarg3); + __ mov32(scratch, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); + __ testl(scratch, scratch); __ jcc(Assembler::zero, L2); __ pop_ptr(rbx); // copy the object pointer from tos __ verify_oop(rbx); @@ -2669,17 +3114,16 @@ void TemplateTable::jvmti_post_fast_field_mod() { default: ShouldNotReachHere(); } - __ mov(c_rarg3, rsp); // points to jvalue on the stack + __ mov(scratch, rsp); // points to jvalue on the stack // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1); + LP64_ONLY(__ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1)); + NOT_LP64(__ get_cache_entry_pointer_at_bcp(rax, rdx, 1)); __ verify_oop(rbx); // rbx: object pointer copied above // c_rarg2: cache entry pointer // c_rarg3: jvalue object on the stack - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_modification), - rbx, c_rarg2, c_rarg3); + LP64_ONLY(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, c_rarg2, c_rarg3)); + NOT_LP64(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx)); switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; @@ -2705,13 +3149,13 @@ void TemplateTable::fast_storefield(TosState state) { // access constant pool cache __ get_cache_and_index_at_bcp(rcx, rbx, 1); - // test for volatile with rdx - __ movl(rdx, Address(rcx, rbx, Address::times_8, + // test for volatile with rdx but rdx is tos register for lputfield. + __ movl(rdx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + ConstantPoolCacheEntry::flags_offset()))); // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, rbx, Address::times_8, + __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); // [jk] not needed currently @@ -2734,7 +3178,11 @@ void TemplateTable::fast_storefield(TosState state) { do_oop_store(_masm, field, rax, _bs->kind(), false); break; case Bytecodes::_fast_lputfield: - __ movq(field, rax); +#ifdef _LP64 + __ movq(field, rax); +#else + __ stop("should not be rewritten"); +#endif break; case Bytecodes::_fast_iputfield: __ movl(field, rax); @@ -2748,10 +3196,12 @@ void TemplateTable::fast_storefield(TosState state) { __ movw(field, rax); break; case Bytecodes::_fast_fputfield: - __ movflt(field, xmm0); + NOT_LP64( __ fstp_s(field); ) + LP64_ONLY( __ movflt(field, xmm0);) break; case Bytecodes::_fast_dputfield: - __ movdbl(field, xmm0); + NOT_LP64( __ fstp_d(field); ) + LP64_ONLY( __ movdbl(field, xmm0);) break; default: ShouldNotReachHere(); @@ -2765,7 +3215,6 @@ void TemplateTable::fast_storefield(TosState state) { __ bind(notVolatile); } - void TemplateTable::fast_accessfield(TosState state) { transition(atos, state); @@ -2778,16 +3227,15 @@ void TemplateTable::fast_accessfield(TosState state) { __ testl(rcx, rcx); __ jcc(Assembler::zero, L1); // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); + LP64_ONLY(__ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1)); + NOT_LP64(__ get_cache_entry_pointer_at_bcp(rcx, rdx, 1)); __ verify_oop(rax); __ push_ptr(rax); // save object pointer before call_VM() clobbers it - __ mov(c_rarg1, rax); + LP64_ONLY(__ mov(c_rarg1, rax)); // c_rarg1: object pointer copied above // c_rarg2: cache entry pointer - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_access), - c_rarg1, c_rarg2); + LP64_ONLY(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), c_rarg1, c_rarg2)); + NOT_LP64(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), rax, rcx)); __ pop_ptr(rax); // restore object pointer __ bind(L1); } @@ -2803,7 +3251,7 @@ void TemplateTable::fast_accessfield(TosState state) { // __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); // __ andl(rdx, 0x1); // } - __ movptr(rbx, Address(rcx, rbx, Address::times_8, + __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); @@ -2819,7 +3267,11 @@ void TemplateTable::fast_accessfield(TosState state) { __ verify_oop(rax); break; case Bytecodes::_fast_lgetfield: - __ movq(rax, field); +#ifdef _LP64 + __ movq(rax, field); +#else + __ stop("should not be rewritten"); +#endif break; case Bytecodes::_fast_igetfield: __ movl(rax, field); @@ -2834,10 +3286,12 @@ void TemplateTable::fast_accessfield(TosState state) { __ load_unsigned_short(rax, field); break; case Bytecodes::_fast_fgetfield: - __ movflt(xmm0, field); + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); break; case Bytecodes::_fast_dgetfield: - __ movdbl(xmm0, field); + LP64_ONLY(__ movdbl(xmm0, field)); + NOT_LP64(__ fld_d(field)); break; default: ShouldNotReachHere(); @@ -2860,23 +3314,25 @@ void TemplateTable::fast_xaccess(TosState state) { // access constant pool cache __ get_cache_and_index_at_bcp(rcx, rdx, 2); __ movptr(rbx, - Address(rcx, rdx, Address::times_8, + Address(rcx, rdx, Address::times_ptr, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); // make sure exception is reported in correct bcp range (getfield is // next instruction) - __ increment(r13); + __ increment(rbcp); __ null_check(rax); + const Address field = Address(rax, rbx, Address::times_1, 0*wordSize); switch (state) { case itos: - __ movl(rax, Address(rax, rbx, Address::times_1)); + __ movl(rax, field); break; case atos: - __ load_heap_oop(rax, Address(rax, rbx, Address::times_1)); + __ load_heap_oop(rax, field); __ verify_oop(rax); break; case ftos: - __ movflt(xmm0, Address(rax, rbx, Address::times_1)); + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); break; default: ShouldNotReachHere(); @@ -2895,11 +3351,9 @@ void TemplateTable::fast_xaccess(TosState state) { // __ bind(notVolatile); // } - __ decrement(r13); + __ decrement(rbcp); } - - //----------------------------------------------------------------------------- // Calls @@ -2968,7 +3422,7 @@ void TemplateTable::prepare_invoke(int byte_no, } if (save_flags) { - __ movl(r13, flags); + __ movl(rbcp, flags); } // compute return type @@ -2979,8 +3433,9 @@ void TemplateTable::prepare_invoke(int byte_no, { const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); ExternalAddress table(table_addr); - __ lea(rscratch1, table); - __ movptr(flags, Address(rscratch1, flags, Address::times_ptr)); + LP64_ONLY(__ lea(rscratch1, table)); + LP64_ONLY(__ movptr(flags, Address(rscratch1, flags, Address::times_ptr))); + NOT_LP64(__ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)))); } // push return address @@ -2989,12 +3444,11 @@ void TemplateTable::prepare_invoke(int byte_no, // Restore flags value from the constant pool cache, and restore rsi // for later null checks. r13 is the bytecode pointer if (save_flags) { - __ movl(flags, r13); + __ movl(flags, rbcp); __ restore_bcp(); } } - void TemplateTable::invokevirtual_helper(Register index, Register recv, Register flags) { @@ -3021,7 +3475,7 @@ void TemplateTable::invokevirtual_helper(Register index, // profile this call __ profile_final_call(rax); - __ profile_arguments_type(rax, method, r13, true); + __ profile_arguments_type(rax, method, rbcp, true); __ jump_from_interpreted(method, rax); @@ -3032,15 +3486,13 @@ void TemplateTable::invokevirtual_helper(Register index, __ load_klass(rax, recv); // profile this call - __ profile_virtual_call(rax, r14, rdx); - + __ profile_virtual_call(rax, rlocals, rdx); // get target Method* & entry point __ lookup_virtual_method(rax, index, method); - __ profile_arguments_type(rdx, method, r13, true); + __ profile_arguments_type(rdx, method, rbcp, true); __ jump_from_interpreted(method, rdx); } - void TemplateTable::invokevirtual(int byte_no) { transition(vtos, vtos); assert(byte_no == f2_byte, "use this argument"); @@ -3056,7 +3508,6 @@ void TemplateTable::invokevirtual(int byte_no) { invokevirtual_helper(rbx, rcx, rdx); } - void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); @@ -3066,27 +3517,28 @@ void TemplateTable::invokespecial(int byte_no) { __ null_check(rcx); // do the call __ profile_call(rax); - __ profile_arguments_type(rax, rbx, r13, false); + __ profile_arguments_type(rax, rbx, rbcp, false); __ jump_from_interpreted(rbx, rax); } - void TemplateTable::invokestatic(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); prepare_invoke(byte_no, rbx); // get f1 Method* // do the call __ profile_call(rax); - __ profile_arguments_type(rax, rbx, r13, false); + __ profile_arguments_type(rax, rbx, rbcp, false); __ jump_from_interpreted(rbx, rax); } + void TemplateTable::fast_invokevfinal(int byte_no) { transition(vtos, vtos); assert(byte_no == f2_byte, "use this argument"); - __ stop("fast_invokevfinal not used on amd64"); + __ stop("fast_invokevfinal not used on x86"); } + void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); @@ -3103,8 +3555,9 @@ void TemplateTable::invokeinterface(int byte_no) { // This code isn't produced by javac, but could be produced by // another compliant java compiler. Label notMethod; - __ movl(r14, rdx); - __ andl(r14, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); + __ movl(rlocals, rdx); + __ andl(rlocals, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); + __ jcc(Assembler::zero, notMethod); invokevirtual_helper(rbx, rcx, rdx); @@ -3116,14 +3569,14 @@ void TemplateTable::invokeinterface(int byte_no) { __ load_klass(rdx, rcx); // profile this call - __ profile_virtual_call(rdx, r13, r14); + __ profile_virtual_call(rdx, rbcp, rlocals); Label no_such_interface, no_such_method; __ lookup_interface_method(// inputs: rec. class, interface, itable index rdx, rax, rbx, // outputs: method, scan temp. reg - rbx, r13, + rbx, rbcp, no_such_interface); // rbx: Method* to call @@ -3135,7 +3588,7 @@ void TemplateTable::invokeinterface(int byte_no) { __ testptr(rbx, rbx); __ jcc(Assembler::zero, no_such_method); - __ profile_arguments_type(rdx, rbx, r13, true); + __ profile_arguments_type(rdx, rbx, rbcp, true); // do the call // rcx: receiver @@ -3150,7 +3603,7 @@ void TemplateTable::invokeinterface(int byte_no) { __ bind(no_such_method); // throw exception __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) + __ restore_bcp(); // rbcp must be correct for exception handler (was destroyed) __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); // the call_VM checks for exception, so we should never return here. @@ -3159,7 +3612,7 @@ void TemplateTable::invokeinterface(int byte_no) { __ bind(no_such_interface); // throw exception __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) + __ restore_bcp(); // rbcp must be correct for exception handler (was destroyed) __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); @@ -3167,7 +3620,6 @@ void TemplateTable::invokeinterface(int byte_no) { __ should_not_reach_here(); } - void TemplateTable::invokehandle(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); @@ -3188,12 +3640,11 @@ void TemplateTable::invokehandle(int byte_no) { // FIXME: profile the LambdaForm also __ profile_final_call(rax); - __ profile_arguments_type(rdx, rbx_method, r13, true); + __ profile_arguments_type(rdx, rbx_method, rbcp, true); __ jump_from_interpreted(rbx_method, rdx); } - void TemplateTable::invokedynamic(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); @@ -3210,15 +3661,14 @@ void TemplateTable::invokedynamic(int byte_no) { // %%% should make a type profile for any invokedynamic that takes a ref argument // profile this call - __ profile_call(r13); - __ profile_arguments_type(rdx, rbx_method, r13, false); + __ profile_call(rbcp); + __ profile_arguments_type(rdx, rbx_method, rbcp, false); __ verify_oop(rax_callsite); __ jump_from_interpreted(rbx_method, rdx); } - //----------------------------------------------------------------------------- // Allocation @@ -3226,39 +3676,37 @@ void TemplateTable::_new() { transition(vtos, atos); __ get_unsigned_2_byte_index_at_bcp(rdx, 1); Label slow_case; + Label slow_case_no_pop; Label done; Label initialize_header; - Label initialize_object; // including clearing the fields + Label initialize_object; // including clearing the fields Label allocate_shared; - __ get_cpool_and_tags(rsi, rax); + __ get_cpool_and_tags(rcx, rax); + // Make sure the class we're about to instantiate has been resolved. // This is done before loading InstanceKlass to be consistent with the order // how Constant Pool is updated (see ConstantPool::klass_at_put) const int tags_offset = Array::base_offset_in_bytes(); - __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), - JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, slow_case); + __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), JVM_CONSTANT_Class); + __ jcc(Assembler::notEqual, slow_case_no_pop); // get InstanceKlass - __ movptr(rsi, Address(rsi, rdx, - Address::times_8, sizeof(ConstantPool))); + __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); + __ push(rcx); // save the contexts of klass for initializing the header // make sure klass is initialized & doesn't have finalizer // make sure klass is fully initialized - __ cmpb(Address(rsi, - InstanceKlass::init_state_offset()), - InstanceKlass::fully_initialized); + __ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized); __ jcc(Assembler::notEqual, slow_case); // get instance_size in InstanceKlass (scaled to a count of bytes) - __ movl(rdx, - Address(rsi, - Klass::layout_helper_offset())); + __ movl(rdx, Address(rcx, Klass::layout_helper_offset())); // test to see if it has a finalizer or is malformed in some way __ testl(rdx, Klass::_lh_instance_slow_path_bit); __ jcc(Assembler::notZero, slow_case); + // // Allocate the instance // 1) Try to allocate in the TLAB // 2) if fail and the object is large allocate in the shared Eden @@ -3268,12 +3716,19 @@ void TemplateTable::_new() { const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc(); + const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rcx); +#ifndef _LP64 + if (UseTLAB || allow_shared_alloc) { + __ get_thread(thread); + } +#endif // _LP64 + if (UseTLAB) { - __ movptr(rax, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset()))); + __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(r15_thread, in_bytes(JavaThread::tlab_end_offset()))); + __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case); - __ movptr(Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())), rbx); + __ movptr(Address(thread, in_bytes(JavaThread::tlab_top_offset())), rbx); if (ZeroTLAB) { // the fields have been already cleared __ jmp(initialize_header); @@ -3289,93 +3744,104 @@ void TemplateTable::_new() { if (allow_shared_alloc) { __ bind(allocate_shared); - ExternalAddress top((address)Universe::heap()->top_addr()); - ExternalAddress end((address)Universe::heap()->end_addr()); + ExternalAddress heap_top((address)Universe::heap()->top_addr()); + ExternalAddress heap_end((address)Universe::heap()->end_addr()); - const Register RtopAddr = rscratch1; - const Register RendAddr = rscratch2; - - __ lea(RtopAddr, top); - __ lea(RendAddr, end); - __ movptr(rax, Address(RtopAddr, 0)); - - // For retries rax gets set by cmpxchgq Label retry; __ bind(retry); + __ movptr(rax, heap_top); __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(RendAddr, 0)); + __ cmpptr(rbx, heap_end); __ jcc(Assembler::above, slow_case); - // Compare rax with the top addr, and if still equal, store the new - // top addr in rbx at the address of the top addr pointer. Sets ZF if was + // Compare rax, with the top addr, and if still equal, store the new + // top addr in rbx, at the address of the top addr pointer. Sets ZF if was // equal, and clears it otherwise. Use lock prefix for atomicity on MPs. // - // rax: object begin - // rbx: object end + // rax,: object begin + // rbx,: object end // rdx: instance size in bytes - if (os::is_MP()) { - __ lock(); - } - __ cmpxchgptr(rbx, Address(RtopAddr, 0)); + __ locked_cmpxchgptr(rbx, heap_top); // if someone beat us on the allocation, try again, otherwise continue __ jcc(Assembler::notEqual, retry); - __ incr_allocated_bytes(r15_thread, rdx, 0); + __ incr_allocated_bytes(thread, rdx, 0); } if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { // The object is initialized before the header. If the object size is // zero, go directly to the header initialization. __ bind(initialize_object); - __ decrementl(rdx, sizeof(oopDesc)); + __ decrement(rdx, sizeof(oopDesc)); __ jcc(Assembler::zero, initialize_header); - // Initialize object fields - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ shrl(rdx, LogBytesPerLong); // divide by oopSize to simplify the loop - { - Label loop; - __ bind(loop); - __ movq(Address(rax, rdx, Address::times_8, - sizeof(oopDesc) - oopSize), - rcx); - __ decrementl(rdx); - __ jcc(Assembler::notZero, loop); + // Initialize topmost object field, divide rdx by 8, check if odd and + // test if zero. + __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) + __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd + + // rdx must have been multiple of 8 +#ifdef ASSERT + // make sure rdx was multiple of 8 + Label L; + // Ignore partial flag stall after shrl() since it is debug VM + __ jccb(Assembler::carryClear, L); + __ stop("object size is not multiple of 2 - adjust this code"); + __ bind(L); + // rdx must be > 0, no extra check needed here +#endif + + // initialize remaining object fields: rdx was a multiple of 8 + { Label loop; + __ bind(loop); + __ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 1*oopSize), rcx); + NOT_LP64(__ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 2*oopSize), rcx)); + __ decrement(rdx); + __ jcc(Assembler::notZero, loop); } // initialize object header only. __ bind(initialize_header); if (UseBiasedLocking) { - __ movptr(rscratch1, Address(rsi, Klass::prototype_header_offset())); - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1); + __ pop(rcx); // get saved klass back in the register. + __ movptr(rbx, Address(rcx, Klass::prototype_header_offset())); + __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), rbx); } else { - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), - (intptr_t) markOopDesc::prototype()); // header (address 0x1) + __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), + (intptr_t)markOopDesc::prototype()); // header + __ pop(rcx); // get saved klass back in the register. } - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ store_klass_gap(rax, rcx); // zero klass gap for compressed oops - __ store_klass(rax, rsi); // store klass last +#ifdef _LP64 + __ xorl(rsi, rsi); // use zero reg to clear memory (shorter code) + __ store_klass_gap(rax, rsi); // zero klass gap for compressed oops +#endif + __ store_klass(rax, rcx); // klass { - SkipIfEqual skip(_masm, &DTraceAllocProbes, false); + SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0); // Trigger dtrace event for fastpath - __ push(atos); // save the return value + __ push(atos); __ call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); - __ pop(atos); // restore the return value - + __ pop(atos); } + __ jmp(done); } - // slow case __ bind(slow_case); - __ get_constant_pool(c_rarg1); - __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), c_rarg1, c_rarg2); - __ verify_oop(rax); + __ pop(rcx); // restore stack pointer to what it was when we came in. + __ bind(slow_case_no_pop); + + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rax); + Register rarg2 = LP64_ONLY(c_rarg2) NOT_LP64(rdx); + + __ get_constant_pool(rarg1); + __ get_unsigned_2_byte_index_at_bcp(rarg2, 1); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), rarg1, rarg2); + __ verify_oop(rax); // continue __ bind(done); @@ -3383,19 +3849,22 @@ void TemplateTable::_new() { void TemplateTable::newarray() { transition(itos, atos); - __ load_unsigned_byte(c_rarg1, at_bcp(1)); - __ movl(c_rarg2, rax); + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + __ load_unsigned_byte(rarg1, at_bcp(1)); call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), - c_rarg1, c_rarg2); + rarg1, rax); } void TemplateTable::anewarray() { transition(itos, atos); - __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); - __ get_constant_pool(c_rarg1); - __ movl(c_rarg3, rax); + + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rcx); + Register rarg2 = LP64_ONLY(c_rarg2) NOT_LP64(rdx); + + __ get_unsigned_2_byte_index_at_bcp(rarg2, 1); + __ get_constant_pool(rarg1); call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), - c_rarg1, c_rarg2, c_rarg3); + rarg1, rarg2, rax); } void TemplateTable::arraylength() { @@ -3421,8 +3890,17 @@ void TemplateTable::checkcast() { __ jcc(Assembler::equal, quicked); __ push(atos); // save receiver for result, and for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); + // vm_result_2 has metadata result +#ifndef _LP64 + // borrow rdi from locals + __ get_thread(rdi); + __ get_vm_result_2(rax, rdi); + __ restore_locals(); +#else __ get_vm_result_2(rax, r15_thread); +#endif + __ pop_ptr(rdx); // restore receiver __ jmpb(resolved); @@ -3430,7 +3908,7 @@ void TemplateTable::checkcast() { __ bind(quicked); __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check __ movptr(rax, Address(rcx, rbx, - Address::times_8, sizeof(ConstantPool))); + Address::times_ptr, sizeof(ConstantPool))); __ bind(resolved); __ load_klass(rbx, rdx); @@ -3478,7 +3956,16 @@ void TemplateTable::instanceof() { __ push(atos); // save receiver for result, and for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); // vm_result_2 has metadata result + +#ifndef _LP64 + // borrow rdi from locals + __ get_thread(rdi); + __ get_vm_result_2(rax, rdi); + __ restore_locals(); +#else __ get_vm_result_2(rax, r15_thread); +#endif + __ pop_ptr(rdx); // restore receiver __ verify_oop(rdx); __ load_klass(rdx, rdx); @@ -3488,7 +3975,7 @@ void TemplateTable::instanceof() { __ bind(quicked); __ load_klass(rdx, rax); __ movptr(rax, Address(rcx, rbx, - Address::times_8, sizeof(ConstantPool))); + Address::times_ptr, sizeof(ConstantPool))); __ bind(resolved); @@ -3516,28 +4003,31 @@ void TemplateTable::instanceof() { // rax = 1: obj != NULL and obj is an instanceof the specified klass } -//----------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------------------- // Breakpoints void TemplateTable::_breakpoint() { // Note: We get here even if we are single stepping.. - // jbug inists on setting breakpoints at every bytecode + // jbug insists on setting breakpoints at every bytecode // even if we are in single step mode. transition(vtos, vtos); + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rcx); + // get the unpatched byte code - __ get_method(c_rarg1); + __ get_method(rarg); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_original_bytecode_at), - c_rarg1, r13); - __ mov(rbx, rax); + rarg, rbcp); + __ mov(rbx, rax); // why? // post the breakpoint event - __ get_method(c_rarg1); + __ get_method(rarg); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), - c_rarg1, r13); + rarg, rbcp); // complete the execution of original bytecode __ dispatch_only_normal(vtos); @@ -3583,75 +4073,79 @@ void TemplateTable::monitorenter() { Label allocated; - // initialize entry pointer - __ xorl(c_rarg1, c_rarg1); // points to free slot or NULL + Register rtop = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx); + Register rmon = LP64_ONLY(c_rarg1) NOT_LP64(rdx); - // find a free slot in the monitor block (result in c_rarg1) + // initialize entry pointer + __ xorl(rmon, rmon); // points to free slot or NULL + + // find a free slot in the monitor block (result in rmon) { Label entry, loop, exit; - __ movptr(c_rarg3, monitor_block_top); // points to current entry, - // starting with top-most entry - __ lea(c_rarg2, monitor_block_bot); // points to word before bottom - // of monitor block + __ movptr(rtop, monitor_block_top); // points to current entry, + // starting with top-most entry + __ lea(rbot, monitor_block_bot); // points to word before bottom + // of monitor block __ jmpb(entry); __ bind(loop); // check if current entry is used - __ cmpptr(Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD); - // if not used then remember entry in c_rarg1 - __ cmov(Assembler::equal, c_rarg1, c_rarg3); + __ cmpptr(Address(rtop, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD); + // if not used then remember entry in rmon + __ cmovptr(Assembler::equal, rmon, rtop); // cmov => cmovptr // check if current entry is for same object - __ cmpptr(rax, Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes())); + __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes())); // if same object then stop searching __ jccb(Assembler::equal, exit); // otherwise advance to next entry - __ addptr(c_rarg3, entry_size); + __ addptr(rtop, entry_size); __ bind(entry); // check if bottom reached - __ cmpptr(c_rarg3, c_rarg2); + __ cmpptr(rtop, rbot); // if not at bottom then check this entry __ jcc(Assembler::notEqual, loop); __ bind(exit); } - __ testptr(c_rarg1, c_rarg1); // check if a slot has been found + __ testptr(rmon, rmon); // check if a slot has been found __ jcc(Assembler::notZero, allocated); // if found, continue with that one // allocate one if there's no free slot { Label entry, loop; - // 1. compute new pointers // rsp: old expression stack top - __ movptr(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom - __ subptr(rsp, entry_size); // move expression stack top - __ subptr(c_rarg1, entry_size); // move expression stack bottom - __ mov(c_rarg3, rsp); // set start value for copy loop - __ movptr(monitor_block_bot, c_rarg1); // set new monitor block bottom + // 1. compute new pointers // rsp: old expression stack top + __ movptr(rmon, monitor_block_bot); // rmon: old expression stack bottom + __ subptr(rsp, entry_size); // move expression stack top + __ subptr(rmon, entry_size); // move expression stack bottom + __ mov(rtop, rsp); // set start value for copy loop + __ movptr(monitor_block_bot, rmon); // set new monitor block bottom __ jmp(entry); // 2. move expression stack contents __ bind(loop); - __ movptr(c_rarg2, Address(c_rarg3, entry_size)); // load expression stack - // word from old location - __ movptr(Address(c_rarg3, 0), c_rarg2); // and store it at new location - __ addptr(c_rarg3, wordSize); // advance to next word + __ movptr(rbot, Address(rtop, entry_size)); // load expression stack + // word from old location + __ movptr(Address(rtop, 0), rbot); // and store it at new location + __ addptr(rtop, wordSize); // advance to next word __ bind(entry); - __ cmpptr(c_rarg3, c_rarg1); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then - // copy next word + __ cmpptr(rtop, rmon); // check if bottom reached + __ jcc(Assembler::notEqual, loop); // if not at bottom then + // copy next word } // call run-time routine - // c_rarg1: points to monitor entry + // rmon: points to monitor entry __ bind(allocated); // Increment bcp to point to the next bytecode, so exception // handling for async. exceptions work correctly. // The object has already been poped from the stack, so the // expression stack looks correct. - __ increment(r13); + __ increment(rbcp); // store object - __ movptr(Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()), rax); - __ lock_object(c_rarg1); + __ movptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), rax); + __ lock_object(rmon); // check to make sure this monitor doesn't cause stack overflow after locking __ save_bcp(); // in case of exception @@ -3662,7 +4156,6 @@ void TemplateTable::monitorenter() { __ dispatch_next(vtos); } - void TemplateTable::monitorexit() { transition(atos, vtos); @@ -3675,27 +4168,30 @@ void TemplateTable::monitorexit() { rbp, frame::interpreter_frame_initial_sp_offset * wordSize); const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + Register rtop = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx); + Label found; // find matching slot { Label entry, loop; - __ movptr(c_rarg1, monitor_block_top); // points to current entry, - // starting with top-most entry - __ lea(c_rarg2, monitor_block_bot); // points to word before bottom - // of monitor block + __ movptr(rtop, monitor_block_top); // points to current entry, + // starting with top-most entry + __ lea(rbot, monitor_block_bot); // points to word before bottom + // of monitor block __ jmpb(entry); __ bind(loop); // check if current entry is for same object - __ cmpptr(rax, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); + __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes())); // if same object then stop searching __ jcc(Assembler::equal, found); // otherwise advance to next entry - __ addptr(c_rarg1, entry_size); + __ addptr(rtop, entry_size); __ bind(entry); // check if bottom reached - __ cmpptr(c_rarg1, c_rarg2); + __ cmpptr(rtop, rbot); // if not at bottom then check this entry __ jcc(Assembler::notEqual, loop); } @@ -3706,36 +4202,34 @@ void TemplateTable::monitorexit() { __ should_not_reach_here(); // call run-time routine - // rsi: points to monitor entry __ bind(found); __ push_ptr(rax); // make sure object is on stack (contract with oopMaps) - __ unlock_object(c_rarg1); + __ unlock_object(rtop); __ pop_ptr(rax); // discard object } - // Wide instructions void TemplateTable::wide() { transition(vtos, vtos); __ load_unsigned_byte(rbx, at_bcp(1)); - __ lea(rscratch1, ExternalAddress((address)Interpreter::_wentry_point)); - __ jmp(Address(rscratch1, rbx, Address::times_8)); - // Note: the r13 increment step is part of the individual wide - // bytecode implementations + ExternalAddress wtable((address)Interpreter::_wentry_point); + __ jump(ArrayAddress(wtable, Address(noreg, rbx, Address::times_ptr))); + // Note: the rbcp increment step is part of the individual wide bytecode implementations } - // Multi arrays void TemplateTable::multianewarray() { transition(vtos, atos); + + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rax); __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions // last dim is on top of stack; we want address of first one: - // first_addr = last_addr + (ndims - 1) * wordSize - __ lea(c_rarg1, Address(rsp, rax, Address::times_8, -wordSize)); - call_VM(rax, - CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), - c_rarg1); + // first_addr = last_addr + (ndims - 1) * stackElementSize - 1*wordsize + // the latter wordSize to point to the beginning of the array. + __ lea(rarg, Address(rsp, rax, Interpreter::stackElementScale(), -wordSize)); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), rarg); __ load_unsigned_byte(rbx, at_bcp(3)); - __ lea(rsp, Address(rsp, rbx, Address::times_8)); + __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); // get rid of counts } -#endif // !CC_INTERP +#endif /* !CC_INTERP */ + diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp deleted file mode 100644 index 1a8d8870c2a..00000000000 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ /dev/null @@ -1,3668 +0,0 @@ -/* - * Copyright (c) 1997, 2014, 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" -#include "asm/macroAssembler.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "interpreter/interp_masm.hpp" -#include "interpreter/templateTable.hpp" -#include "memory/universe.inline.hpp" -#include "oops/methodData.hpp" -#include "oops/objArrayKlass.hpp" -#include "oops/oop.inline.hpp" -#include "prims/methodHandles.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/stubRoutines.hpp" -#include "runtime/synchronizer.hpp" -#include "utilities/macros.hpp" - -#ifndef CC_INTERP -#define __ _masm-> - -//---------------------------------------------------------------------------------------------------- -// Platform-dependent initialization - -void TemplateTable::pd_initialize() { - // No i486 specific initialization -} - -//---------------------------------------------------------------------------------------------------- -// Address computation - -// local variables -static inline Address iaddress(int n) { - return Address(rdi, Interpreter::local_offset_in_bytes(n)); -} - -static inline Address laddress(int n) { return iaddress(n + 1); } -static inline Address haddress(int n) { return iaddress(n + 0); } -static inline Address faddress(int n) { return iaddress(n); } -static inline Address daddress(int n) { return laddress(n); } -static inline Address aaddress(int n) { return iaddress(n); } - -static inline Address iaddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale()); -} -static inline Address laddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(1)); -} -static inline Address haddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(0)); -} - -static inline Address faddress(Register r) { return iaddress(r); } -static inline Address daddress(Register r) { return laddress(r); } -static inline Address aaddress(Register r) { return iaddress(r); } - -// expression stack -// (Note: Must not use symmetric equivalents at_rsp_m1/2 since they store -// data beyond the rsp which is potentially unsafe in an MT environment; -// an interrupt may overwrite that data.) -static inline Address at_rsp () { - return Address(rsp, 0); -} - -// At top of Java expression stack which may be different than rsp(). It -// isn't for category 1 objects. -static inline Address at_tos () { - Address tos = Address(rsp, Interpreter::expr_offset_in_bytes(0)); - return tos; -} - -static inline Address at_tos_p1() { - return Address(rsp, Interpreter::expr_offset_in_bytes(1)); -} - -static inline Address at_tos_p2() { - return Address(rsp, Interpreter::expr_offset_in_bytes(2)); -} - -// Condition conversion -static Assembler::Condition j_not(TemplateTable::Condition cc) { - switch (cc) { - case TemplateTable::equal : return Assembler::notEqual; - case TemplateTable::not_equal : return Assembler::equal; - case TemplateTable::less : return Assembler::greaterEqual; - case TemplateTable::less_equal : return Assembler::greater; - case TemplateTable::greater : return Assembler::lessEqual; - case TemplateTable::greater_equal: return Assembler::less; - } - ShouldNotReachHere(); - return Assembler::zero; -} - - -//---------------------------------------------------------------------------------------------------- -// Miscelaneous helper routines - -// Store an oop (or NULL) at the address described by obj. -// If val == noreg this means store a NULL - -static void do_oop_store(InterpreterMacroAssembler* _masm, - Address obj, - Register val, - BarrierSet::Name barrier, - bool precise) { - assert(val == noreg || val == rax, "parameter is just for looks"); - switch (barrier) { -#if INCLUDE_ALL_GCS - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: - { - // flatten object address if needed - // We do it regardless of precise because we need the registers - if (obj.index() == noreg && obj.disp() == 0) { - if (obj.base() != rdx) { - __ movl(rdx, obj.base()); - } - } else { - __ leal(rdx, obj); - } - __ get_thread(rcx); - __ save_bcp(); - __ g1_write_barrier_pre(rdx /* obj */, - rbx /* pre_val */, - rcx /* thread */, - rsi /* tmp */, - val != noreg /* tosca_live */, - false /* expand_call */); - - // Do the actual store - // noreg means NULL - if (val == noreg) { - __ movptr(Address(rdx, 0), NULL_WORD); - // No post barrier for NULL - } else { - __ movl(Address(rdx, 0), val); - __ g1_write_barrier_post(rdx /* store_adr */, - val /* new_val */, - rcx /* thread */, - rbx /* tmp */, - rsi /* tmp2 */); - } - __ restore_bcp(); - - } - break; -#endif // INCLUDE_ALL_GCS - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: - { - if (val == noreg) { - __ movptr(obj, NULL_WORD); - } else { - __ movl(obj, val); - // flatten object address if needed - if (!precise || (obj.index() == noreg && obj.disp() == 0)) { - __ store_check(obj.base()); - } else { - __ leal(rdx, obj); - __ store_check(rdx); - } - } - } - break; - case BarrierSet::ModRef: - if (val == noreg) { - __ movptr(obj, NULL_WORD); - } else { - __ movl(obj, val); - } - break; - default : - ShouldNotReachHere(); - - } -} - -Address TemplateTable::at_bcp(int offset) { - assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); - return Address(rsi, offset); -} - - -void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, - Register temp_reg, bool load_bc_into_bc_reg/*=true*/, - int byte_no) { - if (!RewriteBytecodes) return; - Label L_patch_done; - - switch (bc) { - case Bytecodes::_fast_aputfield: - case Bytecodes::_fast_bputfield: - case Bytecodes::_fast_cputfield: - case Bytecodes::_fast_dputfield: - case Bytecodes::_fast_fputfield: - case Bytecodes::_fast_iputfield: - case Bytecodes::_fast_lputfield: - case Bytecodes::_fast_sputfield: - { - // We skip bytecode quickening for putfield instructions when - // the put_code written to the constant pool cache is zero. - // This is required so that every execution of this instruction - // calls out to InterpreterRuntime::resolve_get_put to do - // additional, required work. - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - assert(load_bc_into_bc_reg, "we use bc_reg as temp"); - __ get_cache_and_index_and_bytecode_at_bcp(bc_reg, temp_reg, temp_reg, byte_no, 1); - __ movl(bc_reg, bc); - __ cmpl(temp_reg, (int) 0); - __ jcc(Assembler::zero, L_patch_done); // don't patch - } - break; - default: - assert(byte_no == -1, "sanity"); - // the pair bytecodes have already done the load. - if (load_bc_into_bc_reg) { - __ movl(bc_reg, bc); - } - } - - if (JvmtiExport::can_post_breakpoint()) { - Label L_fast_patch; - // if a breakpoint is present we can't rewrite the stream directly - __ movzbl(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, Bytecodes::_breakpoint); - __ jcc(Assembler::notEqual, L_fast_patch); - __ get_method(temp_reg); - // Let breakpoint table handling rewrite to quicker bytecode - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, rsi, bc_reg); -#ifndef ASSERT - __ jmpb(L_patch_done); -#else - __ jmp(L_patch_done); -#endif - __ bind(L_fast_patch); - } - -#ifdef ASSERT - Label L_okay; - __ load_unsigned_byte(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, (int)Bytecodes::java_code(bc)); - __ jccb(Assembler::equal, L_okay); - __ cmpl(temp_reg, bc_reg); - __ jcc(Assembler::equal, L_okay); - __ stop("patching the wrong bytecode"); - __ bind(L_okay); -#endif - - // patch bytecode - __ movb(at_bcp(0), bc_reg); - __ bind(L_patch_done); -} - -//---------------------------------------------------------------------------------------------------- -// Individual instructions - -void TemplateTable::nop() { - transition(vtos, vtos); - // nothing to do -} - -void TemplateTable::shouldnotreachhere() { - transition(vtos, vtos); - __ stop("shouldnotreachhere bytecode"); -} - - - -void TemplateTable::aconst_null() { - transition(vtos, atos); - __ xorptr(rax, rax); -} - - -void TemplateTable::iconst(int value) { - transition(vtos, itos); - if (value == 0) { - __ xorptr(rax, rax); - } else { - __ movptr(rax, value); - } -} - - -void TemplateTable::lconst(int value) { - transition(vtos, ltos); - if (value == 0) { - __ xorptr(rax, rax); - } else { - __ movptr(rax, value); - } - assert(value >= 0, "check this code"); - __ xorptr(rdx, rdx); -} - - -void TemplateTable::fconst(int value) { - transition(vtos, ftos); - if (value == 0) { __ fldz(); - } else if (value == 1) { __ fld1(); - } else if (value == 2) { __ fld1(); __ fld1(); __ faddp(); // should do a better solution here - } else { ShouldNotReachHere(); - } -} - - -void TemplateTable::dconst(int value) { - transition(vtos, dtos); - if (value == 0) { __ fldz(); - } else if (value == 1) { __ fld1(); - } else { ShouldNotReachHere(); - } -} - - -void TemplateTable::bipush() { - transition(vtos, itos); - __ load_signed_byte(rax, at_bcp(1)); -} - - -void TemplateTable::sipush() { - transition(vtos, itos); - __ load_unsigned_short(rax, at_bcp(1)); - __ bswapl(rax); - __ sarl(rax, 16); -} - -void TemplateTable::ldc(bool wide) { - transition(vtos, vtos); - Label call_ldc, notFloat, notClass, Done; - - if (wide) { - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - } else { - __ load_unsigned_byte(rbx, at_bcp(1)); - } - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ xorptr(rdx, rdx); - __ movb(rdx, Address(rax, rbx, Address::times_1, tags_offset)); - - // unresolved class - get the resolved class - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass); - __ jccb(Assembler::equal, call_ldc); - - // unresolved class in error (resolution failed) - call into runtime - // so that the same error from first resolution attempt is thrown. - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError); - __ jccb(Assembler::equal, call_ldc); - - // resolved class - need to call vm to get java mirror of the class - __ cmpl(rdx, JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, notClass); - - __ bind(call_ldc); - __ movl(rcx, wide); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), rcx); - __ push(atos); - __ jmp(Done); - - __ bind(notClass); - __ cmpl(rdx, JVM_CONSTANT_Float); - __ jccb(Assembler::notEqual, notFloat); - // ftos - __ fld_s( Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(ftos); - __ jmp(Done); - - __ bind(notFloat); -#ifdef ASSERT - { Label L; - __ cmpl(rdx, JVM_CONSTANT_Integer); - __ jcc(Assembler::equal, L); - // String and Object are rewritten to fast_aldc - __ stop("unexpected tag type in ldc"); - __ bind(L); - } -#endif - // itos JVM_CONSTANT_Integer only - __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(itos); - __ bind(Done); -} - -// Fast path for caching oop constants. -void TemplateTable::fast_aldc(bool wide) { - transition(vtos, atos); - - Register result = rax; - Register tmp = rdx; - int index_size = wide ? sizeof(u2) : sizeof(u1); - - Label resolved; - - // We are resolved if the resolved reference cache entry contains a - // non-null object (String, MethodType, etc.) - assert_different_registers(result, tmp); - __ get_cache_index_at_bcp(tmp, 1, index_size); - __ load_resolved_reference_at_index(result, tmp); - __ testl(result, result); - __ jcc(Assembler::notZero, resolved); - - address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); - - // first time invocation - must resolve first - __ movl(tmp, (int)bytecode()); - __ call_VM(result, entry, tmp); - - __ bind(resolved); - - if (VerifyOops) { - __ verify_oop(result); - } -} - -void TemplateTable::ldc2_w() { - transition(vtos, vtos); - Label Long, Done; - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ cmpb(Address(rax, rbx, Address::times_1, tags_offset), JVM_CONSTANT_Double); - __ jccb(Assembler::notEqual, Long); - // dtos - __ fld_d( Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(dtos); - __ jmpb(Done); - - __ bind(Long); - // ltos - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, base_offset + 0 * wordSize)); - NOT_LP64(__ movptr(rdx, Address(rcx, rbx, Address::times_ptr, base_offset + 1 * wordSize))); - - __ push(ltos); - - __ bind(Done); -} - - -void TemplateTable::locals_index(Register reg, int offset) { - __ load_unsigned_byte(reg, at_bcp(offset)); - __ negptr(reg); -} - - -void TemplateTable::iload() { - transition(vtos, itos); - if (RewriteFrequentPairs) { - Label rewrite, done; - - // get next byte - __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_iload))); - // if _iload, wait to rewrite to iload2. We only want to rewrite the - // last two iloads in a pair. Comparing against fast_iload means that - // the next bytecode is neither an iload or a caload, and therefore - // an iload pair. - __ cmpl(rbx, Bytecodes::_iload); - __ jcc(Assembler::equal, done); - - __ cmpl(rbx, Bytecodes::_fast_iload); - __ movl(rcx, Bytecodes::_fast_iload2); - __ jccb(Assembler::equal, rewrite); - - // if _caload, rewrite to fast_icaload - __ cmpl(rbx, Bytecodes::_caload); - __ movl(rcx, Bytecodes::_fast_icaload); - __ jccb(Assembler::equal, rewrite); - - // rewrite so iload doesn't check again. - __ movl(rcx, Bytecodes::_fast_iload); - - // rewrite - // rcx: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_iload, rcx, rbx, false); - __ bind(done); - } - - // Get the local value into tos - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::fast_iload2() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - __ push(itos); - locals_index(rbx, 3); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::fast_iload() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::lload() { - transition(vtos, ltos); - locals_index(rbx); - __ movptr(rax, laddress(rbx)); - NOT_LP64(__ movl(rdx, haddress(rbx))); -} - - -void TemplateTable::fload() { - transition(vtos, ftos); - locals_index(rbx); - __ fld_s(faddress(rbx)); -} - - -void TemplateTable::dload() { - transition(vtos, dtos); - locals_index(rbx); - __ fld_d(daddress(rbx)); -} - - -void TemplateTable::aload() { - transition(vtos, atos); - locals_index(rbx); - __ movptr(rax, aaddress(rbx)); -} - - -void TemplateTable::locals_index_wide(Register reg) { - __ load_unsigned_short(reg, at_bcp(2)); - __ bswapl(reg); - __ shrl(reg, 16); - __ negptr(reg); -} - - -void TemplateTable::wide_iload() { - transition(vtos, itos); - locals_index_wide(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::wide_lload() { - transition(vtos, ltos); - locals_index_wide(rbx); - __ movptr(rax, laddress(rbx)); - NOT_LP64(__ movl(rdx, haddress(rbx))); -} - - -void TemplateTable::wide_fload() { - transition(vtos, ftos); - locals_index_wide(rbx); - __ fld_s(faddress(rbx)); -} - - -void TemplateTable::wide_dload() { - transition(vtos, dtos); - locals_index_wide(rbx); - __ fld_d(daddress(rbx)); -} - - -void TemplateTable::wide_aload() { - transition(vtos, atos); - locals_index_wide(rbx); - __ movptr(rax, aaddress(rbx)); -} - -void TemplateTable::index_check(Register array, Register index) { - // Pop ptr into array - __ pop_ptr(array); - index_check_without_pop(array, index); -} - -void TemplateTable::index_check_without_pop(Register array, Register index) { - // destroys rbx, - // check array - __ null_check(array, arrayOopDesc::length_offset_in_bytes()); - LP64_ONLY(__ movslq(index, index)); - // check index - __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes())); - if (index != rbx) { - // ??? convention: move aberrant index into rbx, for exception message - assert(rbx != array, "different registers"); - __ mov(rbx, index); - } - __ jump_cc(Assembler::aboveEqual, - ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); -} - - -void TemplateTable::iaload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ movl(rax, Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT))); -} - - -void TemplateTable::laload() { - transition(itos, ltos); - // rax,: index - // rdx: array - index_check(rdx, rax); - __ mov(rbx, rax); - // rbx,: index - __ movptr(rax, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize)); - NOT_LP64(__ movl(rdx, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize))); -} - - -void TemplateTable::faload() { - transition(itos, ftos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ fld_s(Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT))); -} - - -void TemplateTable::daload() { - transition(itos, dtos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ fld_d(Address(rdx, rax, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); -} - - -void TemplateTable::aaload() { - transition(itos, atos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ movptr(rax, Address(rdx, rax, Address::times_ptr, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); -} - - -void TemplateTable::baload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - fix this at some point - __ load_signed_byte(rbx, Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE))); - __ mov(rax, rbx); -} - - -void TemplateTable::caload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - may want to improve this at some point - __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - __ mov(rax, rbx); -} - -// iload followed by caload frequent pair -void TemplateTable::fast_icaload() { - transition(vtos, itos); - // load index out of locals - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - - // rdx: array - index_check(rdx, rax); - // rax,: index - __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - __ mov(rax, rbx); -} - -void TemplateTable::saload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - may want to improve this at some point - __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); - __ mov(rax, rbx); -} - - -void TemplateTable::iload(int n) { - transition(vtos, itos); - __ movl(rax, iaddress(n)); -} - - -void TemplateTable::lload(int n) { - transition(vtos, ltos); - __ movptr(rax, laddress(n)); - NOT_LP64(__ movptr(rdx, haddress(n))); -} - - -void TemplateTable::fload(int n) { - transition(vtos, ftos); - __ fld_s(faddress(n)); -} - - -void TemplateTable::dload(int n) { - transition(vtos, dtos); - __ fld_d(daddress(n)); -} - - -void TemplateTable::aload(int n) { - transition(vtos, atos); - __ movptr(rax, aaddress(n)); -} - - -void TemplateTable::aload_0() { - transition(vtos, atos); - // According to bytecode histograms, the pairs: - // - // _aload_0, _fast_igetfield - // _aload_0, _fast_agetfield - // _aload_0, _fast_fgetfield - // - // occur frequently. If RewriteFrequentPairs is set, the (slow) _aload_0 - // bytecode checks if the next bytecode is either _fast_igetfield, - // _fast_agetfield or _fast_fgetfield and then rewrites the - // current bytecode into a pair bytecode; otherwise it rewrites the current - // bytecode into _fast_aload_0 that doesn't do the pair check anymore. - // - // Note: If the next bytecode is _getfield, the rewrite must be delayed, - // otherwise we may miss an opportunity for a pair. - // - // Also rewrite frequent pairs - // aload_0, aload_1 - // aload_0, iload_1 - // These bytecodes with a small amount of code are most profitable to rewrite - if (RewriteFrequentPairs) { - Label rewrite, done; - // get next byte - __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); - - // do actual aload_0 - aload(0); - - // if _getfield then wait with rewrite - __ cmpl(rbx, Bytecodes::_getfield); - __ jcc(Assembler::equal, done); - - // if _igetfield then reqrite to _fast_iaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_igetfield); - __ movl(rcx, Bytecodes::_fast_iaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _agetfield then reqrite to _fast_aaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_agetfield); - __ movl(rcx, Bytecodes::_fast_aaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _fgetfield then reqrite to _fast_faccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_fgetfield); - __ movl(rcx, Bytecodes::_fast_faccess_0); - __ jccb(Assembler::equal, rewrite); - - // else rewrite to _fast_aload0 - assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ movl(rcx, Bytecodes::_fast_aload_0); - - // rewrite - // rcx: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_aload_0, rcx, rbx, false); - - __ bind(done); - } else { - aload(0); - } -} - -void TemplateTable::istore() { - transition(itos, vtos); - locals_index(rbx); - __ movl(iaddress(rbx), rax); -} - - -void TemplateTable::lstore() { - transition(ltos, vtos); - locals_index(rbx); - __ movptr(laddress(rbx), rax); - NOT_LP64(__ movptr(haddress(rbx), rdx)); -} - - -void TemplateTable::fstore() { - transition(ftos, vtos); - locals_index(rbx); - __ fstp_s(faddress(rbx)); -} - - -void TemplateTable::dstore() { - transition(dtos, vtos); - locals_index(rbx); - __ fstp_d(daddress(rbx)); -} - - -void TemplateTable::astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index(rbx); - __ movptr(aaddress(rbx), rax); -} - - -void TemplateTable::wide_istore() { - transition(vtos, vtos); - __ pop_i(rax); - locals_index_wide(rbx); - __ movl(iaddress(rbx), rax); -} - - -void TemplateTable::wide_lstore() { - transition(vtos, vtos); - __ pop_l(rax, rdx); - locals_index_wide(rbx); - __ movptr(laddress(rbx), rax); - NOT_LP64(__ movl(haddress(rbx), rdx)); -} - - -void TemplateTable::wide_fstore() { - wide_istore(); -} - - -void TemplateTable::wide_dstore() { - wide_lstore(); -} - - -void TemplateTable::wide_astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index_wide(rbx); - __ movptr(aaddress(rbx), rax); -} - - -void TemplateTable::iastore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movl(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), rax); -} - - -void TemplateTable::lastore() { - transition(ltos, vtos); - __ pop_i(rbx); - // rax,: low(value) - // rcx: array - // rdx: high(value) - index_check(rcx, rbx); // prefer index in rbx, - // rbx,: index - __ movptr(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize), rax); - NOT_LP64(__ movl(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize), rdx)); -} - - -void TemplateTable::fastore() { - transition(ftos, vtos); - __ pop_i(rbx); - // rdx: array - // st0: value - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ fstp_s(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT))); -} - - -void TemplateTable::dastore() { - transition(dtos, vtos); - __ pop_i(rbx); - // rdx: array - // st0: value - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ fstp_d(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); -} - - -void TemplateTable::aastore() { - Label is_null, ok_is_subtype, done; - transition(vtos, vtos); - // stack: ..., array, index, value - __ movptr(rax, at_tos()); // Value - __ movl(rcx, at_tos_p1()); // Index - __ movptr(rdx, at_tos_p2()); // Array - - Address element_address(rdx, rcx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - index_check_without_pop(rdx, rcx); // kills rbx, - // do array store check - check for NULL value first - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Move subklass into EBX - __ load_klass(rbx, rax); - // Move superklass into EAX - __ load_klass(rax, rdx); - __ movptr(rax, Address(rax, ObjArrayKlass::element_klass_offset())); - // Compress array+index*wordSize+12 into a single register. Frees ECX. - __ lea(rdx, element_address); - - // Generate subtype check. Blows ECX. Resets EDI to locals. - // Superklass in EAX. Subklass in EBX. - __ gen_subtype_check( rbx, ok_is_subtype ); - - // Come here on failure - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - - // Get the value to store - __ movptr(rax, at_rsp()); - // and store it with appropriate barrier - do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true); - - __ jmp(done); - - // Have a NULL in EAX, EDX=array, ECX=index. Store NULL at ary[idx] - __ bind(is_null); - __ profile_null_seen(rbx); - - // Store NULL, (noreg means NULL to do_oop_store) - do_oop_store(_masm, element_address, noreg, _bs->kind(), true); - - // Pop stack arguments - __ bind(done); - __ addptr(rsp, 3 * Interpreter::stackElementSize); -} - - -void TemplateTable::bastore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rax); -} - - -void TemplateTable::castore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movw(Address(rdx, rbx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), rax); -} - - -void TemplateTable::sastore() { - castore(); -} - - -void TemplateTable::istore(int n) { - transition(itos, vtos); - __ movl(iaddress(n), rax); -} - - -void TemplateTable::lstore(int n) { - transition(ltos, vtos); - __ movptr(laddress(n), rax); - NOT_LP64(__ movptr(haddress(n), rdx)); -} - - -void TemplateTable::fstore(int n) { - transition(ftos, vtos); - __ fstp_s(faddress(n)); -} - - -void TemplateTable::dstore(int n) { - transition(dtos, vtos); - __ fstp_d(daddress(n)); -} - - -void TemplateTable::astore(int n) { - transition(vtos, vtos); - __ pop_ptr(rax); - __ movptr(aaddress(n), rax); -} - - -void TemplateTable::pop() { - transition(vtos, vtos); - __ addptr(rsp, Interpreter::stackElementSize); -} - - -void TemplateTable::pop2() { - transition(vtos, vtos); - __ addptr(rsp, 2*Interpreter::stackElementSize); -} - - -void TemplateTable::dup() { - transition(vtos, vtos); - // stack: ..., a - __ load_ptr(0, rax); - __ push_ptr(rax); - // stack: ..., a, a -} - - -void TemplateTable::dup_x1() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 0, rax); // load b - __ load_ptr( 1, rcx); // load a - __ store_ptr(1, rax); // store b - __ store_ptr(0, rcx); // store a - __ push_ptr(rax); // push b - // stack: ..., b, a, b -} - - -void TemplateTable::dup_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rax); // load c - __ load_ptr( 2, rcx); // load a - __ store_ptr(2, rax); // store c in a - __ push_ptr(rax); // push c - // stack: ..., c, b, c, c - __ load_ptr( 2, rax); // load b - __ store_ptr(2, rcx); // store a in b - // stack: ..., c, a, c, c - __ store_ptr(1, rax); // store b in c - // stack: ..., c, a, b, c -} - - -void TemplateTable::dup2() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr(1, rax); // load a - __ push_ptr(rax); // push a - __ load_ptr(1, rax); // load b - __ push_ptr(rax); // push b - // stack: ..., a, b, a, b -} - - -void TemplateTable::dup2_x1() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rcx); // load c - __ load_ptr( 1, rax); // load b - __ push_ptr(rax); // push b - __ push_ptr(rcx); // push c - // stack: ..., a, b, c, b, c - __ store_ptr(3, rcx); // store c in b - // stack: ..., a, c, c, b, c - __ load_ptr( 4, rcx); // load a - __ store_ptr(2, rcx); // store a in 2nd c - // stack: ..., a, c, a, b, c - __ store_ptr(4, rax); // store b in a - // stack: ..., b, c, a, b, c - // stack: ..., b, c, a, b, c -} - - -void TemplateTable::dup2_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c, d - __ load_ptr( 0, rcx); // load d - __ load_ptr( 1, rax); // load c - __ push_ptr(rax); // push c - __ push_ptr(rcx); // push d - // stack: ..., a, b, c, d, c, d - __ load_ptr( 4, rax); // load b - __ store_ptr(2, rax); // store b in d - __ store_ptr(4, rcx); // store d in b - // stack: ..., a, d, c, b, c, d - __ load_ptr( 5, rcx); // load a - __ load_ptr( 3, rax); // load c - __ store_ptr(3, rcx); // store a in c - __ store_ptr(5, rax); // store c in a - // stack: ..., c, d, a, b, c, d - // stack: ..., c, d, a, b, c, d -} - - -void TemplateTable::swap() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 1, rcx); // load a - __ load_ptr( 0, rax); // load b - __ store_ptr(0, rcx); // store a in b - __ store_ptr(1, rax); // store b in a - // stack: ..., b, a -} - - -void TemplateTable::iop2(Operation op) { - transition(itos, itos); - switch (op) { - case add : __ pop_i(rdx); __ addl (rax, rdx); break; - case sub : __ mov(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break; - case mul : __ pop_i(rdx); __ imull(rax, rdx); break; - case _and : __ pop_i(rdx); __ andl (rax, rdx); break; - case _or : __ pop_i(rdx); __ orl (rax, rdx); break; - case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; - case shl : __ mov(rcx, rax); __ pop_i(rax); __ shll (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - case shr : __ mov(rcx, rax); __ pop_i(rax); __ sarl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - case ushr : __ mov(rcx, rax); __ pop_i(rax); __ shrl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - default : ShouldNotReachHere(); - } -} - - -void TemplateTable::lop2(Operation op) { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - switch (op) { - case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; - case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); - __ mov (rax, rbx); __ mov (rdx, rcx); break; - case _and : __ andl(rax, rbx); __ andl(rdx, rcx); break; - case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; - case _xor : __ xorl(rax, rbx); __ xorl(rdx, rcx); break; - default : ShouldNotReachHere(); - } -} - - -void TemplateTable::idiv() { - transition(itos, itos); - __ mov(rcx, rax); - __ pop_i(rax); - // Note: could xor rax, and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); -} - - -void TemplateTable::irem() { - transition(itos, itos); - __ mov(rcx, rax); - __ pop_i(rax); - // Note: could xor rax, and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); - __ mov(rax, rdx); -} - - -void TemplateTable::lmul() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - __ lmul(2 * wordSize, 0); - __ addptr(rsp, 4 * wordSize); // take off temporaries -} - - -void TemplateTable::ldiv() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - // check if y = 0 - __ orl(rax, rdx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); - __ addptr(rsp, 4 * wordSize); // take off temporaries -} - - -void TemplateTable::lrem() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - // check if y = 0 - __ orl(rax, rdx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); - __ addptr(rsp, 4 * wordSize); -} - - -void TemplateTable::lshl() { - transition(itos, ltos); - __ movl(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshl(rdx, rax); -} - - -void TemplateTable::lshr() { - transition(itos, ltos); - __ mov(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshr(rdx, rax, true); -} - - -void TemplateTable::lushr() { - transition(itos, ltos); - __ mov(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshr(rdx, rax); -} - - -void TemplateTable::fop2(Operation op) { - transition(ftos, ftos); - switch (op) { - case add: __ fadd_s (at_rsp()); break; - case sub: __ fsubr_s(at_rsp()); break; - case mul: __ fmul_s (at_rsp()); break; - case div: __ fdivr_s(at_rsp()); break; - case rem: __ fld_s (at_rsp()); __ fremr(rax); break; - default : ShouldNotReachHere(); - } - __ f2ieee(); - __ pop(rax); // pop float thing off -} - - -void TemplateTable::dop2(Operation op) { - transition(dtos, dtos); - - switch (op) { - case add: __ fadd_d (at_rsp()); break; - case sub: __ fsubr_d(at_rsp()); break; - case mul: { - Label L_strict; - Label L_join; - const Address access_flags (rcx, Method::access_flags_offset()); - __ get_method(rcx); - __ movl(rcx, access_flags); - __ testl(rcx, JVM_ACC_STRICT); - __ jccb(Assembler::notZero, L_strict); - __ fmul_d (at_rsp()); - __ jmpb(L_join); - __ bind(L_strict); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); - __ fmulp(); - __ fmul_d (at_rsp()); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); - __ fmulp(); - __ bind(L_join); - break; - } - case div: { - Label L_strict; - Label L_join; - const Address access_flags (rcx, Method::access_flags_offset()); - __ get_method(rcx); - __ movl(rcx, access_flags); - __ testl(rcx, JVM_ACC_STRICT); - __ jccb(Assembler::notZero, L_strict); - __ fdivr_d(at_rsp()); - __ jmp(L_join); - __ bind(L_strict); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); - __ fmul_d (at_rsp()); - __ fdivrp(); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); - __ fmulp(); - __ bind(L_join); - break; - } - case rem: __ fld_d (at_rsp()); __ fremr(rax); break; - default : ShouldNotReachHere(); - } - __ d2ieee(); - // Pop double precision number from rsp. - __ pop(rax); - __ pop(rdx); -} - - -void TemplateTable::ineg() { - transition(itos, itos); - __ negl(rax); -} - - -void TemplateTable::lneg() { - transition(ltos, ltos); - __ lneg(rdx, rax); -} - - -void TemplateTable::fneg() { - transition(ftos, ftos); - __ fchs(); -} - - -void TemplateTable::dneg() { - transition(dtos, dtos); - __ fchs(); -} - - -void TemplateTable::iinc() { - transition(vtos, vtos); - __ load_signed_byte(rdx, at_bcp(2)); // get constant - locals_index(rbx); - __ addl(iaddress(rbx), rdx); -} - - -void TemplateTable::wide_iinc() { - transition(vtos, vtos); - __ movl(rdx, at_bcp(4)); // get constant - locals_index_wide(rbx); - __ bswapl(rdx); // swap bytes & sign-extend constant - __ sarl(rdx, 16); - __ addl(iaddress(rbx), rdx); - // Note: should probably use only one movl to get both - // the index and the constant -> fix this -} - - -void TemplateTable::convert() { - // Checking -#ifdef ASSERT - { TosState tos_in = ilgl; - TosState tos_out = ilgl; - switch (bytecode()) { - case Bytecodes::_i2l: // fall through - case Bytecodes::_i2f: // fall through - case Bytecodes::_i2d: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_in = itos; break; - case Bytecodes::_l2i: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_l2d: tos_in = ltos; break; - case Bytecodes::_f2i: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_f2d: tos_in = ftos; break; - case Bytecodes::_d2i: // fall through - case Bytecodes::_d2l: // fall through - case Bytecodes::_d2f: tos_in = dtos; break; - default : ShouldNotReachHere(); - } - switch (bytecode()) { - case Bytecodes::_l2i: // fall through - case Bytecodes::_f2i: // fall through - case Bytecodes::_d2i: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_out = itos; break; - case Bytecodes::_i2l: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_d2l: tos_out = ltos; break; - case Bytecodes::_i2f: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_d2f: tos_out = ftos; break; - case Bytecodes::_i2d: // fall through - case Bytecodes::_l2d: // fall through - case Bytecodes::_f2d: tos_out = dtos; break; - default : ShouldNotReachHere(); - } - transition(tos_in, tos_out); - } -#endif // ASSERT - - // Conversion - // (Note: use push(rcx)/pop(rcx) for 1/2-word stack-ptr manipulation) - switch (bytecode()) { - case Bytecodes::_i2l: - __ extend_sign(rdx, rax); - break; - case Bytecodes::_i2f: - __ push(rax); // store int on tos - __ fild_s(at_rsp()); // load int to ST0 - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - break; - case Bytecodes::_i2d: - __ push(rax); // add one slot for d2ieee() - __ push(rax); // store int on tos - __ fild_s(at_rsp()); // load int to ST0 - __ d2ieee(); // truncate to double size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_i2b: - __ shll(rax, 24); // truncate upper 24 bits - __ sarl(rax, 24); // and sign-extend byte - LP64_ONLY(__ movsbl(rax, rax)); - break; - case Bytecodes::_i2c: - __ andl(rax, 0xFFFF); // truncate upper 16 bits - LP64_ONLY(__ movzwl(rax, rax)); - break; - case Bytecodes::_i2s: - __ shll(rax, 16); // truncate upper 16 bits - __ sarl(rax, 16); // and sign-extend short - LP64_ONLY(__ movswl(rax, rax)); - break; - case Bytecodes::_l2i: - /* nothing to do */ - break; - case Bytecodes::_l2f: - __ push(rdx); // store long on tos - __ push(rax); - __ fild_d(at_rsp()); // load long to ST0 - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_l2d: - __ push(rdx); // store long on tos - __ push(rax); - __ fild_d(at_rsp()); // load long to ST0 - __ d2ieee(); // truncate to double size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_f2i: - __ push(rcx); // reserve space for argument - __ fstp_s(at_rsp()); // pass float argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); - break; - case Bytecodes::_f2l: - __ push(rcx); // reserve space for argument - __ fstp_s(at_rsp()); // pass float argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); - break; - case Bytecodes::_f2d: - /* nothing to do */ - break; - case Bytecodes::_d2i: - __ push(rcx); // reserve space for argument - __ push(rcx); - __ fstp_d(at_rsp()); // pass double argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 2); - break; - case Bytecodes::_d2l: - __ push(rcx); // reserve space for argument - __ push(rcx); - __ fstp_d(at_rsp()); // pass double argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 2); - break; - case Bytecodes::_d2f: - __ push(rcx); // reserve space for f2ieee() - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - break; - default : - ShouldNotReachHere(); - } -} - - -void TemplateTable::lcmp() { - transition(ltos, itos); - // y = rdx:rax - __ pop_l(rbx, rcx); // get x = rcx:rbx - __ lcmp2int(rcx, rbx, rdx, rax);// rcx := cmp(x, y) - __ mov(rax, rcx); -} - - -void TemplateTable::float_cmp(bool is_float, int unordered_result) { - if (is_float) { - __ fld_s(at_rsp()); - } else { - __ fld_d(at_rsp()); - __ pop(rdx); - } - __ pop(rcx); - __ fcmp2int(rax, unordered_result < 0); -} - - -void TemplateTable::branch(bool is_jsr, bool is_wide) { - __ get_method(rcx); // ECX holds method - __ profile_taken_branch(rax,rbx); // EAX holds updated MDP, EBX holds bumped taken count - - const ByteSize be_offset = MethodCounters::backedge_counter_offset() + - InvocationCounter::counter_offset(); - const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + - InvocationCounter::counter_offset(); - - // Load up EDX with the branch displacement - if (is_wide) { - __ movl(rdx, at_bcp(1)); - } else { - __ load_signed_short(rdx, at_bcp(1)); - } - __ bswapl(rdx); - if (!is_wide) __ sarl(rdx, 16); - LP64_ONLY(__ movslq(rdx, rdx)); - - - // Handle all the JSR stuff here, then exit. - // It's much shorter and cleaner than intermingling with the - // non-JSR normal-branch stuff occurring below. - if (is_jsr) { - // Pre-load the next target bytecode into EBX - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0)); - - // compute return address as bci in rax, - __ lea(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(ConstMethod::codes_offset()))); - __ subptr(rax, Address(rcx, Method::const_offset())); - // Adjust the bcp in RSI by the displacement in EDX - __ addptr(rsi, rdx); - // Push return address - __ push_i(rax); - // jsr returns vtos - __ dispatch_only_noverify(vtos); - return; - } - - // Normal (non-jsr) branch handling - - // Adjust the bcp in RSI by the displacement in EDX - __ addptr(rsi, rdx); - - assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters"); - Label backedge_counter_overflow; - Label profile_method; - Label dispatch; - if (UseLoopCounter) { - // increment backedge counter for backward branches - // rax,: MDO - // rbx,: MDO bumped taken-count - // rcx: method - // rdx: target offset - // rsi: target bcp - // rdi: locals pointer - __ testl(rdx, rdx); // check if forward or backward branch - __ jcc(Assembler::positive, dispatch); // count only if backward branch - - // check if MethodCounters exists - Label has_counters; - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ testptr(rax, rax); - __ jcc(Assembler::notZero, has_counters); - __ push(rdx); - __ push(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), - rcx); - __ pop(rcx); - __ pop(rdx); - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ testptr(rax, rax); - __ jcc(Assembler::zero, dispatch); - __ bind(has_counters); - - if (TieredCompilation) { - Label no_mdo; - int increment = InvocationCounter::count_increment; - if (ProfileInterpreter) { - // Are we profiling? - __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset()))); - __ testptr(rbx, rbx); - __ jccb(Assembler::zero, no_mdo); - // Increment the MDO backedge counter - const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) + - in_bytes(InvocationCounter::counter_offset())); - const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset())); - __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - __ jmp(dispatch); - } - __ bind(no_mdo); - // Increment backedge counter in MethodCounters* - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); - __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - } else { // not TieredCompilation - // increment counter - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - __ movl(rax, Address(rcx, be_offset)); // load backedge counter - __ incrementl(rax, InvocationCounter::count_increment); // increment counter - __ movl(Address(rcx, be_offset), rax); // store counter - - __ movl(rax, Address(rcx, inv_offset)); // load invocation counter - - __ andl(rax, InvocationCounter::count_mask_value); // and the status bits - __ addl(rax, Address(rcx, be_offset)); // add both counters - - if (ProfileInterpreter) { - // Test to see if we should create a method data oop - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); - __ jcc(Assembler::less, dispatch); - - // if no method data exists, go to profile method - __ test_method_data_pointer(rax, profile_method); - - if (UseOnStackReplacement) { - // check for overflow against rbx, which is the MDO taken count - __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::below, dispatch); - - // When ProfileInterpreter is on, the backedge_count comes from the - // MethodData*, which value does not get reset on the call to - // frequency_counter_overflow(). To avoid excessive calls to the overflow - // routine while the method is being compiled, add a second test to make - // sure the overflow function is called only once every overflow_frequency. - const int overflow_frequency = 1024; - __ andptr(rbx, overflow_frequency-1); - __ jcc(Assembler::zero, backedge_counter_overflow); - } - } else { - if (UseOnStackReplacement) { - // check for overflow against rax, which is the sum of the counters - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::aboveEqual, backedge_counter_overflow); - - } - } - } - __ bind(dispatch); - } - - // Pre-load the next target bytecode into EBX - __ load_unsigned_byte(rbx, Address(rsi, 0)); - - // continue with the bytecode @ target - // rax,: return bci for jsr's, unused otherwise - // rbx,: target bytecode - // rsi: target bcp - __ dispatch_only(vtos); - - if (UseLoopCounter) { - if (ProfileInterpreter) { - // Out-of-line code to allocate method data oop. - __ bind(profile_method); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); - __ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode - __ set_method_data_pointer_for_bcp(); - __ jmp(dispatch); - } - - if (UseOnStackReplacement) { - - // invocation counter overflow - __ bind(backedge_counter_overflow); - __ negptr(rdx); - __ addptr(rdx, rsi); // branch bcp - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx); - __ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode - - // rax,: osr nmethod (osr ok) or NULL (osr not possible) - // rbx,: target bytecode - // rdx: scratch - // rdi: locals pointer - // rsi: bcp - __ testptr(rax, rax); // test result - __ jcc(Assembler::zero, dispatch); // no osr if null - // nmethod may have been invalidated (VM may block upon call_VM return) - __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use); - __ jcc(Assembler::notEqual, dispatch); - - // We have the address of an on stack replacement routine in rax, - // We need to prepare to execute the OSR method. First we must - // migrate the locals and monitors off of the stack. - - __ mov(rbx, rax); // save the nmethod - - __ get_thread(rcx); - call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); - // rax, is OSR buffer, move it to expected parameter location - __ mov(rcx, rax); - - // pop the interpreter frame - __ movptr(rdx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp - __ leave(); // remove frame anchor - __ pop(rdi); // get return address - __ mov(rsp, rdx); // set sp to sender sp - - // Align stack pointer for compiled code (note that caller is - // responsible for undoing this fixup by remembering the old SP - // in an rbp,-relative location) - __ andptr(rsp, -(StackAlignmentInBytes)); - - // push the (possibly adjusted) return address - __ push(rdi); - - // and begin the OSR nmethod - __ jmp(Address(rbx, nmethod::osr_entry_point_offset())); - } - } -} - - -void TemplateTable::if_0cmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testl(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_icmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_i(rdx); - __ cmpl(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_nullcmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testptr(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_acmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_ptr(rdx); - __ cmpptr(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::ret() { - transition(vtos, vtos); - locals_index(rbx); - __ movptr(rbx, iaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(rsi, Address(rax, Method::const_offset())); - __ lea(rsi, Address(rsi, rbx, Address::times_1, - ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - - -void TemplateTable::wide_ret() { - transition(vtos, vtos); - locals_index_wide(rbx); - __ movptr(rbx, iaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(rsi, Address(rax, Method::const_offset())); - __ lea(rsi, Address(rsi, rbx, Address::times_1, ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - - -void TemplateTable::tableswitch() { - Label default_case, continue_execution; - transition(itos, vtos); - // align rsi - __ lea(rbx, at_bcp(wordSize)); - __ andptr(rbx, -wordSize); - // load lo & hi - __ movl(rcx, Address(rbx, 1 * wordSize)); - __ movl(rdx, Address(rbx, 2 * wordSize)); - __ bswapl(rcx); - __ bswapl(rdx); - // check against lo & hi - __ cmpl(rax, rcx); - __ jccb(Assembler::less, default_case); - __ cmpl(rax, rdx); - __ jccb(Assembler::greater, default_case); - // lookup dispatch offset - __ subl(rax, rcx); - __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt)); - __ profile_switch_case(rax, rbx, rcx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1)); - __ addptr(rsi, rdx); - __ dispatch_only(vtos); - // handle default - __ bind(default_case); - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmp(continue_execution); -} - - -void TemplateTable::lookupswitch() { - transition(itos, itos); - __ stop("lookupswitch bytecode should have been rewritten"); -} - - -void TemplateTable::fast_linearswitch() { - transition(itos, vtos); - Label loop_entry, loop, found, continue_execution; - // bswapl rax, so we can avoid bswapping the table entries - __ bswapl(rax); - // align rsi - __ lea(rbx, at_bcp(wordSize)); // btw: should be able to get rid of this instruction (change offsets below) - __ andptr(rbx, -wordSize); - // set counter - __ movl(rcx, Address(rbx, wordSize)); - __ bswapl(rcx); - __ jmpb(loop_entry); - // table search - __ bind(loop); - __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * wordSize)); - __ jccb(Assembler::equal, found); - __ bind(loop_entry); - __ decrementl(rcx); - __ jcc(Assembler::greaterEqual, loop); - // default case - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmpb(continue_execution); - // entry found -> get offset - __ bind(found); - __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * wordSize)); - __ profile_switch_case(rcx, rax, rbx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1)); - __ addptr(rsi, rdx); - __ dispatch_only(vtos); -} - - -void TemplateTable::fast_binaryswitch() { - transition(itos, vtos); - // Implementation using the following core algorithm: - // - // int binary_search(int key, LookupswitchPair* array, int n) { - // // Binary search according to "Methodik des Programmierens" by - // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. - // int i = 0; - // int j = n; - // while (i+1 < j) { - // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) - // // with Q: for all i: 0 <= i < n: key < a[i] - // // where a stands for the array and assuming that the (inexisting) - // // element a[n] is infinitely big. - // int h = (i + j) >> 1; - // // i < h < j - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // } - // // R: a[i] <= key < a[i+1] or Q - // // (i.e., if key is within array, i is the correct index) - // return i; - // } - - // register allocation - const Register key = rax; // already set (tosca) - const Register array = rbx; - const Register i = rcx; - const Register j = rdx; - const Register h = rdi; // needs to be restored - const Register temp = rsi; - // setup array - __ save_bcp(); - - __ lea(array, at_bcp(3*wordSize)); // btw: should be able to get rid of this instruction (change offsets below) - __ andptr(array, -wordSize); - // initialize i & j - __ xorl(i, i); // i = 0; - __ movl(j, Address(array, -wordSize)); // j = length(array); - // Convert j into native byteordering - __ bswapl(j); - // and start - Label entry; - __ jmp(entry); - - // binary search loop - { Label loop; - __ bind(loop); - // int h = (i + j) >> 1; - __ leal(h, Address(i, j, Address::times_1)); // h = i + j; - __ sarl(h, 1); // h = (i + j) >> 1; - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // Convert array[h].match to native byte-ordering before compare - __ movl(temp, Address(array, h, Address::times_8, 0*wordSize)); - __ bswapl(temp); - __ cmpl(key, temp); - // j = h if (key < array[h].fast_match()) - __ cmov32(Assembler::less , j, h); - // i = h if (key >= array[h].fast_match()) - __ cmov32(Assembler::greaterEqual, i, h); - // while (i+1 < j) - __ bind(entry); - __ leal(h, Address(i, 1)); // i+1 - __ cmpl(h, j); // i+1 < j - __ jcc(Assembler::less, loop); - } - - // end of binary search, result index is i (must check again!) - Label default_case; - // Convert array[i].match to native byte-ordering before compare - __ movl(temp, Address(array, i, Address::times_8, 0*wordSize)); - __ bswapl(temp); - __ cmpl(key, temp); - __ jcc(Assembler::notEqual, default_case); - - // entry found -> j = offset - __ movl(j , Address(array, i, Address::times_8, 1*wordSize)); - __ profile_switch_case(i, key, array); - __ bswapl(j); - LP64_ONLY(__ movslq(j, j)); - __ restore_bcp(); - __ restore_locals(); // restore rdi - __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1)); - - __ addptr(rsi, j); - __ dispatch_only(vtos); - - // default case -> j = default offset - __ bind(default_case); - __ profile_switch_default(i); - __ movl(j, Address(array, -2*wordSize)); - __ bswapl(j); - LP64_ONLY(__ movslq(j, j)); - __ restore_bcp(); - __ restore_locals(); // restore rdi - __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1)); - __ addptr(rsi, j); - __ dispatch_only(vtos); -} - - -void TemplateTable::_return(TosState state) { - transition(state, state); - assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation - - if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { - assert(state == vtos, "only valid state"); - __ movptr(rax, aaddress(0)); - __ load_klass(rdi, rax); - __ movl(rdi, Address(rdi, Klass::access_flags_offset())); - __ testl(rdi, JVM_ACC_HAS_FINALIZER); - Label skip_register_finalizer; - __ jcc(Assembler::zero, skip_register_finalizer); - - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), rax); - - __ bind(skip_register_finalizer); - } - - __ remove_activation(state, rsi); - __ jmp(rsi); -} - - -// ---------------------------------------------------------------------------- -// Volatile variables demand their effects be made known to all CPU's in -// order. Store buffers on most chips allow reads & writes to reorder; the -// JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of -// memory barrier (i.e., it's not sufficient that the interpreter does not -// reorder volatile references, the hardware also must not reorder them). -// -// According to the new Java Memory Model (JMM): -// (1) All volatiles are serialized wrt to each other. -// ALSO reads & writes act as aquire & release, so: -// (2) A read cannot let unrelated NON-volatile memory refs that happen after -// the read float up to before the read. It's OK for non-volatile memory refs -// that happen before the volatile read to float down below it. -// (3) Similar a volatile write cannot let unrelated NON-volatile memory refs -// that happen BEFORE the write float down to after the write. It's OK for -// non-volatile memory refs that happen after the volatile write to float up -// before it. -// -// We only put in barriers around volatile refs (they are expensive), not -// _between_ memory refs (that would require us to track the flavor of the -// previous memory refs). Requirements (2) and (3) require some barriers -// before volatile stores and after volatile loads. These nearly cover -// requirement (1) but miss the volatile-store-volatile-load case. This final -// case is placed after volatile-stores although it could just as well go -// before volatile-loads. -void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint ) { - // Helper function to insert a is-volatile test and memory barrier - if( !os::is_MP() ) return; // Not needed on single CPU - __ membar(order_constraint); -} - -void TemplateTable::resolve_cache_and_index(int byte_no, - Register Rcache, - Register index, - size_t index_size) { - const Register temp = rbx; - assert_different_registers(Rcache, index, temp); - - Label resolved; - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); - __ cmpl(temp, (int) bytecode()); // have we resolved this bytecode? - __ jcc(Assembler::equal, resolved); - - // resolve first time through - address entry; - switch (bytecode()) { - case Bytecodes::_getstatic : // fall through - case Bytecodes::_putstatic : // fall through - case Bytecodes::_getfield : // fall through - case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; - case Bytecodes::_invokevirtual : // fall through - case Bytecodes::_invokespecial : // fall through - case Bytecodes::_invokestatic : // fall through - case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; - case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break; - case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; - default: - fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); - break; - } - __ movl(temp, (int)bytecode()); - __ call_VM(noreg, entry, temp); - // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); - __ bind(resolved); -} - - -// The cache and index registers must be set before call -void TemplateTable::load_field_cp_cache_entry(Register obj, - Register cache, - Register index, - Register off, - Register flags, - bool is_static = false) { - assert_different_registers(cache, index, flags, off); - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - // Field offset - __ movptr(off, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()))); - // Flags - __ movl(flags, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()))); - - // klass overwrite register - if (is_static) { - __ movptr(obj, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset()))); - const int mirror_offset = in_bytes(Klass::java_mirror_offset()); - __ movptr(obj, Address(obj, mirror_offset)); - } -} - -void TemplateTable::load_invoke_cp_cache_entry(int byte_no, - Register method, - Register itable_index, - Register flags, - bool is_invokevirtual, - bool is_invokevfinal, /*unused*/ - bool is_invokedynamic) { - // setup registers - const Register cache = rcx; - const Register index = rdx; - assert_different_registers(method, flags); - assert_different_registers(method, cache, index); - assert_different_registers(itable_index, flags); - assert_different_registers(itable_index, cache, index); - // determine constant pool cache field offsets - assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); - const int method_offset = in_bytes( - ConstantPoolCache::base_offset() + - ((byte_no == f2_byte) - ? ConstantPoolCacheEntry::f2_offset() - : ConstantPoolCacheEntry::f1_offset())); - const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset()); - // access constant pool cache fields - const int index_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset()); - - size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); - resolve_cache_and_index(byte_no, cache, index, index_size); - __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); - - if (itable_index != noreg) { - __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); - } - __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); -} - - -// The registers cache and index expected to be set before call. -// Correct values of the cache and index registers are preserved. -void TemplateTable::jvmti_post_field_access(Register cache, - Register index, - bool is_static, - bool has_tos) { - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we take - // the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rax,rax); - __ jcc(Assembler::zero, L1); - - // cache entry pointer - __ addptr(cache, in_bytes(ConstantPoolCache::base_offset())); - __ shll(index, LogBytesPerWord); - __ addptr(cache, index); - if (is_static) { - __ xorptr(rax, rax); // NULL object reference - } else { - __ pop(atos); // Get the object - __ verify_oop(rax); - __ push(atos); // Restore stack state - } - // rax,: object pointer or NULL - // cache: cache entry pointer - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), - rax, cache); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - -void TemplateTable::pop_and_check_object(Register r) { - __ pop_ptr(r); - __ null_check(r); // for field access must check obj. - __ verify_oop(r); -} - -void TemplateTable::getfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = rcx; - const Register off = rbx; - const Register flags = rax; - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_access(cache, index, is_static, false); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - if (!is_static) pop_and_check_object(obj); - - const Address lo(obj, off, Address::times_1, 0*wordSize); - const Address hi(obj, off, Address::times_1, 1*wordSize); - - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - assert(btos == 0, "change code, btos != 0"); - // btos - __ andptr(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - - __ load_signed_byte(rax, lo ); - __ push(btos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notByte); - // itos - __ cmpl(flags, itos ); - __ jcc(Assembler::notEqual, notInt); - - __ movl(rax, lo ); - __ push(itos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_igetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notInt); - // atos - __ cmpl(flags, atos ); - __ jcc(Assembler::notEqual, notObj); - - __ movl(rax, lo ); - __ push(atos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_agetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notObj); - // ctos - __ cmpl(flags, ctos ); - __ jcc(Assembler::notEqual, notChar); - - __ load_unsigned_short(rax, lo ); - __ push(ctos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notChar); - // stos - __ cmpl(flags, stos ); - __ jcc(Assembler::notEqual, notShort); - - __ load_signed_short(rax, lo ); - __ push(stos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notShort); - // ltos - __ cmpl(flags, ltos ); - __ jcc(Assembler::notEqual, notLong); - - // Generate code as if volatile. There just aren't enough registers to - // save that information and this code is faster than the test. - __ fild_d(lo); // Must load atomically - __ subptr(rsp,2*wordSize); // Make space for store - __ fistp_d(Address(rsp,0)); - __ pop(rax); - __ pop(rdx); - - __ push(ltos); - // Don't rewrite to _fast_lgetfield for potential volatile case. - __ jmp(Done); - - __ bind(notLong); - // ftos - __ cmpl(flags, ftos ); - __ jcc(Assembler::notEqual, notFloat); - - __ fld_s(lo); - __ push(ftos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notFloat); - // dtos - __ cmpl(flags, dtos ); - __ jcc(Assembler::notEqual, notDouble); - - __ fld_d(lo); - __ push(dtos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dgetfield, rcx, rbx); - } - __ jmpb(Done); - - __ bind(notDouble); - - __ stop("Bad state"); - - __ bind(Done); - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); -} - - -void TemplateTable::getfield(int byte_no) { - getfield_or_static(byte_no, false); -} - - -void TemplateTable::getstatic(int byte_no) { - getfield_or_static(byte_no, true); -} - -// The registers cache and index expected to be set before call. -// The function may destroy various registers, just not the cache and index registers. -void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before we take - // the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rax, rax); - __ jcc(Assembler::zero, L1); - - // The cache and index registers have been already set. - // This allows to eliminate this call but the cache and index - // registers have to be correspondingly used after this line. - __ get_cache_and_index_at_bcp(rax, rdx, 1); - - if (is_static) { - // Life is simple. Null out the object pointer. - __ xorptr(rbx, rbx); - } else { - // Life is harder. The stack holds the value on top, followed by the object. - // We don't know the size of the value, though; it could be one or two words - // depending on its type. As a result, we must find the type to determine where - // the object is. - Label two_word, valsize_known; - __ movl(rcx, Address(rax, rdx, Address::times_ptr, in_bytes(cp_base_offset + - ConstantPoolCacheEntry::flags_offset()))); - __ mov(rbx, rsp); - __ shrl(rcx, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask rcx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ cmpl(rcx, ltos); - __ jccb(Assembler::equal, two_word); - __ cmpl(rcx, dtos); - __ jccb(Assembler::equal, two_word); - __ addptr(rbx, Interpreter::expr_offset_in_bytes(1)); // one word jvalue (not ltos, dtos) - __ jmpb(valsize_known); - - __ bind(two_word); - __ addptr(rbx, Interpreter::expr_offset_in_bytes(2)); // two words jvalue - - __ bind(valsize_known); - // setup object pointer - __ movptr(rbx, Address(rbx, 0)); - } - // cache entry pointer - __ addptr(rax, in_bytes(cp_base_offset)); - __ shll(rdx, LogBytesPerWord); - __ addptr(rax, rdx); - // object (tos) - __ mov(rcx, rsp); - // rbx,: object pointer set up above (NULL if static) - // rax,: cache entry pointer - // rcx: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), - rbx, rax, rcx); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - - -void TemplateTable::putfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = rcx; - const Register off = rbx; - const Register flags = rax; - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_mod(cache, index, is_static); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); - - Label notVolatile, Done; - __ movl(rdx, flags); - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - - // field addresses - const Address lo(obj, off, Address::times_1, 0*wordSize); - const Address hi(obj, off, Address::times_1, 1*wordSize); - - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - assert(btos == 0, "change code, btos != 0"); - __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - - // btos - { - __ pop(btos); - if (!is_static) pop_and_check_object(obj); - __ movb(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notByte); - __ cmpl(flags, itos); - __ jcc(Assembler::notEqual, notInt); - - // itos - { - __ pop(itos); - if (!is_static) pop_and_check_object(obj); - __ movl(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_iputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notInt); - __ cmpl(flags, atos); - __ jcc(Assembler::notEqual, notObj); - - // atos - { - __ pop(atos); - if (!is_static) pop_and_check_object(obj); - do_oop_store(_masm, lo, rax, _bs->kind(), false); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notObj); - __ cmpl(flags, ctos); - __ jcc(Assembler::notEqual, notChar); - - // ctos - { - __ pop(ctos); - if (!is_static) pop_and_check_object(obj); - __ movw(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notChar); - __ cmpl(flags, stos); - __ jcc(Assembler::notEqual, notShort); - - // stos - { - __ pop(stos); - if (!is_static) pop_and_check_object(obj); - __ movw(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notShort); - __ cmpl(flags, ltos); - __ jcc(Assembler::notEqual, notLong); - - // ltos - { - Label notVolatileLong; - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatileLong); - - __ pop(ltos); // overwrites rdx, do this after testing volatile. - if (!is_static) pop_and_check_object(obj); - - // Replace with real volatile test - __ push(rdx); - __ push(rax); // Must update atomically with FIST - __ fild_d(Address(rsp,0)); // So load into FPU register - __ fistp_d(lo); // and put into memory atomically - __ addptr(rsp, 2*wordSize); - // volatile_barrier(); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - // Don't rewrite volatile version - __ jmp(notVolatile); - - __ bind(notVolatileLong); - - __ pop(ltos); // overwrites rdx - if (!is_static) pop_and_check_object(obj); - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_lputfield, rcx, rbx, true, byte_no); - } - __ jmp(notVolatile); - } - - __ bind(notLong); - __ cmpl(flags, ftos); - __ jcc(Assembler::notEqual, notFloat); - - // ftos - { - __ pop(ftos); - if (!is_static) pop_and_check_object(obj); - __ fstp_s(lo); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notFloat); -#ifdef ASSERT - __ cmpl(flags, dtos); - __ jcc(Assembler::notEqual, notDouble); -#endif - - // dtos - { - __ pop(dtos); - if (!is_static) pop_and_check_object(obj); - __ fstp_d(lo); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - -#ifdef ASSERT - __ bind(notDouble); - __ stop("Bad state"); -#endif - - __ bind(Done); - - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - __ bind(notVolatile); -} - - -void TemplateTable::putfield(int byte_no) { - putfield_or_static(byte_no, false); -} - - -void TemplateTable::putstatic(int byte_no) { - putfield_or_static(byte_no, true); -} - -void TemplateTable::jvmti_post_fast_field_mod() { - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before we take - // the time to call into the VM. - Label L2; - __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rcx,rcx); - __ jcc(Assembler::zero, L2); - __ pop_ptr(rbx); // copy the object pointer from tos - __ verify_oop(rbx); - __ push_ptr(rbx); // put the object pointer back on tos - - // Save tos values before call_VM() clobbers them. Since we have - // to do it for every data type, we use the saved values as the - // jvalue object. - switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ push_i(rax); break; - case Bytecodes::_fast_dputfield: __ push_d(); break; - case Bytecodes::_fast_fputfield: __ push_f(); break; - case Bytecodes::_fast_lputfield: __ push_l(rax); break; - - default: - ShouldNotReachHere(); - } - __ mov(rcx, rsp); // points to jvalue on the stack - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(rax, rdx, 1); - __ verify_oop(rbx); - // rbx,: object pointer copied above - // rax,: cache entry pointer - // rcx: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx); - - switch (bytecode()) { // restore tos values - case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ pop_i(rax); break; - case Bytecodes::_fast_dputfield: __ pop_d(); break; - case Bytecodes::_fast_fputfield: __ pop_f(); break; - case Bytecodes::_fast_lputfield: __ pop_l(rax); break; - } - __ bind(L2); - } -} - -void TemplateTable::fast_storefield(TosState state) { - transition(state, vtos); - - ByteSize base = ConstantPoolCache::base_offset(); - - jvmti_post_fast_field_mod(); - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - - // test for volatile with rdx but rdx is tos register for lputfield. - if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx); - __ movl(rdx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + - ConstantPoolCacheEntry::flags_offset()))); - - // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); - - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); - - Label notVolatile, Done; - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - - if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx); - - // Get object from stack - pop_and_check_object(rcx); - - // field addresses - const Address lo(rcx, rbx, Address::times_1, 0*wordSize); - const Address hi(rcx, rbx, Address::times_1, 1*wordSize); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; - case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; - case Bytecodes::_fast_lputfield: - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - break; - case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; - case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; - case Bytecodes::_fast_aputfield: { - do_oop_store(_masm, lo, rax, _bs->kind(), false); - break; - } - default: - ShouldNotReachHere(); - } - - Label done; - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - // Barriers are so large that short branch doesn't reach! - __ jmp(done); - - // Same code as above, but don't need rdx to test for volatile. - __ bind(notVolatile); - - if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx); - - // Get object from stack - pop_and_check_object(rcx); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; - case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; - case Bytecodes::_fast_lputfield: - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - break; - case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; - case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; - case Bytecodes::_fast_aputfield: { - do_oop_store(_masm, lo, rax, _bs->kind(), false); - break; - } - default: - ShouldNotReachHere(); - } - __ bind(done); -} - - -void TemplateTable::fast_accessfield(TosState state) { - transition(atos, state); - - // do the JVMTI work here to avoid disturbing the register state below - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we take - // the time to call into the VM. - Label L1; - __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rcx,rcx); - __ jcc(Assembler::zero, L1); - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(rcx, rdx, 1); - __ push_ptr(rax); // save object pointer before call_VM() clobbers it - __ verify_oop(rax); - // rax,: object pointer copied above - // rcx: cache entry pointer - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), rax, rcx); - __ pop_ptr(rax); // restore object pointer - __ bind(L1); - } - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, - rbx, - Address::times_ptr, - in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); - - - // rax,: object - __ verify_oop(rax); - __ null_check(rax); - // field addresses - const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize); - const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break; - case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo ); break; - case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo ); break; - case Bytecodes::_fast_igetfield: __ movl(rax, lo); break; - case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break; - case Bytecodes::_fast_fgetfield: __ fld_s(lo); break; - case Bytecodes::_fast_dgetfield: __ fld_d(lo); break; - case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break; - default: - ShouldNotReachHere(); - } - - // Doug Lea believes this is not needed with current Sparcs(TSO) and Intel(PSO) - // volatile_barrier( ); -} - -void TemplateTable::fast_xaccess(TosState state) { - transition(vtos, state); - // get receiver - __ movptr(rax, aaddress(0)); - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rdx, 2); - __ movptr(rbx, Address(rcx, - rdx, - Address::times_ptr, - in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); - // make sure exception is reported in correct bcp range (getfield is next instruction) - __ increment(rsi); - __ null_check(rax); - const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize); - if (state == itos) { - __ movl(rax, lo); - } else if (state == atos) { - __ movptr(rax, lo); - __ verify_oop(rax); - } else if (state == ftos) { - __ fld_s(lo); - } else { - ShouldNotReachHere(); - } - __ decrement(rsi); -} - - - -//---------------------------------------------------------------------------------------------------- -// Calls - -void TemplateTable::count_calls(Register method, Register temp) { - // implemented elsewhere - ShouldNotReachHere(); -} - - -void TemplateTable::prepare_invoke(int byte_no, - Register method, // linked method (or i-klass) - Register index, // itable index, MethodType, etc. - Register recv, // if caller wants to see it - Register flags // if caller wants to test it - ) { - // determine flags - const Bytecodes::Code code = bytecode(); - const bool is_invokeinterface = code == Bytecodes::_invokeinterface; - const bool is_invokedynamic = code == Bytecodes::_invokedynamic; - const bool is_invokehandle = code == Bytecodes::_invokehandle; - const bool is_invokevirtual = code == Bytecodes::_invokevirtual; - const bool is_invokespecial = code == Bytecodes::_invokespecial; - const bool load_receiver = (recv != noreg); - const bool save_flags = (flags != noreg); - assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); - assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); - assert(flags == noreg || flags == rdx, ""); - assert(recv == noreg || recv == rcx, ""); - - // setup registers & access constant pool cache - if (recv == noreg) recv = rcx; - if (flags == noreg) flags = rdx; - assert_different_registers(method, index, recv, flags); - - // save 'interpreter return address' - __ save_bcp(); - - load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); - - // maybe push appendix to arguments (just before return address) - if (is_invokedynamic || is_invokehandle) { - Label L_no_push; - __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift)); - __ jccb(Assembler::zero, L_no_push); - // Push the appendix as a trailing parameter. - // This must be done before we get the receiver, - // since the parameter_size includes it. - __ push(rbx); - __ mov(rbx, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); - __ load_resolved_reference_at_index(index, rbx); - __ pop(rbx); - __ push(index); // push appendix (MethodType, CallSite, etc.) - __ bind(L_no_push); - } - - // load receiver if needed (note: no return address pushed yet) - if (load_receiver) { - __ movl(recv, flags); - __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask); - const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address - const int receiver_is_at_end = -1; // back off one slot to get receiver - Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end); - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } - - if (save_flags) { - __ mov(rsi, flags); - } - - // compute return type - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask flags after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - // load return address - { - const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); - ExternalAddress table(table_addr); - __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))); - } - - // push return address - __ push(flags); - - // Restore flags value from the constant pool cache, and restore rsi - // for later null checks. rsi is the bytecode pointer - if (save_flags) { - __ mov(flags, rsi); - __ restore_bcp(); - } -} - - -void TemplateTable::invokevirtual_helper(Register index, - Register recv, - Register flags) { - // Uses temporary registers rax, rdx - assert_different_registers(index, recv, rax, rdx); - assert(index == rbx, ""); - assert(recv == rcx, ""); - - // Test for an invoke of a final method - Label notFinal; - __ movl(rax, flags); - __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); - __ jcc(Assembler::zero, notFinal); - - const Register method = index; // method must be rbx - assert(method == rbx, - "Method* must be rbx for interpreter calling convention"); - - // do the call - the index is actually the method to call - // that is, f2 is a vtable index if !is_vfinal, else f2 is a Method* - - // It's final, need a null check here! - __ null_check(recv); - - // profile this call - __ profile_final_call(rax); - __ profile_arguments_type(rax, method, rsi, true); - - __ jump_from_interpreted(method, rax); - - __ bind(notFinal); - - // get receiver klass - __ null_check(recv, oopDesc::klass_offset_in_bytes()); - __ load_klass(rax, recv); - - // profile this call - __ profile_virtual_call(rax, rdi, rdx); - - // get target Method* & entry point - __ lookup_virtual_method(rax, index, method); - __ profile_arguments_type(rdx, method, rsi, true); - __ jump_from_interpreted(method, rdx); -} - - -void TemplateTable::invokevirtual(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - prepare_invoke(byte_no, - rbx, // method or vtable index - noreg, // unused itable index - rcx, rdx); // recv, flags - - // rbx: index - // rcx: receiver - // rdx: flags - - invokevirtual_helper(rbx, rcx, rdx); -} - - -void TemplateTable::invokespecial(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx, noreg, // get f1 Method* - rcx); // get receiver also for null check - __ verify_oop(rcx); - __ null_check(rcx); - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, rsi, false); - __ jump_from_interpreted(rbx, rax); -} - - -void TemplateTable::invokestatic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx); // get f1 Method* - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, rsi, false); - __ jump_from_interpreted(rbx, rax); -} - - -void TemplateTable::fast_invokevfinal(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - __ stop("fast_invokevfinal not used on x86"); -} - - -void TemplateTable::invokeinterface(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index - rcx, rdx); // recv, flags - - // rax: interface klass (from f1) - // rbx: itable index (from f2) - // rcx: receiver - // rdx: flags - - // Special case of invokeinterface called for virtual method of - // java.lang.Object. See cpCacheOop.cpp for details. - // This code isn't produced by javac, but could be produced by - // another compliant java compiler. - Label notMethod; - __ movl(rdi, rdx); - __ andl(rdi, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); - __ jcc(Assembler::zero, notMethod); - - invokevirtual_helper(rbx, rcx, rdx); - __ bind(notMethod); - - // Get receiver klass into rdx - also a null check - __ restore_locals(); // restore rdi - __ null_check(rcx, oopDesc::klass_offset_in_bytes()); - __ load_klass(rdx, rcx); - - // profile this call - __ profile_virtual_call(rdx, rsi, rdi); - - Label no_such_interface, no_such_method; - - __ lookup_interface_method(// inputs: rec. class, interface, itable index - rdx, rax, rbx, - // outputs: method, scan temp. reg - rbx, rsi, - no_such_interface); - - // rbx: Method* to call - // rcx: receiver - // Check for abstract method error - // Note: This should be done more efficiently via a throw_abstract_method_error - // interpreter entry point and a conditional jump to it in case of a null - // method. - __ testptr(rbx, rbx); - __ jcc(Assembler::zero, no_such_method); - - __ profile_arguments_type(rdx, rbx, rsi, true); - - // do the call - // rcx: receiver - // rbx,: Method* - __ jump_from_interpreted(rbx, rdx); - __ should_not_reach_here(); - - // exception handling code follows... - // note: must restore interpreter registers to canonical - // state for exception handling to work correctly! - - __ bind(no_such_method); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - __ bind(no_such_interface); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_IncompatibleClassChangeError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); -} - -void TemplateTable::invokehandle(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - const Register rbx_method = rbx; - const Register rax_mtype = rax; - const Register rcx_recv = rcx; - const Register rdx_flags = rdx; - - prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv); - __ verify_method_ptr(rbx_method); - __ verify_oop(rcx_recv); - __ null_check(rcx_recv); - - // rax: MethodType object (from cpool->resolved_references[f1], if necessary) - // rbx: MH.invokeExact_MT method (from f2) - - // Note: rax_mtype is already pushed (if necessary) by prepare_invoke - - // FIXME: profile the LambdaForm also - __ profile_final_call(rax); - __ profile_arguments_type(rdx, rbx_method, rsi, true); - - __ jump_from_interpreted(rbx_method, rdx); -} - - -void TemplateTable::invokedynamic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - - const Register rbx_method = rbx; - const Register rax_callsite = rax; - - prepare_invoke(byte_no, rbx_method, rax_callsite); - - // rax: CallSite object (from cpool->resolved_references[f1]) - // rbx: MH.linkToCallSite method (from f2) - - // Note: rax_callsite is already pushed by prepare_invoke - - // %%% should make a type profile for any invokedynamic that takes a ref argument - // profile this call - __ profile_call(rsi); - __ profile_arguments_type(rdx, rbx, rsi, false); - - __ verify_oop(rax_callsite); - - __ jump_from_interpreted(rbx_method, rdx); -} - -//---------------------------------------------------------------------------------------------------- -// Allocation - -void TemplateTable::_new() { - transition(vtos, atos); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - Label slow_case; - Label slow_case_no_pop; - Label done; - Label initialize_header; - Label initialize_object; // including clearing the fields - Label allocate_shared; - - __ get_cpool_and_tags(rcx, rax); - - // Make sure the class we're about to instantiate has been resolved. - // This is done before loading InstanceKlass to be consistent with the order - // how Constant Pool is updated (see ConstantPool::klass_at_put) - const int tags_offset = Array::base_offset_in_bytes(); - __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, slow_case_no_pop); - - // get InstanceKlass - __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); - __ push(rcx); // save the contexts of klass for initializing the header - - // make sure klass is initialized & doesn't have finalizer - // make sure klass is fully initialized - __ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized); - __ jcc(Assembler::notEqual, slow_case); - - // get instance_size in InstanceKlass (scaled to a count of bytes) - __ movl(rdx, Address(rcx, Klass::layout_helper_offset())); - // test to see if it has a finalizer or is malformed in some way - __ testl(rdx, Klass::_lh_instance_slow_path_bit); - __ jcc(Assembler::notZero, slow_case); - - // - // Allocate the instance - // 1) Try to allocate in the TLAB - // 2) if fail and the object is large allocate in the shared Eden - // 3) if the above fails (or is not applicable), go to a slow case - // (creates a new TLAB, etc.) - - const bool allow_shared_alloc = - Universe::heap()->supports_inline_contig_alloc(); - - const Register thread = rcx; - if (UseTLAB || allow_shared_alloc) { - __ get_thread(thread); - } - - if (UseTLAB) { - __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); - __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case); - __ movptr(Address(thread, in_bytes(JavaThread::tlab_top_offset())), rbx); - if (ZeroTLAB) { - // the fields have been already cleared - __ jmp(initialize_header); - } else { - // initialize both the header and fields - __ jmp(initialize_object); - } - } - - // Allocation in the shared Eden, if allowed. - // - // rdx: instance size in bytes - if (allow_shared_alloc) { - __ bind(allocate_shared); - - ExternalAddress heap_top((address)Universe::heap()->top_addr()); - - Label retry; - __ bind(retry); - __ movptr(rax, heap_top); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, ExternalAddress((address)Universe::heap()->end_addr())); - __ jcc(Assembler::above, slow_case); - - // Compare rax, with the top addr, and if still equal, store the new - // top addr in rbx, at the address of the top addr pointer. Sets ZF if was - // equal, and clears it otherwise. Use lock prefix for atomicity on MPs. - // - // rax,: object begin - // rbx,: object end - // rdx: instance size in bytes - __ locked_cmpxchgptr(rbx, heap_top); - - // if someone beat us on the allocation, try again, otherwise continue - __ jcc(Assembler::notEqual, retry); - - __ incr_allocated_bytes(thread, rdx, 0); - } - - if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { - // The object is initialized before the header. If the object size is - // zero, go directly to the header initialization. - __ bind(initialize_object); - __ decrement(rdx, sizeof(oopDesc)); - __ jcc(Assembler::zero, initialize_header); - - // Initialize topmost object field, divide rdx by 8, check if odd and - // test if zero. - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd - - // rdx must have been multiple of 8 -#ifdef ASSERT - // make sure rdx was multiple of 8 - Label L; - // Ignore partial flag stall after shrl() since it is debug VM - __ jccb(Assembler::carryClear, L); - __ stop("object size is not multiple of 2 - adjust this code"); - __ bind(L); - // rdx must be > 0, no extra check needed here -#endif - - // initialize remaining object fields: rdx was a multiple of 8 - { Label loop; - __ bind(loop); - __ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 1*oopSize), rcx); - NOT_LP64(__ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 2*oopSize), rcx)); - __ decrement(rdx); - __ jcc(Assembler::notZero, loop); - } - - // initialize object header only. - __ bind(initialize_header); - if (UseBiasedLocking) { - __ pop(rcx); // get saved klass back in the register. - __ movptr(rbx, Address(rcx, Klass::prototype_header_offset())); - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), rbx); - } else { - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), - (int32_t)markOopDesc::prototype()); // header - __ pop(rcx); // get saved klass back in the register. - } - __ store_klass(rax, rcx); // klass - - { - SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0); - // Trigger dtrace event for fastpath - __ push(atos); - __ call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); - __ pop(atos); - } - - __ jmp(done); - } - - // slow case - __ bind(slow_case); - __ pop(rcx); // restore stack pointer to what it was when we came in. - __ bind(slow_case_no_pop); - __ get_constant_pool(rax); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), rax, rdx); - - // continue - __ bind(done); -} - - -void TemplateTable::newarray() { - transition(itos, atos); - __ push_i(rax); // make sure everything is on the stack - __ load_unsigned_byte(rdx, at_bcp(1)); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), rdx, rax); - __ pop_i(rdx); // discard size -} - - -void TemplateTable::anewarray() { - transition(itos, atos); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - __ get_constant_pool(rcx); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), rcx, rdx, rax); -} - - -void TemplateTable::arraylength() { - transition(atos, itos); - __ null_check(rax, arrayOopDesc::length_offset_in_bytes()); - __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes())); -} - - -void TemplateTable::checkcast() { - transition(atos, atos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); // Object is in EAX - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, Address::times_1, Array::base_offset_in_bytes()), JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - - __ push(atos); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); - // vm_result_2 has metadata result - // borrow rdi from locals - __ get_thread(rdi); - __ get_vm_result_2(rax, rdi); - __ restore_locals(); - __ pop_ptr(rdx); - __ jmpb(resolved); - - // Get superklass in EAX and subklass in EBX - __ bind(quicked); - __ mov(rdx, rax); // Save object in EDX; EAX needed for subtype check - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool))); - - __ bind(resolved); - __ load_klass(rbx, rdx); - - // Generate subtype check. Blows ECX. Resets EDI. Object in EDX. - // Superklass in EAX. Subklass in EBX. - __ gen_subtype_check( rbx, ok_is_subtype ); - - // Come here on failure - __ push(rdx); - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - __ mov(rax,rdx); // Restore object in EDX - - // Collect counts on whether this check-cast sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); -} - - -void TemplateTable::instanceof() { - transition(atos, itos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, Address::times_1, Array::base_offset_in_bytes()), JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - - __ push(atos); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); - // vm_result_2 has metadata result - // borrow rdi from locals - __ get_thread(rdi); - __ get_vm_result_2(rax, rdi); - __ restore_locals(); - __ pop_ptr(rdx); - __ load_klass(rdx, rdx); - __ jmp(resolved); - - // Get superklass in EAX and subklass in EDX - __ bind(quicked); - __ load_klass(rdx, rax); - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool))); - - __ bind(resolved); - - // Generate subtype check. Blows ECX. Resets EDI. - // Superklass in EAX. Subklass in EDX. - __ gen_subtype_check( rdx, ok_is_subtype ); - - // Come here on failure - __ xorl(rax,rax); - __ jmpb(done); - // Come here on success - __ bind(ok_is_subtype); - __ movl(rax, 1); - - // Collect counts on whether this test sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); - // rax, = 0: obj == NULL or obj is not an instanceof the specified klass - // rax, = 1: obj != NULL and obj is an instanceof the specified klass -} - - -//---------------------------------------------------------------------------------------------------- -// Breakpoints -void TemplateTable::_breakpoint() { - - // Note: We get here even if we are single stepping.. - // jbug inists on setting breakpoints at every bytecode - // even if we are in single step mode. - - transition(vtos, vtos); - - // get the unpatched byte code - __ get_method(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_original_bytecode_at), rcx, rsi); - __ mov(rbx, rax); - - // post the breakpoint event - __ get_method(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), rcx, rsi); - - // complete the execution of original bytecode - __ dispatch_only_normal(vtos); -} - - -//---------------------------------------------------------------------------------------------------- -// Exceptions - -void TemplateTable::athrow() { - transition(atos, vtos); - __ null_check(rax); - __ jump(ExternalAddress(Interpreter::throw_exception_entry())); -} - - -//---------------------------------------------------------------------------------------------------- -// Synchronization -// -// Note: monitorenter & exit are symmetric routines; which is reflected -// in the assembly code structure as well -// -// Stack layout: -// -// [expressions ] <--- rsp = expression stack top -// .. -// [expressions ] -// [monitor entry] <--- monitor block top = expression stack bot -// .. -// [monitor entry] -// [frame data ] <--- monitor block bot -// ... -// [saved rbp, ] <--- rbp, - - -void TemplateTable::monitorenter() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = ( frame::interpreter_frame_monitor_size() * wordSize); - Label allocated; - - // initialize entry pointer - __ xorl(rdx, rdx); // points to free slot or NULL - - // find a free slot in the monitor block (result in rdx) - { Label entry, loop, exit; - __ movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry - - __ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block - __ jmpb(entry); - - __ bind(loop); - __ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used - __ cmovptr(Assembler::equal, rdx, rcx); // if not used then remember entry in rdx - __ cmpptr(rax, Address(rcx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object - __ jccb(Assembler::equal, exit); // if same object then stop searching - __ addptr(rcx, entry_size); // otherwise advance to next entry - __ bind(entry); - __ cmpptr(rcx, rbx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then check this entry - __ bind(exit); - } - - __ testptr(rdx, rdx); // check if a slot has been found - __ jccb(Assembler::notZero, allocated); // if found, continue with that one - - // allocate one if there's no free slot - { Label entry, loop; - // 1. compute new pointers // rsp: old expression stack top - __ movptr(rdx, monitor_block_bot); // rdx: old expression stack bottom - __ subptr(rsp, entry_size); // move expression stack top - __ subptr(rdx, entry_size); // move expression stack bottom - __ mov(rcx, rsp); // set start value for copy loop - __ movptr(monitor_block_bot, rdx); // set new monitor block top - __ jmp(entry); - // 2. move expression stack contents - __ bind(loop); - __ movptr(rbx, Address(rcx, entry_size)); // load expression stack word from old location - __ movptr(Address(rcx, 0), rbx); // and store it at new location - __ addptr(rcx, wordSize); // advance to next word - __ bind(entry); - __ cmpptr(rcx, rdx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then copy next word - } - - // call run-time routine - // rdx: points to monitor entry - __ bind(allocated); - - // Increment bcp to point to the next bytecode, so exception handling for async. exceptions work correctly. - // The object has already been poped from the stack, so the expression stack looks correct. - __ increment(rsi); - - __ movptr(Address(rdx, BasicObjectLock::obj_offset_in_bytes()), rax); // store object - __ lock_object(rdx); - - // check to make sure this monitor doesn't cause stack overflow after locking - __ save_bcp(); // in case of exception - __ generate_stack_overflow_check(0); - - // The bcp has already been incremented. Just need to dispatch to next instruction. - __ dispatch_next(vtos); -} - - -void TemplateTable::monitorexit() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = ( frame::interpreter_frame_monitor_size() * wordSize); - Label found; - - // find matching slot - { Label entry, loop; - __ movptr(rdx, monitor_block_top); // points to current entry, starting with top-most entry - __ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block - __ jmpb(entry); - - __ bind(loop); - __ cmpptr(rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object - __ jcc(Assembler::equal, found); // if same object then stop searching - __ addptr(rdx, entry_size); // otherwise advance to next entry - __ bind(entry); - __ cmpptr(rdx, rbx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then check this entry - } - - // error handling. Unlocking was not block-structured - Label end; - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); - __ should_not_reach_here(); - - // call run-time routine - // rcx: points to monitor entry - __ bind(found); - __ push_ptr(rax); // make sure object is on stack (contract with oopMaps) - __ unlock_object(rdx); - __ pop_ptr(rax); // discard object - __ bind(end); -} - - -//---------------------------------------------------------------------------------------------------- -// Wide instructions - -void TemplateTable::wide() { - transition(vtos, vtos); - __ load_unsigned_byte(rbx, at_bcp(1)); - ExternalAddress wtable((address)Interpreter::_wentry_point); - __ jump(ArrayAddress(wtable, Address(noreg, rbx, Address::times_ptr))); - // Note: the rsi increment step is part of the individual wide bytecode implementations -} - - -//---------------------------------------------------------------------------------------------------- -// Multi arrays - -void TemplateTable::multianewarray() { - transition(vtos, atos); - __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions - // last dim is on top of stack; we want address of first one: - // first_addr = last_addr + (ndims - 1) * stackElementSize - 1*wordsize - // the latter wordSize to point to the beginning of the array. - __ lea( rax, Address(rsp, rax, Interpreter::stackElementScale(), -wordSize)); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), rax); // pass in rax, - __ load_unsigned_byte(rbx, at_bcp(3)); - __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); // get rid of counts -} - -#endif /* !CC_INTERP */ From 06a745fd7ecf7762adc9eddefcd021854c455708 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Tue, 10 Mar 2015 04:53:58 -0700 Subject: [PATCH 16/79] 8069124: runtime/NMT/MallocSiteHashOverflow.java failing in nightlies Reviewed-by: coleenp, gtriantafill, dholmes --- .../src/share/vm/services/mallocSiteTable.cpp | 3 +-- .../src/share/vm/services/mallocSiteTable.hpp | 3 +-- .../src/share/vm/utilities/nativeCallStack.cpp | 16 +++++++--------- .../src/share/vm/utilities/nativeCallStack.hpp | 6 +++--- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/services/mallocSiteTable.cpp b/hotspot/src/share/vm/services/mallocSiteTable.cpp index 59339a17750..4ab10b49a52 100644 --- a/hotspot/src/share/vm/services/mallocSiteTable.cpp +++ b/hotspot/src/share/vm/services/mallocSiteTable.cpp @@ -135,8 +135,7 @@ bool MallocSiteTable::walk(MallocSiteWalker* walker) { */ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx) { - int index = hash_to_index(key.hash()); - assert(index >= 0, err_msg("Negative index %d", index)); + unsigned int index = hash_to_index(key.hash()); *bucket_idx = (size_t)index; *pos_idx = 0; diff --git a/hotspot/src/share/vm/services/mallocSiteTable.hpp b/hotspot/src/share/vm/services/mallocSiteTable.hpp index cff98161449..7ded2d2b74a 100644 --- a/hotspot/src/share/vm/services/mallocSiteTable.hpp +++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp @@ -238,8 +238,7 @@ class MallocSiteTable : AllStatic { static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx); static bool walk(MallocSiteWalker* walker); - static inline int hash_to_index(int hash) { - hash = (hash > 0) ? hash : (-hash); + static inline unsigned int hash_to_index(unsigned int hash) { return (hash % table_size); } diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.cpp b/hotspot/src/share/vm/utilities/nativeCallStack.cpp index aa3a1e67a5d..7b3717be4c0 100644 --- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp +++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp @@ -55,6 +55,7 @@ NativeCallStack::NativeCallStack(address* pc, int frameCount) { for (; index < NMT_TrackingStackDepth; index ++) { _stack[index] = NULL; } + _hash_value = 0; } // number of stack frames captured @@ -69,19 +70,16 @@ int NativeCallStack::frames() const { } // Hash code. Any better algorithm? -int NativeCallStack::hash() const { - long hash_val = _hash_value; +unsigned int NativeCallStack::hash() const { + uintptr_t hash_val = _hash_value; if (hash_val == 0) { - long pc; - int index; - for (index = 0; index < NMT_TrackingStackDepth; index ++) { - pc = (long)_stack[index]; - if (pc == 0) break; - hash_val += pc; + for (int index = 0; index < NMT_TrackingStackDepth; index++) { + if (_stack[index] == NULL) break; + hash_val += (uintptr_t)_stack[index]; } NativeCallStack* p = const_cast(this); - p->_hash_value = (int)(hash_val & 0xFFFFFFFF); + p->_hash_value = (unsigned int)(hash_val & 0xFFFFFFFF); } return _hash_value; } diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.hpp b/hotspot/src/share/vm/utilities/nativeCallStack.hpp index b6d6a35303e..673d4938b26 100644 --- a/hotspot/src/share/vm/utilities/nativeCallStack.hpp +++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp @@ -56,8 +56,8 @@ class NativeCallStack : public StackObj { static const NativeCallStack EMPTY_STACK; private: - address _stack[NMT_TrackingStackDepth]; - int _hash_value; + address _stack[NMT_TrackingStackDepth]; + unsigned int _hash_value; public: NativeCallStack(int toSkip = 0, bool fillStack = false); @@ -89,7 +89,7 @@ class NativeCallStack : public StackObj { } // Hash code. Any better algorithm? - int hash() const; + unsigned int hash() const; void print_on(outputStream* out) const; void print_on(outputStream* out, int indent) const; From 017611edae784060107305a258f0a7364aca89a0 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 10 Mar 2015 09:42:23 -0700 Subject: [PATCH 17/79] 8074726: Update source and target version used when compiling hotspot class files Use BOOT_JDK_SOURCETARGET from top level, or fall back to -source 8 -target 8 Reviewed-by: dholmes, sla --- hotspot/make/aix/makefiles/rules.make | 13 ++++++++++--- hotspot/make/bsd/makefiles/rules.make | 13 ++++++++++--- hotspot/make/defs.make | 2 ++ hotspot/make/linux/makefiles/rules.make | 13 ++++++++++--- hotspot/make/solaris/makefiles/rules.make | 13 ++++++++++--- hotspot/make/windows/makefiles/rules.make | 13 ++++++++++--- 6 files changed, 52 insertions(+), 15 deletions(-) diff --git a/hotspot/make/aix/makefiles/rules.make b/hotspot/make/aix/makefiles/rules.make index 894c169e39d..2c4c38658c6 100644 --- a/hotspot/make/aix/makefiles/rules.make +++ b/hotspot/make/aix/makefiles/rules.make @@ -126,10 +126,17 @@ QUIETLY$(MAKE_VERBOSE) = @ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff --git a/hotspot/make/bsd/makefiles/rules.make b/hotspot/make/bsd/makefiles/rules.make index 894c169e39d..2c4c38658c6 100644 --- a/hotspot/make/bsd/makefiles/rules.make +++ b/hotspot/make/bsd/makefiles/rules.make @@ -126,10 +126,17 @@ QUIETLY$(MAKE_VERBOSE) = @ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index 5c4f00dc1d8..1c7f8ce9624 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -347,6 +347,8 @@ MAKE_ARGS += JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) # includes this make/defs.make file. MAKE_ARGS += HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) +MAKE_ARGS += BOOT_JDK_SOURCETARGET="$(BOOT_JDK_SOURCETARGET)" + # Various export sub directories EXPORT_INCLUDE_DIR = $(EXPORT_PATH)/include EXPORT_DOCS_DIR = $(EXPORT_PATH)/docs diff --git a/hotspot/make/linux/makefiles/rules.make b/hotspot/make/linux/makefiles/rules.make index 894c169e39d..2c4c38658c6 100644 --- a/hotspot/make/linux/makefiles/rules.make +++ b/hotspot/make/linux/makefiles/rules.make @@ -126,10 +126,17 @@ QUIETLY$(MAKE_VERBOSE) = @ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff --git a/hotspot/make/solaris/makefiles/rules.make b/hotspot/make/solaris/makefiles/rules.make index d7435502107..e809b49f691 100644 --- a/hotspot/make/solaris/makefiles/rules.make +++ b/hotspot/make/solaris/makefiles/rules.make @@ -118,10 +118,17 @@ QUIETLY$(MAKE_VERBOSE) = @ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff --git a/hotspot/make/windows/makefiles/rules.make b/hotspot/make/windows/makefiles/rules.make index 08a6a85e101..2bd02379060 100644 --- a/hotspot/make/windows/makefiles/rules.make +++ b/hotspot/make/windows/makefiles/rules.make @@ -44,10 +44,17 @@ BOOT_JAVA_HOME= !endif # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION=6 -BOOT_TARGET_CLASS_VERSION=6 JAVAC_FLAGS=-g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +!ifndef BOOT_JDK_SOURCETARGET +BOOTSTRAP_SOURCETARGET=-source 8 -target 8 +!else +BOOTSTRAP_SOURCETARGET=$(BOOT_JDK_SOURCETARGET) +!endif + +BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # VS2012 and VS2013 loads VS10 projects just fine (and will # upgrade them automatically to VS2012 format). From 8a235045ca1416362a49fa18b0d5a1fc35d007ab Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Thu, 12 Mar 2015 19:11:17 +0300 Subject: [PATCH 18/79] 8074980: add WhiteBox API to get a flag value for a method Reviewed-by: kvn, fzhinkin --- test/lib/sun/hotspot/WhiteBox.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index b19845392ff..fb95cc4a106 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,6 +27,7 @@ package sun.hotspot; import java.lang.reflect.Executable; import java.util.Arrays; import java.util.List; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; import java.security.BasicPermission; @@ -250,6 +251,23 @@ public class WhiteBox { } return offset; } + public native Boolean getMethodBooleanOption(Executable method, String name); + public native Long getMethodIntxOption(Executable method, String name); + public native Long getMethodUintxOption(Executable method, String name); + public native Double getMethodDoubleOption(Executable method, String name); + public native String getMethodStringOption(Executable method, String name); + private final List> methodOptionGetters + = Arrays.asList(this::getMethodBooleanOption, this::getMethodIntxOption, + this::getMethodUintxOption, this::getMethodDoubleOption, + this::getMethodStringOption); + + public Object getMethodOption(Executable method, String name) { + return methodOptionGetters.stream() + .map(f -> f.apply(method, name)) + .filter(x -> x != null) + .findAny() + .orElse(null); + } // Safepoint Checking public native void assertMatchingSafepointCalls(boolean mutexSafepointValue, boolean attemptedNoSafepointValue); From b78d23ed01a13e4e0dc6f8782db6290c4c7c2d83 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Thu, 12 Mar 2015 19:12:52 +0300 Subject: [PATCH 19/79] 8073860: [TESTBUG] compiler/whitebox/DeoptimizeFramesTest fails with exit code 1 Reviewed-by: kvn, roland --- hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java index d5268dfe5b6..40d7be385bf 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java @@ -31,11 +31,13 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -Xmixed * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method - * -XX:-DeoptimizeRandom -XX:-DeoptimizeALot DeoptimizeFramesTest true + * -XX:+IgnoreUnexpectedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot + * DeoptimizeFramesTest true * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -Xmixed * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method - * -XX:-DeoptimizeRandom -XX:-DeoptimizeALot DeoptimizeFramesTest false + * -XX:+IgnoreUnexpectedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot + * DeoptimizeFramesTest false * @summary testing of WB::deoptimizeFrames() */ import java.lang.reflect.Executable; From cc89bac7ab5981245cf4d30bbd748aac1b55e50c Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Thu, 12 Mar 2015 19:11:25 +0300 Subject: [PATCH 20/79] 8074980: add WhiteBox API to get a flag value for a method Reviewed-by: kvn, fzhinkin --- hotspot/src/share/vm/prims/whitebox.cpp | 84 ++++++++++++++ .../compiler/oracle/GetMethodOptionTest.java | 104 ++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 hotspot/test/compiler/oracle/GetMethodOptionTest.java diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index d469831b37e..76e60f18906 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -1133,6 +1133,75 @@ WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb)) VMThread::execute(&force_safepoint_op); WB_END +template +static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) { + assert(value != NULL, "sanity"); + if (method == NULL || name == NULL) { + return false; + } + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, false); + methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid)); + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* flag_name = env->GetStringUTFChars(name, NULL); + bool result = CompilerOracle::has_option_value(mh, flag_name, *value); + env->ReleaseStringUTFChars(name, flag_name); + return result; +} + +WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + bool result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return booleanBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + intx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + uintx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + double result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return doubleBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + ccstr ccstrResult; + if (GetMethodOption (thread, env, method, name, &ccstrResult)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + jstring result = env->NewStringUTF(ccstrResult); + CHECK_JNI_EXCEPTION_(env, NULL); + return result; + } + return NULL; +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -1333,6 +1402,21 @@ static JNINativeMethod methods[] = { {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, + {CC"getMethodBooleanOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", + (void*)&WB_GetMethodBooleaneOption}, + {CC"getMethodIntxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodIntxOption}, + {CC"getMethodUintxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodUintxOption}, + {CC"getMethodDoubleOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;", + (void*)&WB_GetMethodDoubleOption}, + {CC"getMethodStringOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;", + (void*)&WB_GetMethodStringOption}, }; #undef CC diff --git a/hotspot/test/compiler/oracle/GetMethodOptionTest.java b/hotspot/test/compiler/oracle/GetMethodOptionTest.java new file mode 100644 index 00000000000..d66a102673b --- /dev/null +++ b/hotspot/test/compiler/oracle/GetMethodOptionTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 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 + * 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. + */ + +import java.lang.reflect.Executable; +import java.util.function.BiFunction; + +import com.oracle.java.testlibrary.Asserts; +import sun.hotspot.WhiteBox; + +/* + * @test + * @bug 8074980 + * @library /testlibrary /../../test/lib + * @build sun.hotspot.WhiteBox com.oracle.java.testlibrary.Asserts GetMethodOptionTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstrlist,MyListOption,_foo,_bar + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstr,MyStrOption,_foo + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOption,false + * -XX:CompileCommand=option,GetMethodOptionTest::test,intx,MyIntxOption,-1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,uintx,MyUintxOption,1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,MyFlag + * -XX:CompileCommand=option,GetMethodOptionTest::test,double,MyDoubleOption1,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest.test,double,MyDoubleOption2,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123 + * GetMethodOptionTest + */ + +public class GetMethodOptionTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + public static void main(String[] args) { + Executable test = getMethod("test"); + Executable test2 = getMethod("test2"); + BiFunction getter = WB::getMethodOption; + for (TestCase testCase : TestCase.values()) { + Object expected = testCase.value; + String name = testCase.name(); + Asserts.assertEQ(expected, getter.apply(test, name), + testCase + ": universal getter returns wrong value"); + Asserts.assertEQ(expected, testCase.getter.apply(test, name), + testCase + ": specific getter returns wrong value"); + Asserts.assertEQ(null, getter.apply(test2, name), + testCase + ": universal getter returns value for unused method"); + Asserts.assertEQ(null, testCase.getter.apply(test2, name), + testCase + ": type specific getter returns value for unused method"); + } + } + private static void test() { } + private static void test2() { } + + private static enum TestCase { + MyListOption("_foo _bar", WB::getMethodStringOption), + MyStrOption("_foo", WB::getMethodStringOption), + MyBoolOption(false, WB::getMethodBooleanOption), + MyIntxOption(-1L, WB::getMethodIntxOption), + MyUintxOption(1L, WB::getMethodUintxOption), + MyFlag(true, WB::getMethodBooleanOption), + MyDoubleOption1(1.123d, WB::getMethodDoubleOption), + MyDoubleOption2(1.123d, WB::getMethodDoubleOption), + MyBoolOptionX(false, WB::getMethodBooleanOption), + MyIntxOptionX(-1L, WB::getMethodIntxOption), + MyUintxOptionX(1L, WB::getMethodUintxOption), + MyFlagX(true, WB::getMethodBooleanOption), + MyDoubleOptionX(1.123d, WB::getMethodDoubleOption); + + public final Object value; + public final BiFunction getter; + private TestCase(Object value, BiFunction getter) { + this.value = value; + this.getter = getter; + } + } + + private static Executable getMethod(String name) { + Executable result; + try { + result = GetMethodOptionTest.class.getDeclaredMethod(name); + } catch (NoSuchMethodException | SecurityException e) { + throw new Error("TESTBUG : can't get method " + name, e); + } + return result; + } +} From c4ebb7f3c0e8a9b546fb5b7e3e1d994ac0353763 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Fri, 13 Mar 2015 13:15:24 +0530 Subject: [PATCH 21/79] 8071847: java.lang.NullPointerException at com.sun.tools.javac.code.Types.elemtype(Types.java:1870) Class file reader should recover from malformed class files that contain methods incorrectly flagged as variable arity methods. Reviewed-by: jlahoda --- .../com/sun/tools/javac/jvm/ClassReader.java | 10 ++ .../tools/javac/resources/compiler.properties | 3 + .../test/tools/javac/T8071847/T8071847.java | 108 ++++++++++++++++++ .../tools/javac/diags/examples.not-yet.txt | 1 + 4 files changed, 122 insertions(+) create mode 100644 langtools/test/tools/javac/T8071847/T8071847.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 307119aa9bd..641098642ae 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -56,6 +56,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; +import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.TYPEVAR; import static com.sun.tools.javac.jvm.ClassFile.*; @@ -2006,6 +2007,15 @@ public class ClassReader { } if (saveParameterNames) setParameterNames(m, type); + + if ((flags & VARARGS) != 0) { + final Type last = type.getParameterTypes().last(); + if (last == null || !last.hasTag(ARRAY)) { + m.flags_field &= ~VARARGS; + throw badClassFile("malformed.vararg.method", m); + } + } + return m; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index c1bb9da153e..c3a8900c57c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1847,6 +1847,9 @@ compiler.misc.unicode.str.not.supported=\ compiler.misc.undecl.type.var=\ undeclared type variable: {0} +compiler.misc.malformed.vararg.method=\ + class file contains malformed variable arity method: {0} + compiler.misc.wrong.version=\ class file has wrong version {0}.{1}, should be {2}.{3} diff --git a/langtools/test/tools/javac/T8071847/T8071847.java b/langtools/test/tools/javac/T8071847/T8071847.java new file mode 100644 index 00000000000..1d691e15b02 --- /dev/null +++ b/langtools/test/tools/javac/T8071847/T8071847.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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 + * 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 8071847 + * @summary Verify proper termination when instance initialization method uses invalid flags + * @compile T8071847.java + * @run main T8071847 +*/ + + +import java.io.*; +import java.util.*; + +public class T8071847 { + String testclass="invalidFlags.class"; + String testclassHexString = + "CAFEBABE00000031000D0A0003000A07000B07000C0100063C696E69743E0100" + + "03282956010004436F646501000F4C696E654E756D6265725461626C6501000A" + + "536F7572636546696C65010009546573742E6A6176610C0004000501000C696E" + + "76616C6964466C6167730100106A6176612F6C616E672F4F626A656374002000" + + "02000300000000000100A000040005000100060000001D00010001000000052A" + + "B70001B10000000100070000000600010000000100010008000000020009"; + + String testJavaFile = "testInvalidFlags.java"; + String testJavaSource ="public class testInvalidFlags extends invalidFlags {" + + "invalidFlags c = null;" + + "public testInvalidFlags() { c = new invalidFlags(); }" + + "public static void main(String... args) { " + + "new testInvalidFlags();}}"; + + public static void main(String[] args) throws Exception { + new T8071847().run(); + } + + public void run() throws IOException { + writeHexFile(testclass,testclassHexString); + writeTestFile(testJavaFile, testJavaSource); + javac(testJavaFile); + } + + File writeTestFile(String fname, String source) throws IOException { + File f = new File(fname); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(source); + out.close(); + return f; + } + + byte[] hexToByte(String str) { + char[] CA = str.toCharArray(); + byte[] byteArry = new byte[str.length()/2]; + int bi = 0; + for (int i = 0; i javacArgs = new ArrayList<>(); + javacArgs.addAll(Arrays.asList("-XDrawDiagnostics", "-cp", ".", "-d", ".", className)); + rc = com.sun.tools.javac.Main.compile( + javacArgs.toArray(new String[javacArgs.size()]),out); + out.close(); + if (rc > 1) { + System.out.println(sw.toString()); + throw new Error("javac " + className + " failed. rc=" + rc); + } + if (rc != 1 || !sw.toString().contains("compiler.misc.malformed.vararg.method")) + throw new RuntimeException("Unexpected output" + sw.toString()); + return sw.toString(); + } +} diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 9f58cf88154..795f7166008 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -87,6 +87,7 @@ compiler.misc.type.req.exact compiler.misc.unable.to.access.file # ClassFile compiler.misc.undecl.type.var # ClassReader compiler.misc.unicode.str.not.supported # ClassReader +compiler.misc.malformed.vararg.method # ClassReader compiler.misc.verbose.retro # UNUSED compiler.misc.verbose.retro.with # UNUSED compiler.misc.verbose.retro.with.list # UNUSED From f1f1f0f7e110a60035673b2173bf7619581c1101 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Fri, 13 Mar 2015 10:25:46 +0530 Subject: [PATCH 22/79] 8074148: Attr.visitBinary flags error at wrong position Reviewed-by: vromero --- .../classes/com/sun/tools/javac/comp/Attr.java | 2 +- .../test/tools/javac/expression/BinopVoidTest.java | 14 ++++++++++++++ .../test/tools/javac/expression/BinopVoidTest.out | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/expression/BinopVoidTest.java create mode 100644 langtools/test/tools/javac/expression/BinopVoidTest.out diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 25d25c3b863..953c6129f12 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2942,7 +2942,7 @@ public class Attr extends JCTree.Visitor { public void visitBinary(JCBinary tree) { // Attribute arguments. Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); - Type right = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.rhs, env)); + Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env)); // Find operator. Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); Type owntype = types.createErrorType(tree.type); diff --git a/langtools/test/tools/javac/expression/BinopVoidTest.java b/langtools/test/tools/javac/expression/BinopVoidTest.java new file mode 100644 index 00000000000..399845a54f7 --- /dev/null +++ b/langtools/test/tools/javac/expression/BinopVoidTest.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074148 + * @summary Attr.visitBinary flags error at wrong position + * + * @compile/fail/ref=BinopVoidTest.out -XDrawDiagnostics BinopVoidTest.java + */ + +class BinopVoidTest { + void foo() {} + int x = 10 + foo(); + int y = foo() + 10; + int z = foo() + foo(); +} diff --git a/langtools/test/tools/javac/expression/BinopVoidTest.out b/langtools/test/tools/javac/expression/BinopVoidTest.out new file mode 100644 index 00000000000..1d8265b99a5 --- /dev/null +++ b/langtools/test/tools/javac/expression/BinopVoidTest.out @@ -0,0 +1,5 @@ +BinopVoidTest.java:11:21: compiler.err.void.not.allowed.here +BinopVoidTest.java:12:16: compiler.err.void.not.allowed.here +BinopVoidTest.java:13:16: compiler.err.void.not.allowed.here +BinopVoidTest.java:13:24: compiler.err.void.not.allowed.here +4 errors From bb8dc09453b6dcd82825eb40e1db881d9d0ae263 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Fri, 13 Mar 2015 12:44:28 +0000 Subject: [PATCH 23/79] 8074723: AARCH64: Stray pop in C1 LIR_Assembler::emit_profile_type Remove stray POP instruction Reviewed-by: dholmes --- hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index 6b2c4d2741f..d5e0184d6ff 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -2776,7 +2776,6 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { __ stop("unexpected profiling mismatch"); __ bind(ok); - __ pop(tmp); } #endif // first time here. Set profile type. From 71ad1eca2063468709b0f0204ade4b7f15ad347b Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 13 Mar 2015 14:00:36 +0100 Subject: [PATCH 24/79] 8075054: Mixed case Windows path break native dependency checks Reviewed-by: erikj --- make/common/NativeCompilation.gmk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 17dca95b7fe..c749532875e 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -60,7 +60,7 @@ WINDOWS_SHOWINCLUDE_SED_PATTERN := \ -e 's|Note: including file: *||' \ -e 's|\\|/|g' \ -e 's|^\([a-zA-Z]\):|$(UNIX_PATH_PREFIX)/\1|g' \ - -e '/$(subst /,\/,$(TOPDIR))/!d' \ + -e '\|$(TOPDIR)|I !d' \ -e 's|$$$$| \\|g' \ # @@ -153,7 +153,7 @@ define add_native_source exit `cat $$($1_$2_DEP).exitvalue` $(RM) $$($1_$2_DEP).exitvalue ($(ECHO) $$@: \\ \ - && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) > $$($1_$2_DEP) + && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) | $(SORT) -u > $$($1_$2_DEP) endif # Create a dependency target file from the dependency file. # Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ From 10b38fe9aec027fe35fcf82a6c33175f49f5bf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 13 Mar 2015 18:40:07 +0100 Subject: [PATCH 25/79] 8075006: Threads spinning infinitely in WeakHashMap.get running test262parallel Reviewed-by: lagergren, attila --- .../nashorn/internal/runtime/PropertyMap.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java index 2014c643796..db7c5c992ce 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java @@ -330,12 +330,15 @@ public final class PropertyMap implements Iterable, Serializable { * Indicate that proto itself has changed in hierarchy somewhere. */ synchronized void invalidateAllProtoGetSwitchPoints() { - if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) { - if (Context.DEBUG) { - protoInvalidations += protoGetSwitches.size(); + if (protoGetSwitches != null) { + final int size = protoGetSwitches.size(); + if (size > 0) { + if (Context.DEBUG) { + protoInvalidations += size; + } + SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size])); + protoGetSwitches.clear(); } - SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()])); - protoGetSwitches.clear(); } } @@ -375,7 +378,8 @@ public final class PropertyMap implements Iterable, Serializable { } } - // Update the free slots bitmap for a property that has been deleted and/or added. + // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized + // as it is always invoked on a newly created instance. private void updateFreeSlots(final Property oldProperty, final Property newProperty) { // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications. boolean freeSlotsCloned = false; @@ -425,7 +429,7 @@ public final class PropertyMap implements Iterable, Serializable { * * @return New {@link PropertyMap} with {@link Property} added. */ - public PropertyMap addProperty(final Property property) { + public synchronized PropertyMap addProperty(final Property property) { if (listeners != null) { listeners.propertyAdded(property); } @@ -434,9 +438,9 @@ public final class PropertyMap implements Iterable, Serializable { if (newMap == null) { final PropertyHashMap newProperties = properties.immutableAdd(property); newMap = new PropertyMap(this, newProperties); - addToHistory(property, newMap); newMap.updateFlagsAndBoundaries(property); newMap.updateFreeSlots(null, property); + addToHistory(property, newMap); } return newMap; @@ -449,7 +453,7 @@ public final class PropertyMap implements Iterable, Serializable { * * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found. */ - public PropertyMap deleteProperty(final Property property) { + public synchronized PropertyMap deleteProperty(final Property property) { if (listeners != null) { listeners.propertyDeleted(property); } @@ -881,8 +885,7 @@ public final class PropertyMap implements Iterable, Serializable { * @param newProto New prototype object to replace oldProto. * @return New {@link PropertyMap} with prototype changed. */ - public PropertyMap changeProto(final ScriptObject newProto) { - + public synchronized PropertyMap changeProto(final ScriptObject newProto) { final PropertyMap nextMap = checkProtoHistory(newProto); if (nextMap != null) { return nextMap; From fe068291e19e0ad9c87b8a9b1c08cca2984b7cd8 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 13 Mar 2015 13:41:29 -0700 Subject: [PATCH 26/79] 8075035: Turn on doclint checking of modules in the langtools repo Reviewed-by: ihse --- make/CompileJavaModules.gmk | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 23188129d3b..066802688e7 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -90,12 +90,16 @@ endif ################################################################################ +java.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' + +################################################################################ + java.datatransfer_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' java.datatransfer_COPY := flavormap.properties ################################################################################ -java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-missing,-reference '-Xdoclint/package:java.*,javax.*' +java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-missing,-reference '-Xdoclint/package:java.*,javax.*' java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties @@ -336,6 +340,7 @@ jdk.charsets_COPY := .dat ################################################################################ +jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*' jdk.compiler_COPY := javax.tools.JavaCompilerTool jdk.compiler_CLEAN_FILES := $(wildcard \ $(patsubst %, $(JDK_TOPDIR)/src/jdk.compiler/share/classes/%/*.properties, \ From 4c6eb2b310dafd757470ef4514d0552b5fd56adb Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Mon, 16 Mar 2015 11:00:07 +0100 Subject: [PATCH 27/79] 8075090: Add tests for the basic failure of try/finally compilation Reviewed-by: hannesw, lagergren --- nashorn/test/script/basic/JDK-8075090.js | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 nashorn/test/script/basic/JDK-8075090.js diff --git a/nashorn/test/script/basic/JDK-8075090.js b/nashorn/test/script/basic/JDK-8075090.js new file mode 100644 index 00000000000..e39b4f2c777 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8075090.js @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * JDK-8075090: Add tests for the basic failure of try/finally compilation + * + * @test + * @run + */ + +(function() { + var finallyExpected = false; + try { + for(var i = 0; i < 2; ++i) { + if(i == 1) { + continue; + } + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); + +(function() { + var finallyExpected = false; + try { + for(var i = 0; i < 2; ++i) { + if(i == 1) { + break; + } + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); + +(function() { + var finallyExpected = false; + try { + L1: { + if ((function(){return true})()) { + break L1; + } + Assert.fail(); // unreachable + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); From cf37646b3f4f6a06951b7c686f1769923d11031d Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 16 Mar 2015 17:01:47 +0530 Subject: [PATCH 28/79] 8075207: Nashorn parser API returns StatementTree objects in out of order Reviewed-by: lagergren, forax, hannesw --- nashorn/samples/findwith.js | 5 - .../jdk/nashorn/api/tree/DoWhileLoopTree.java | 2 + .../jdk/nashorn/api/tree/ForInLoopTree.java | 1 + .../jdk/nashorn/api/tree/IRTranslator.java | 68 +- .../jdk/nashorn/api/tree/ParserImpl.java | 2 +- .../jdk/nashorn/api/tree/WhileLoopTree.java | 2 + nashorn/test/script/basic/JDK-8075207.js | 76 + .../script/nosecurity/parserapi.js.EXPECTED | 1690 ++++++++--------- 8 files changed, 971 insertions(+), 875 deletions(-) create mode 100644 nashorn/test/script/basic/JDK-8075207.js diff --git a/nashorn/samples/findwith.js b/nashorn/samples/findwith.js index 1d82d712669..31d1f1d7ac0 100644 --- a/nashorn/samples/findwith.js +++ b/nashorn/samples/findwith.js @@ -52,7 +52,6 @@ var Parser = Java.type("jdk.nashorn.api.tree.Parser"); var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1"); var parser = Parser.create("-scripting", "--const-as-var"); -var protoFound = false; function checkFile(file) { // print("checking " + file); @@ -92,7 +91,3 @@ if (file.isDirectory()) { } else { checkFile(file); } - -if (protoFound) { - print("__proto__ is non-standard. Use Object.get/setPrototypeOf instead"); -} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java index f410cb7a899..80632ed09a0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java @@ -44,6 +44,7 @@ public interface DoWhileLoopTree extends ConditionalLoopTree { * * @return the condition expression */ + @Override ExpressionTree getCondition(); /** @@ -51,5 +52,6 @@ public interface DoWhileLoopTree extends ConditionalLoopTree { * * @return the statement */ + @Override StatementTree getStatement(); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java index a1e1d04ebd0..0e28497ec2d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java @@ -57,6 +57,7 @@ public interface ForInLoopTree extends LoopTree { * * @return the statement */ + @Override StatementTree getStatement(); /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java index f923cc8bd2e..cc0093e372c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java @@ -25,6 +25,7 @@ package jdk.nashorn.api.tree; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -92,7 +93,7 @@ final class IRTranslator extends NodeVisitor { final Block body = node.getBody(); return new CompilationUnitTreeImpl(node, - translateStats(body != null? body.getStatements() : null)); + translateStats(body != null? getOrderedStatements(body.getStatements()) : null)); } @Override @@ -103,25 +104,7 @@ final class IRTranslator extends NodeVisitor { @Override public boolean enterBlock(final Block block) { - // FIXME: revisit this! - if (block.isSynthetic()) { - final int statCount = block.getStatementCount(); - switch (statCount) { - case 0: { - final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); - curStat = new EmptyStatementTreeImpl(emptyNode); - return false; - } - case 1: { - curStat = translateStat(block.getStatements().get(0)); - return false; - } - } - } - - curStat = new BlockTreeImpl(block, - translateStats(block.getStatements())); - return false; + return handleBlock(block, false); } @Override @@ -245,7 +228,7 @@ final class IRTranslator extends NodeVisitor { final List paramTrees = translateExprs(functionNode.getParameters()); - final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody()); + final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody(), true); curExpr = new FunctionExpressionTreeImpl(functionNode, paramTrees, blockTree); return false; @@ -420,7 +403,7 @@ final class IRTranslator extends NodeVisitor { final List paramTrees = translateExprs(funcNode.getParameters()); - final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody()); + final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody(), true); curStat = new FunctionDeclarationTreeImpl(varNode, paramTrees, blockTree); } else { curStat = new VariableTreeImpl(varNode, translateExpr(initNode)); @@ -453,14 +436,51 @@ final class IRTranslator extends NodeVisitor { } private StatementTree translateBlock(final Block blockNode) { + return translateBlock(blockNode, false); + } + + private StatementTree translateBlock(final Block blockNode, final boolean sortStats) { if (blockNode == null) { return null; } curStat = null; - blockNode.accept(this); + handleBlock(blockNode, sortStats); return curStat; } + private boolean handleBlock(final Block block, final boolean sortStats) { + // FIXME: revisit this! + if (block.isSynthetic()) { + final int statCount = block.getStatementCount(); + switch (statCount) { + case 0: { + final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); + curStat = new EmptyStatementTreeImpl(emptyNode); + return false; + } + case 1: { + curStat = translateStat(block.getStatements().get(0)); + return false; + } + default: { + // fall through + break; + } + } + } + + final List stats = block.getStatements(); + curStat = new BlockTreeImpl(block, + translateStats(sortStats? getOrderedStatements(stats) : stats)); + return false; + } + + private List getOrderedStatements(final List stats) { + final List statList = new ArrayList<>(stats); + statList.sort(Comparator.comparingInt(Node::getStart)); + return statList; + } + private List translateStats(final List stats) { if (stats == null) { return null; @@ -511,7 +531,7 @@ final class IRTranslator extends NodeVisitor { return curStat; } - private IdentifierTree translateIdent(final IdentNode ident) { + private static IdentifierTree translateIdent(final IdentNode ident) { return new IdentifierTreeImpl(ident); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java index e265cf0c064..e40b84c1c77 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java @@ -139,7 +139,7 @@ final class ParserImpl implements Parser { } } - private CompilationUnitTree translate(final FunctionNode node) { + private static CompilationUnitTree translate(final FunctionNode node) { return new IRTranslator().translate(node); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java index 9e89dd3a95d..5910caf9a0a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java @@ -43,6 +43,7 @@ public interface WhileLoopTree extends ConditionalLoopTree { * * @return the condition expression */ + @Override ExpressionTree getCondition(); /** @@ -50,5 +51,6 @@ public interface WhileLoopTree extends ConditionalLoopTree { * * @return the statement contained */ + @Override StatementTree getStatement(); } diff --git a/nashorn/test/script/basic/JDK-8075207.js b/nashorn/test/script/basic/JDK-8075207.js new file mode 100644 index 00000000000..d44fc5512b9 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8075207.js @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * JDK-8075207: Nashorn parser API returns StatementTree objects in out of order + * + * @test + * @option -scripting + * @run + */ + +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var ExpressionStatementTree = Java.type("jdk.nashorn.api.tree.ExpressionStatementTree"); +var FunctionDeclarationTree = Java.type("jdk.nashorn.api.tree.FunctionDeclarationTree"); +var VariableTree = Java.type("jdk.nashorn.api.tree.VariableTree"); + +var parser = Parser.create(); + +var ast = parser.parse("hello.js", < Date: Mon, 16 Mar 2015 16:17:19 +0100 Subject: [PATCH 29/79] 8066217: ArrayBuffer constructor was erroneous with zero args Reviewed-by: sundar, hannesw --- .../nashorn/internal/objects/NativeArrayBuffer.java | 4 +++- nashorn/test/script/basic/typedarrays.js | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java index e3c5c00d768..2464b844dcf 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java @@ -26,7 +26,9 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + import java.nio.ByteBuffer; + import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -101,7 +103,7 @@ public final class NativeArrayBuffer extends ScriptObject { } if (args.length == 0) { - throw new RuntimeException("missing length argument"); + return new NativeArrayBuffer(0); } return new NativeArrayBuffer(JSType.toInt32(args[0])); diff --git a/nashorn/test/script/basic/typedarrays.js b/nashorn/test/script/basic/typedarrays.js index b15f5dd15f7..d66c79b8a7a 100644 --- a/nashorn/test/script/basic/typedarrays.js +++ b/nashorn/test/script/basic/typedarrays.js @@ -28,6 +28,17 @@ * @run */ +//JDK-8066217, constructor for arraybuffer not behaving as per spec +function checkLength(ab, l) { + if (ab.byteLength != l) { + throw "length error: " + ab.byteLength + " != " + l; + } +} +checkLength(new ArrayBuffer(), 0); +checkLength(new ArrayBuffer(0), 0); +checkLength(new ArrayBuffer(1024), 1024); +checkLength(new ArrayBuffer(1,2,3), 1); +checkLength(new ArrayBuffer([17]), 17); var typeDefinitions = [ Int8Array, From 74e2514b516fcb09dd9581f4378a302d0f5b0697 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Mon, 16 Mar 2015 18:13:38 +0100 Subject: [PATCH 30/79] 8075223: revert multithreaded deoptimizing compilation livelock prevention Reviewed-by: hannesw, sundar --- .../internal/runtime/CompiledFunction.java | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java index 8dee00ec645..ce20ed31520 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java @@ -27,7 +27,6 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; - import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -595,7 +594,7 @@ final class CompiledFunction { * switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function. * This is not a problem, though, as these switch points are always used to produce call sites that fall back to * relinking when they are invalidated, and in this case the execution will end up here again. What this method - * basically does is reduce such busy-loop relinking while the function is being recompiled on a different thread. + * basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread. * @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the * {@code CompiledFunction} method itself in some capacity. * @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions @@ -603,27 +602,20 @@ final class CompiledFunction { * function can't be further deoptimized). */ private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier invocationSupplier) { - for(int i = 0; i < 2; ++i) { + for(;;) { final MethodHandle handle = invocationSupplier.get(); final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null; - if(i == 0 && assumptions != null && assumptions.hasBeenInvalidated()) { + if(assumptions != null && assumptions.hasBeenInvalidated()) { // We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit // this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that // the behavior of invalidating the old switch point before recompilation, and only creating the new one - // after recompilation is by design. If we didn't wait here, we would be busy looping through the - // fallback path of the invalidated switch point, relinking the call site again with the same - // invalidated switch point, invoking the fallback, etc. stealing CPU cycles from the recompilation - // task we're dependent on. This can still happen if the switch point gets invalidated after we grabbed - // it here, in which case we'll indeed do one busy relink immediately. - // On the other hand, in order to avoid a rare livelock, we aren't doing an infinite loop, and we - // aren't wait()-ing indefinitely. We'll do at most one, at most 1000ms long wait after which we'll - // return the current handle even if it's invalidated (and which'll then trigger one loop through the - // relink mechanism). We therefore strike a balance between busy looping and a livelock risk by making - // sure that there's at most one iteration of busy loop per second. It is theoretically possible to - // correctly implement this without ever risking a livelock, but using this heuristic we eliminate the - // chance of the livelock, while still maintaining a good enough busy-looping prevention. + // after recompilation is by design. If we didn't wait here for the recompilation to complete, we would + // be busy looping through the fallback path of the invalidated switch point, relinking the call site + // again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from + // the recompilation task we're dependent on. This can still happen if the switch point gets invalidated + // after we grabbed it here, in which case we'll indeed do one busy relink immediately. try { - wait(1000L); + wait(); } catch (final InterruptedException e) { // Intentionally ignored. There's nothing meaningful we can do if we're interrupted } @@ -631,7 +623,6 @@ final class CompiledFunction { return new HandleAndAssumptions(handle, assumptions); } } - throw new AssertionError(); // never reached } private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) { From 207dec2e01ccb64e2ae994ff26df8c12decc7cc0 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 17 Mar 2015 14:16:30 +0100 Subject: [PATCH 31/79] 8075236: Change layout of gcov .gcno files in symbols image Reviewed-by: ihse, tbell --- make/Images.gmk | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/make/Images.gmk b/make/Images.gmk index 6fe4f766d36..3a8171416c7 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -494,29 +494,16 @@ ifeq ($(GCOV_ENABLED), true) GCOV_FIND_EXPR := -type f -name "*.gcno" - ifeq ($(JVM_VARIANT_CLIENT), true) - $(eval $(call SetupCopyFiles,COPY_HOTSPOT_CLIENT_GCOV_GCNO, \ - SRC := $(HOTSPOT_OUTPUTDIR), \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/hotspot/client, \ - FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR)/*compiler1/ $(GCOV_FIND_EXPR)), \ - FLATTEN := true)) + $(eval $(call SetupCopyFiles,COPY_HOTSPOT_GCOV_GCNO, \ + SRC := $(OUTPUT_ROOT), \ + DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \ + FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR) $(GCOV_FIND_EXPR)))) - SYMBOLS_TARGETS += $(COPY_HOTSPOT_CLIENT_GCOV_GCNO) - endif - - ifeq ($(JVM_VARIANT_SERVER), true) - $(eval $(call SetupCopyFiles,COPY_HOTSPOT_SERVER_GCOV_GCNO, \ - SRC := $(HOTSPOT_OUTPUTDIR), \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/hotspot/server, \ - FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR)/*compiler2/ $(GCOV_FIND_EXPR)), \ - FLATTEN := true)) - - SYMBOLS_TARGETS += $(COPY_HOTSPOT_SERVER_GCOV_GCNO) - endif + SYMBOLS_TARGETS += $(COPY_HOTSPOT_GCOV_GCNO) $(eval $(call SetupCopyFiles,COPY_JDK_GCOV_GCNO, \ - SRC := $(SUPPORT_OUTPUTDIR)/native, \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/jdk, \ + SRC := $(OUTPUT_ROOT), \ + DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \ FILES := $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/native $(GCOV_FIND_EXPR)))) SYMBOLS_TARGETS += $(COPY_JDK_GCOV_GCNO) From 2fc2ef9a394adbc32197c5dc6d50acde138ae452 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 17 Mar 2015 14:03:05 +0000 Subject: [PATCH 32/79] 8075045: AARCH64: Stack banging should use store rather than load Change stack bangs to use a store rather than a load Reviewed-by: dholmes --- hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp | 2 +- hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 558d7aa9377..b922057f897 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -872,7 +872,7 @@ public: // stack grows down, caller passes positive offset assert(offset > 0, "must bang with negative offset"); mov(rscratch2, -offset); - ldr(zr, Address(sp, rscratch2)); + str(zr, Address(sp, rscratch2)); } // Writes to stack successive pages until offset reached to check for diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp index db4f8922dc5..32e4a29d865 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp @@ -858,7 +858,7 @@ void InterpreterGenerator::bang_stack_shadow_pages(bool native_call) { const int page_size = os::vm_page_size(); for (int pages = start_page; pages <= StackShadowPages ; pages++) { __ sub(rscratch2, sp, pages*page_size); - __ ldr(zr, Address(rscratch2)); + __ str(zr, Address(rscratch2)); } } } From 17cc06c77ce65a6ec0f76daf0aa8fa99c3485c62 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 17 Mar 2015 16:01:05 +0100 Subject: [PATCH 33/79] 8075176: DISABLED_WARNINGS caused C++ compiler flags to get lost Reviewed-by: erikj, tbell --- make/common/NativeCompilation.gmk | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index c749532875e..001812585c2 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -392,12 +392,6 @@ define SetupNativeCompilationBody $1_EXTRA_CXXFLAGS+=$$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release) endif - # Pick up disabled warnings, if possible on this platform. - ifneq ($(DISABLE_WARNING_PREFIX),) - $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) - $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) - endif - ifeq ($$($1_DEBUG_SYMBOLS), true) ifeq ($(ENABLE_DEBUG_SYMBOLS), true) ifdef OPENJDK @@ -415,6 +409,9 @@ define SetupNativeCompilationBody endif endif + # If no C++ flags are explicitly set, default to using the C flags. + # After that, we can set additional C++ flags that should not interfere + # with the mechanism for copying the C flags by default. ifeq ($$($1_CXXFLAGS),) $1_CXXFLAGS:=$$($1_CFLAGS) endif @@ -427,6 +424,12 @@ define SetupNativeCompilationBody $1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER) endif + # Pick up disabled warnings, if possible on this platform. + ifneq ($(DISABLE_WARNING_PREFIX),) + $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) + $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) + endif + ifeq (NONE, $$($1_OPTIMIZATION)) $1_EXTRA_CFLAGS += $(C_O_FLAG_NONE) $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NONE) From f75ee76af6a24b01b7dbcf417583caf1a8d1ee28 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 18 Mar 2015 21:54:58 +0530 Subject: [PATCH 34/79] 8075448: nashorn parser API returns init variable tree object of a for loop after for loop statement tree object Reviewed-by: lagergren, hannesw, attila --- .../jdk/nashorn/api/tree/IRTranslator.java | 2 +- .../classes/jdk/nashorn/internal/ir/Node.java | 11 +++++ .../jdk/nashorn/internal/ir/VarNode.java | 42 +++++++++++++--- .../jdk/nashorn/internal/parser/Parser.java | 16 ++++-- nashorn/test/script/basic/JDK-8075448.js | 49 +++++++++++++++++++ .../script/nosecurity/parserapi.js.EXPECTED | 24 ++++----- 6 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 nashorn/test/script/basic/JDK-8075448.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java index cc0093e372c..73ec67f6f59 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java @@ -477,7 +477,7 @@ final class IRTranslator extends NodeVisitor { private List getOrderedStatements(final List stats) { final List statList = new ArrayList<>(stats); - statList.sort(Comparator.comparingInt(Node::getStart)); + statList.sort(Comparator.comparingInt(Node::getSourceOrder)); return statList; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java index 98c265aba40..b41952a1cac 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java @@ -183,6 +183,17 @@ public abstract class Node implements Cloneable, Serializable { return start; } + /** + * Integer to sort nodes in source order. This order is + * used by parser API to sort statements in correct order. + * By default, this is the start position of this node. + * + * @return int code to sort this node. + */ + public int getSourceOrder() { + return getStart(); + } + @Override protected Object clone() { try { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java index 1cee8cb59a6..1f10074f2d6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java @@ -45,6 +45,13 @@ public final class VarNode extends Statement implements Assignment { /** Is this a var statement (as opposed to a "var" in a for loop statement) */ private final int flags; + /** + * source order id to be used for this node. If this is -1, then we + * the default which is start position of this node. See also the + * method Node::getSourceOrder. + */ + private final int sourceOrder; + /** Flag for ES6 LET declaration */ public static final int IS_LET = 1 << 0; @@ -71,6 +78,7 @@ public final class VarNode extends Statement implements Assignment { private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) { super(varNode); + this.sourceOrder = -1; this.name = init == null ? name : name.setIsInitializedHere(); this.init = init; this.flags = flags; @@ -79,21 +87,41 @@ public final class VarNode extends Statement implements Assignment { /** * Constructor * - * @param lineNumber line number - * @param token token - * @param finish finish - * @param name name of variable - * @param init init node or null if just a declaration - * @param flags flags + * @param lineNumber line number + * @param token token + * @param finish finish + * @param name name of variable + * @param init init node or null if just a declaration + * @param flags flags */ public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init, final int flags) { - super(lineNumber, token, finish); + this(lineNumber, token, -1, finish, name, init, flags); + } + /** + * Constructor + * + * @param lineNumber line number + * @param token token + * @param sourceOrder source order + * @param finish finish + * @param name name of variable + * @param init init node or null if just a declaration + * @param flags flags + */ + public VarNode(final int lineNumber, final long token, final int sourceOrder, final int finish, final IdentNode name, final Expression init, final int flags) { + super(lineNumber, token, finish); + this.sourceOrder = sourceOrder; this.name = init == null ? name : name.setIsInitializedHere(); this.init = init; this.flags = flags; } + @Override + public int getSourceOrder() { + return sourceOrder == -1? super.getSourceOrder() : sourceOrder; + } + @Override public boolean isAssignment() { return hasInit(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index 66fe395c4dd..3d761812038 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -1066,6 +1066,10 @@ loop: * @param isStatement True if a statement (not used in a FOR.) */ private List variableStatement(final TokenType varType, final boolean isStatement) { + return variableStatement(varType, isStatement, -1); + } + + private List variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) { // VAR tested in caller. next(); @@ -1104,7 +1108,7 @@ loop: } // Allocate var node. - final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags); + final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name.setIsDeclaredHere(), init, varFlags); vars.add(var); appendStatement(var); @@ -1211,6 +1215,10 @@ loop: private void forStatement() { final long forToken = token; final int forLine = line; + // start position of this for statement. This is used + // for sort order for variables declared in the initialzer + // part of this 'for' statement (if any). + final int forStart = Token.descPosition(forToken); // When ES6 for-let is enabled we create a container block to capture the LET. final int startLine = start; final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; @@ -1243,7 +1251,7 @@ loop: switch (type) { case VAR: // Var declaration captured in for outer block. - vars = variableStatement(type, false); + vars = variableStatement(type, false, forStart); break; case SEMICOLON: break; @@ -1253,12 +1261,12 @@ loop: flags |= ForNode.PER_ITERATION_SCOPE; } // LET/CONST declaration captured in container block created above. - vars = variableStatement(type, false); + vars = variableStatement(type, false, forStart); break; } if (env._const_as_var && type == CONST) { // Var declaration captured in for outer block. - vars = variableStatement(TokenType.VAR, false); + vars = variableStatement(TokenType.VAR, false, forStart); break; } diff --git a/nashorn/test/script/basic/JDK-8075448.js b/nashorn/test/script/basic/JDK-8075448.js new file mode 100644 index 00000000000..3f5e1fd0fa9 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8075448.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * JDK-8075448: nashorn parser API returns init variable tree object of a for + * loop after for loop statement tree object + * + * @test + * @option -scripting + * @run + */ + +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var ForLoopTree = Java.type("jdk.nashorn.api.tree.ForLoopTree"); +var VariableTree = Java.type("jdk.nashorn.api.tree.VariableTree"); +var parser = Parser.create(); + +var code = < Date: Wed, 18 Mar 2015 23:14:12 +0530 Subject: [PATCH 35/79] 8075454: Anonymous functions have internal names exposed via parser API Reviewed-by: hannesw, lagergren --- .../api/tree/FunctionDeclarationTreeImpl.java | 2 +- nashorn/test/script/basic/JDK-8075454.js | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/basic/JDK-8075454.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java index c1ca8c54198..b53c008a5b0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java @@ -43,7 +43,7 @@ final class FunctionDeclarationTreeImpl extends StatementTreeImpl assert node.getInit() instanceof FunctionNode : "function expected"; funcNode = (FunctionNode)node.getInit(); assert funcNode.isDeclared() : "function declaration expected"; - funcName = node.getName().getName(); + funcName = funcNode.isAnonymous()? null : node.getName().getName(); this.params = params; this.body = body; } diff --git a/nashorn/test/script/basic/JDK-8075454.js b/nashorn/test/script/basic/JDK-8075454.js new file mode 100644 index 00000000000..91e30b8f74f --- /dev/null +++ b/nashorn/test/script/basic/JDK-8075454.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * JDK-8075454: Anonymous functions have internal names exposed via parser API + * + * @test + * @option -scripting + * @run + */ + +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var parser = Parser.create(); + +var ast = parser.parse("test.js", < Date: Thu, 19 Mar 2015 15:13:01 +0530 Subject: [PATCH 36/79] 8006996: Add a pretty printer that prints script source in nice form Reviewed-by: lagergren, hannesw --- nashorn/samples/prettyprinter.js | 642 +++++++++++++++++++++++++++++++ 1 file changed, 642 insertions(+) create mode 100644 nashorn/samples/prettyprinter.js diff --git a/nashorn/samples/prettyprinter.js b/nashorn/samples/prettyprinter.js new file mode 100644 index 00000000000..c9cec3cdab4 --- /dev/null +++ b/nashorn/samples/prettyprinter.js @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This script is a AST pretty printer for ECMAScript. It uses + * Nashorn parser API to parser given script and uses tree visitor + * to pretty print the AST to stdout as a script string. + */ + +var File = Java.type("java.io.File"); +var file = arguments.length == 0? new File(__FILE__) : new File(arguments[0]); +if (! file.isFile()) { + print(arguments[0] + " is not a file"); + exit(1); +} + +// Java classes used +var ArrayAccess = Java.type("jdk.nashorn.api.tree.ArrayAccessTree"); +var Block = Java.type("jdk.nashorn.api.tree.BlockTree"); +var FunctionDeclaration = Java.type("jdk.nashorn.api.tree.FunctionDeclarationTree"); +var FunctionExpression = Java.type("jdk.nashorn.api.tree.FunctionExpressionTree"); +var Identifier = Java.type("jdk.nashorn.api.tree.IdentifierTree"); +var Kind = Java.type("jdk.nashorn.api.tree.Tree.Kind"); +var MemberSelect = Java.type("jdk.nashorn.api.tree.MemberSelectTree"); +var ObjectLiteral = Java.type("jdk.nashorn.api.tree.ObjectLiteralTree"); +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1"); +var System = Java.type("java.lang.System"); + +// make a nashorn parser +var parser = Parser.create("-scripting", "--const-as-var"); + +// symbols for nashorn operators +var operatorSymbols = { + POSTFIX_INCREMENT: "++", + POSTFIX_DECREMENT: "--", + PREFIX_INCREMENT: "++", + PREFIX_DECREMENT: "--", + UNARY_PLUS: "+", + UNARY_MINUS: "-", + BITWISE_COMPLEMENT: "~", + LOGICAL_COMPLEMENT: "!", + DELETE: "delete ", + TYPEOF: "typeof ", + VOID: "void ", + COMMA: ",", + MULTIPLY: "*", + DIVIDE: "/", + REMINDER: "%", + PLUS: "+", + MINUS: "-", + LEFT_SHIFT: "<<", + RIGHT_SHIFT: ">>", + UNSIGNED_RIGHT_SHIFT: ">>>", + LESS_THAN: "<", + GREATER_THAN: ">", + LESS_THAN_EQUAL: "<=", + GREATER_THAN_EQUAL: ">=", + IN: "in", + EQUAL_TO: "==", + NOT_EQUAL_TO: "!=", + STRICT_EQUAL_TO: "===", + STRICT_NOT_EQUAL_TO: "!==", + AND: "&", + XOR: "^", + OR: "|", + CONDITIONAL_AND: "&&", + CONDITIONAL_OR: "||", + MULTIPLY_ASSIGNMENT: "*=", + DIVIDE_ASSIGNMENT: "/=", + REMINDER_ASSIGNMENT: "%=", + PLUS_ASSIGNMENT: "+=", + MINUS_ASSIGNMENT: "-=", + LEFT_SHIFT_ASSIGNMENT: "<<=", + RIGHT_SHIFT_ASSIGNMENT: ">>=", + UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: ">>>=", + AND_ASSIGNMENT: "&=", + XOR_ASSIGNMENT: "^=", + OR_ASSIGNMENT: "|=" +}; + +function operatorOf(kind) { + var name = kind.name(); + if (name in operatorSymbols) { + return operatorSymbols[name]; + } + throw "invalid operator: " + name; +} + +var gprint = print; + +function prettyPrint(file) { + var ast = parser.parse(file, gprint); + if (!ast) { + // failed to parse. don't print anything! + return; + } + + // AST visitor + var visitor; + // current indent level + var indentLevel = 0; + var out = System.out; + + function print(obj) { + out.print(String(obj)); + } + + function println(obj) { + obj? out.println(String(obj)) : out.println(); + } + + // semicolon and end-of-line + function eol() { + println(";"); + } + + // print indentation - 4 spaces per level + function indent() { + for (var i = 0; i < indentLevel; i++) { + // 4 spaces per indent level + print(" "); + } + } + + // escape string literals + function escapeString(str) { + // FIXME: incomplete, revisit again! + return str.replace(/[\\"']/g, '\\$&') + } + + // print a single statement (could be a block too) + function printStatement(stat, extra, end) { + if (stat instanceof Block) { + println(" {"); + printStatements(stat.statements, extra); + indent(); + print('}'); + typeof end != "undefined"? print(end) : println(); + } else { + println(); + indentLevel++; + try { + stat.accept(visitor, extra); + } finally { + indentLevel--; + } + } + } + + // print a statement list + function printStatements(stats, extra) { + indentLevel++; + try { + for each (var stat in stats) { + stat.accept(visitor, extra); + } + } finally { + indentLevel--; + } + } + + // function arguments, array literal elements. + function printCommaList(args, extra) { + var len = args.length; + for (var i = 0; i < len; i++) { + args[i].accept(visitor, extra); + if (i != len - 1) { + print(", "); + } + } + } + + // print function declarations and expressions + function printFunction(func, extra, end) { + // extra lines around function declarations for clarity + var funcDecl = (func instanceof FunctionDeclaration); + if (funcDecl) { + println(); + indent(); + } + print("function "); + if (func.name) { + print(func.name); + } + printFunctionBody(func, extra, end); + if (funcDecl) { + println(); + } + } + + // print function declaration/expression body + function printFunctionBody(func, extra, end) { + print('('); + var params = func.parameters; + if (params) { + printCommaList(params); + } + print(')'); + printStatement(func.body, extra, end); + } + + // print object literal property + function printProperty(node, extra, comma) { + var key = node.key; + var val = node.value; + var getter = node.getter; + var setter = node.setter; + + if (getter) { + print("get "); + } else if (setter) { + print("set "); + } + + if (typeof key == "string") { + print(key); + } else { + key.accept(visitor, extra); + } + + if (val) { + print(": "); + if (val instanceof FunctionExpression) { + printFunction(val, extra, comma? ',' : undefined); + } else { + val.accept(visitor, extra); + if (comma) print(','); + } + } else if (getter) { + printFunctionBody(getter, extra, comma? ',' : undefined); + } else if (setter) { + printFunctionBody(setter, extra, comma? ',' : undefined); + } + } + + + ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) { + visitAssignment: function(node, extra) { + node.variable.accept(visitor, extra); + print(" = "); + node.expression.accept(visitor, extra); + }, + + visitCompoundAssignment: function(node, extra) { + node.variable.accept(visitor, extra); + print(' ' + operatorOf(node.kind) + ' '); + node.expression.accept(visitor, extra); + }, + + visitBinary: function(node, extra) { + node.leftOperand.accept(visitor, extra); + print(' ' + operatorOf(node.kind) + ' '); + node.rightOperand.accept(visitor, extra); + }, + + visitBlock: function(node, extra) { + indent(); + println('{'); + printStatements(node.statements, extra); + indent(); + println('}'); + }, + + visitBreak: function(node, extra) { + indent(); + print("break"); + if (node.label) { + print(' ' + node.label); + } + eol(); + }, + + visitCase: function(node, extra) { + var expr = node.expression; + indent(); + if (expr) { + print("case "); + expr.accept(visitor, extra); + println(':'); + } else { + println("default:"); + } + + printStatements(node.statements, extra); + }, + + visitCatch: function(node, extra) { + indent(); + print("catch (" + node.parameter.name); + var cond = node.condition; + if (cond) { + print(" if "); + cond.accept(visitor, extra); + } + print(')'); + printStatement(node.block); + }, + + visitConditionalExpression: function(node, extra) { + print('('); + node.condition.accept(visitor, extra); + print(" ? "); + node.trueExpression.accept(visitor, extra); + print(" : "); + node.falseExpression.accept(visitor, extra); + print(')'); + }, + + visitContinue: function(node, extra) { + indent(); + print("continue"); + if (node.label) { + print(' ' + node.label); + } + eol(); + }, + + visitDebugger: function(node, extra) { + indent(); + print("debugger"); + eol(); + }, + + visitDoWhileLoop: function(node, extra) { + indent(); + print("do"); + printStatement(node.statement, extra); + indent(); + print("while ("); + node.condition.accept(visitor, extra); + print(')'); + eol(); + }, + + visitExpressionStatement: function(node, extra) { + indent(); + var expr = node.expression; + var objLiteral = expr instanceof ObjectLiteral; + if (objLiteral) { + print('('); + } + + expr.accept(visitor, extra); + if (objLiteral) { + print(')'); + } + eol(); + }, + + visitForLoop: function(node, extra) { + indent(); + print("for ("); + if (node.initializer) { + node.initializer.accept(visitor, extra); + } + + print(';'); + if (node.condition) { + node.condition.accept(visitor, extra); + } + print(';'); + if (node.update) { + node.update.accept(visitor, extra); + } + print(')'); + printStatement(node.statement); + }, + + visitForInLoop: function(node, extra) { + indent(); + print("for "); + if (node.forEach) { + print("each "); + } + print('('); + node.variable.accept(visitor, extra); + print(" in "); + node.expression.accept(visitor, extra); + print(')'); + printStatement(node.statement); + }, + + visitFunctionCall: function(node, extra) { + var func = node.functionSelect; + // We need parens around function selected + // in many non-simple cases. Eg. function + // expression created and called immediately. + // Such parens are not preserved in AST and so + // introduce here. + var simpleFunc = + (func instanceof ArrayAccess) || + (func instanceof Identifier) || + (func instanceof MemberSelect); + if (! simpleFunc) { + print('('); + } + func.accept(visitor, extra); + if (! simpleFunc) { + print(')'); + } + print('('); + printCommaList(node.arguments, extra); + print(')'); + }, + + visitFunctionDeclaration: function(node, extra) { + printFunction(node, extra); + }, + + visitFunctionExpression: function(node, extra) { + printFunction(node, extra); + }, + + visitIdentifier: function(node, extra) { + print(node.name); + }, + + visitIf: function(node, extra) { + indent(); + print("if ("); + node.condition.accept(visitor, extra); + print(')'); + printStatement(node.thenStatement); + var el = node.elseStatement; + if (el) { + indent(); + print("else"); + printStatement(el); + } + }, + + visitArrayAccess: function(node, extra) { + node.expression.accept(visitor, extra); + print('['); + node.index.accept(visitor, extra); + print(']'); + }, + + visitArrayLiteral: function(node, extra) { + print('['); + printCommaList(node.elements); + print(']'); + }, + + visitLabeledStatement: function(node, extra) { + indent(); + print(node.label); + print(':'); + printStatement(node.statement); + }, + + visitLiteral: function(node, extra) { + var val = node.value; + if (typeof val == "string") { + print("'" + escapeString(val) + "'"); + } else { + print(val); + } + }, + + visitParenthesized: function(node, extra) { + print('('); + node.expression.accept(visitor, extra); + print(')'); + }, + + visitReturn: function(node, extra) { + indent(); + print("return"); + if (node.expression) { + print(' '); + node.expression.accept(visitor, extra); + } + eol(); + }, + + visitMemberSelect: function(node, extra) { + node.expression.accept(visitor, extra); + print('.' + node.identifier); + }, + + visitNew: function(node, extra) { + print("new "); + node.constructorExpression.accept(visitor, extra); + }, + + visitObjectLiteral: function(node, extra) { + println('{'); + indentLevel++; + try { + var props = node.properties; + var len = props.length; + for (var p = 0; p < len; p++) { + var last = (p == len - 1); + indent(); + printProperty(props[p], extra, !last); + println(); + } + } finally { + indentLevel--; + } + indent(); + print('}'); + }, + + visitRegExpLiteral: function(node, extra) { + print('/' + node.pattern + '/'); + print(node.options); + }, + + visitEmptyStatement: function(node, extra) { + indent(); + eol(); + }, + + visitSwitch: function(node, extra) { + indent(); + print("switch ("); + node.expression.accept(visitor, extra); + println(") {"); + indentLevel++; + try { + for each (var c in node.cases) { + c.accept(visitor, extra); + } + } finally { + indentLevel--; + } + indent(); + println('}'); + }, + + visitThrow: function(node, extra) { + indent(); + print("throw "); + node.expression.accept(visitor, extra); + eol(); + }, + + visitCompilationUnit: function(node, extra) { + for each (var stat in node.sourceElements) { + stat.accept(visitor, extra); + } + }, + + visitTry: function(node, extra) { + indent(); + print("try"); + printStatement(node.block); + var catches = node.catches; + for each (var c in catches) { + c.accept(visitor, extra); + } + var finallyBlock = node.finallyBlock; + if (finallyBlock) { + indent(); + print("finally"); + printStatement(finallyBlock); + } + }, + + visitInstanceOf: function(node, extra) { + node.expression.accept(visitor, extra); + print(" instanceof "); + node.type.accept(visitor, extra); + }, + + visitUnary: function(node, extra) { + var kind = node.kind; + var prefix = kind != Kind.POSTFIX_INCREMENT && kind != Kind.POSTFIX_DECREMENT; + if (prefix) { + print(operatorOf(kind)); + } + node.expression.accept(visitor, extra); + if (!prefix) { + print(operatorOf(kind)); + } + }, + + visitVariable: function(node, extra) { + indent(); + print("var " + node.name); + var init = node.initializer; + if (init) { + print(" = "); + if (init instanceof FunctionExpression) { + printFunction(init, extra, ""); + } else { + init.accept(visitor, extra); + } + } + eol(); + }, + + visitWhileLoop: function(node, extra) { + indent(); + print("while ("); + node.condition.accept(visitor, extra); + print(')'); + printStatement(node.statement); + }, + + visitWith: function(node, extra) { + indent(); + print("with ("); + node.scope.accept(visitor, extra); + print(')'); + printStatement(node.statement); + } + }, null); +} + +prettyPrint(file); From da2900101844bed6506d929d2846308d12676cbc Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 19 Mar 2015 12:10:56 +0100 Subject: [PATCH 37/79] 8075495: Update jtreg bin location in configure Reviewed-by: alanb --- common/autoconf/generated-configure.sh | 4 ++-- common/autoconf/toolchain.m4 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 2ed5e8f5090..5ec19ef9854 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4369,7 +4369,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1425994551 +DATE_WHEN_GENERATED=1426763441 ############################################################################### # @@ -41174,7 +41174,7 @@ $as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." # jtreg win32 script works for everybody - JTREGEXE="$JT_HOME/win32/bin/jtreg" + JTREGEXE="$JT_HOME/bin/jtreg" if test ! -f "$JTREGEXE"; then as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5 diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 1de284e285e..7737ef8adf2 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -763,7 +763,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], BASIC_FIXUP_PATH([JT_HOME]) # jtreg win32 script works for everybody - JTREGEXE="$JT_HOME/win32/bin/jtreg" + JTREGEXE="$JT_HOME/bin/jtreg" if test ! -f "$JTREGEXE"; then AC_MSG_ERROR([JTReg executable does not exist: $JTREGEXE]) From c03dd06d9a011baa8397da3a7b94da48dd3effe3 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 19 Mar 2015 11:39:36 +0000 Subject: [PATCH 38/79] 8074381: java.lang.AssertionError during compiling Add extra functional interface check to prevent crash during code generation Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Attr.java | 12 +++++ .../tools/javac/lambda/8074381/T8074381a.java | 33 ++++++++++++++ .../tools/javac/lambda/8074381/T8074381a.out | 4 ++ .../tools/javac/lambda/8074381/T8074381b.java | 44 +++++++++++++++++++ .../tools/javac/lambda/8074381/T8074381b.out | 2 + 5 files changed, 95 insertions(+) create mode 100644 langtools/test/tools/javac/lambda/8074381/T8074381a.java create mode 100644 langtools/test/tools/javac/lambda/8074381/T8074381a.out create mode 100644 langtools/test/tools/javac/lambda/8074381/T8074381b.java create mode 100644 langtools/test/tools/javac/lambda/8074381/T8074381b.out diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 953c6129f12..ce01abdc960 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -40,11 +40,13 @@ import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.DeferredAttr.AttrMode; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.FreeTypeListener; import com.sun.tools.javac.jvm.*; +import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; @@ -2871,6 +2873,16 @@ public class Attr extends JCTree.Visitor { names.empty, List.of(fExpr.targets.head), ABSTRACT); if (csym != null) { chk.checkImplementations(env.tree, csym, csym); + try { + //perform an additional functional interface check on the synthetic class, + //as there may be spurious errors for raw targets - because of existing issues + //with membership and inheritance (see JDK-8074570). + csym.flags_field |= INTERFACE; + types.findDescriptorType(csym.type); + } catch (FunctionDescriptorLookupError err) { + resultInfo.checkContext.report(fExpr, + diags.fragment(Fragments.NoSuitableFunctionalIntfInst(fExpr.targets.head))); + } } } catch (Types.FunctionDescriptorLookupError ex) { JCDiagnostic cause = ex.getDiagnostic(); diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.java b/langtools/test/tools/javac/lambda/8074381/T8074381a.java new file mode 100644 index 00000000000..7b7b9dd6cc2 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074381 + * @summary java.lang.AssertionError during compiling + * @compile/fail/ref=T8074381a.out -XDrawDiagnostics T8074381a.java + */ +class T8074381a { + interface Sup { + boolean m(X x); + } + + interface Sub extends Sup { + boolean m(String s); + } + + void testRaw() { + Sub s1 = c -> true; + Sub s2 = Boolean::new; + Sub s3 = new Sub() { + @Override + public boolean m(String o) { return true; } + }; + } + + void testNonRaw() { + Sub s1 = c -> true; + Sub s2 = Boolean::new; + Sub s3 = new Sub() { + @Override + public boolean m(String o) { return true; } + }; + } +} diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.out b/langtools/test/tools/javac/lambda/8074381/T8074381a.out new file mode 100644 index 00000000000..f7ba487c586 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out @@ -0,0 +1,4 @@ +T8074381a.java:17:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:18:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:19:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup +3 errors diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381b.java b/langtools/test/tools/javac/lambda/8074381/T8074381b.java new file mode 100644 index 00000000000..3c28b8095e1 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.java @@ -0,0 +1,44 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074381 + * @summary java.lang.AssertionError during compiling + * @compile/fail/ref=T8074381b.out -XDrawDiagnostics T8074381b.java + */ +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +class T8074381b { + + @SuppressWarnings("unchecked") + public Invocation resolve(Handler handler) { + return new Invocation((t) -> handler.handle((String) t)); + } + + public static class Handler { + public void handle(String s) { + System.out.println(s); + } + } + + public static class Invocation { + public final ThrowingConsumer consumer; + + public Invocation(final ThrowingConsumer consumer) { + this.consumer = consumer; + } + } + + @FunctionalInterface + public interface ThrowingConsumer extends BiConsumer> { + @Override + default void accept(final T elem, final Consumer errorHandler) { + try { + acceptThrows(elem); + } catch (final Throwable e) { + errorHandler.accept(e); + } + } + + void acceptThrows(T elem) throws Throwable; + } +} diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381b.out b/langtools/test/tools/javac/lambda/8074381/T8074381b.out new file mode 100644 index 00000000000..7965e2e3734 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.out @@ -0,0 +1,2 @@ +T8074381b.java:14:16: compiler.err.cant.apply.symbol: kindname.constructor, Invocation, T8074381b.ThrowingConsumer, @383, kindname.class, T8074381b.Invocation, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: T8074381b.ThrowingConsumer)) +1 error From 582a4ebd92e60f95ae77d25eb00c6a146e727fab Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 19 Mar 2015 11:40:07 +0000 Subject: [PATCH 39/79] 8074100: Turn Type.Mapping into a true visitor Replace Type.Mapping with a true visitor in Types Reviewed-by: jlahoda, vromero --- .../com/sun/tools/javac/code/Type.java | 140 +++++++++--------- .../com/sun/tools/javac/code/Types.java | 51 +++---- .../com/sun/tools/javac/comp/Attr.java | 6 +- .../sun/tools/javac/comp/DeferredAttr.java | 26 +--- .../com/sun/tools/javac/comp/Infer.java | 40 ++--- .../com/sun/tools/javac/comp/Resolve.java | 5 +- .../com/sun/tools/javac/util/List.java | 9 ++ 7 files changed, 137 insertions(+), 140 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java index 502fc412e50..e2d3208c211 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java @@ -31,10 +31,12 @@ import java.util.EnumMap; import java.util.EnumSet; import java.util.Map; import java.util.Set; +import java.util.function.Function; import javax.lang.model.type.*; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Types.MapVisitor; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; import static com.sun.tools.javac.code.BoundKind.*; @@ -218,33 +220,81 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { /** An abstract class for mappings from types to types */ - public static abstract class Mapping { - private String name; - public Mapping(String name) { - this.name = name; + public static abstract class TypeMapping extends Types.MapVisitor implements Function { + + @Override + public Type apply(Type type) { + return visit(type); } - public abstract Type apply(Type t); - public String toString() { - return name; + + List visit(List ts, S s) { + return ts.map(t -> visit(t, s)); + } + + @Override + public Type visitClassType(ClassType t, S s) { + Type outer = t.getEnclosingType(); + Type outer1 = visit(outer, s); + List typarams = t.getTypeArguments(); + List typarams1 = visit(typarams, s); + if (outer1 == outer && typarams1 == typarams) return t; + else return new ClassType(outer1, typarams1, t.tsym, t.metadata); + } + + @Override + public Type visitWildcardType(WildcardType wt, S s) { + Type t = wt.type; + if (t != null) + t = visit(t, s); + if (t == wt.type) + return wt; + else + return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata); + } + + @Override + public Type visitArrayType(ArrayType t, S s) { + Type elemtype = t.elemtype; + Type elemtype1 = visit(elemtype, s); + if (elemtype1 == elemtype) return t; + else return new ArrayType(elemtype1, t.tsym, t.metadata); + } + + @Override + public Type visitMethodType(MethodType t, S s) { + List argtypes = t.argtypes; + Type restype = t.restype; + List thrown = t.thrown; + List argtypes1 = visit(argtypes, s); + Type restype1 = visit(restype, s); + List thrown1 = visit(thrown, s); + if (argtypes1 == argtypes && + restype1 == restype && + thrown1 == thrown) return t; + else return new MethodType(argtypes1, restype1, thrown1, t.tsym); + } + + @Override + public Type visitCapturedType(CapturedType t, S s) { + return visitTypeVar(t, s); + } + + @Override + public Type visitForAll(ForAll t, S s) { + return visit(t.qtype, s); } } /** map a type function over all immediate descendants of this type */ - public Type map(Mapping f) { - return this; + public Type map(TypeMapping mapping, Z arg) { + return mapping.visit(this, arg); } - /** map a type function over a list of types + /** map a type function over all immediate descendants of this type (no arg version) */ - public static List map(List ts, Mapping f) { - if (ts.nonEmpty()) { - List tail1 = map(ts.tail, f); - Type t = f.apply(ts.head); - if (tail1 != ts.tail || t != ts.head) - return tail1.prepend(t); - } - return ts; + public Type map(TypeMapping mapping) { + return mapping.visit(this, null); } /** Define a constant type, of the same kind as this type @@ -775,17 +825,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { return s.toString(); } - public Type map(Mapping f) { - //- System.err.println(" (" + this + ").map(" + f + ")");//DEBUG - Type t = type; - if (t != null) - t = f.apply(t); - if (t == type) - return this; - else - return new WildcardType(t, kind, tsym, bound, metadata); - } - @DefinedBy(Api.LANGUAGE_MODEL) public Type getExtendsBound() { if (kind == EXTENDS) @@ -1009,15 +1048,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { allparams().isEmpty(); } - public Type map(Mapping f) { - Type outer = getEnclosingType(); - Type outer1 = f.apply(outer); - List typarams = getTypeArguments(); - List typarams1 = map(typarams, f); - if (outer1 == outer && typarams1 == typarams) return this; - else return new ClassType(outer1, typarams1, tsym, metadata); - } - public boolean contains(Type elem) { return elem == this @@ -1248,12 +1278,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { }; } - public Type map(Mapping f) { - Type elemtype1 = f.apply(elemtype); - if (elemtype1 == elemtype) return this; - else return new ArrayType(elemtype1, tsym, metadata); - } - public boolean contains(Type elem) { return elem == this || elemtype.contains(elem); } @@ -1345,16 +1369,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { restype != null && restype.isErroneous(); } - public Type map(Mapping f) { - List argtypes1 = map(argtypes, f); - Type restype1 = f.apply(restype); - List thrown1 = map(thrown, f); - if (argtypes1 == argtypes && - restype1 == restype && - thrown1 == thrown) return this; - else return new MethodType(argtypes1, restype1, thrown1, tsym); - } - public boolean contains(Type elem) { return elem == this || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem); } @@ -1647,10 +1661,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { return qtype.isErroneous(); } - public Type map(Mapping f) { - return f.apply(qtype); - } - public boolean contains(Type elem) { return qtype.contains(elem); } @@ -1820,7 +1830,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { } protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) { - Type bound2 = toTypeVarMap.apply(bound).baseType(); + Type bound2 = bound.map(toTypeVarMap).baseType(); List prevBounds = bounds.get(ib); for (Type b : prevBounds) { //check for redundancy - use strict version of isSameType on tvars @@ -1831,15 +1841,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { notifyChange(EnumSet.of(ib)); } //where - Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") { + TypeMapping toTypeVarMap = new TypeMapping() { @Override - public Type apply(Type t) { - if (t.hasTag(UNDETVAR)) { - UndetVar uv = (UndetVar)t; - return uv.inst != null ? uv.inst : uv.qtype; - } else { - return t.map(this); - } + public Type visitUndetVar(UndetVar uv, Void _unused) { + return uv.inst != null ? uv.inst : uv.qtype; } }; @@ -2110,7 +2115,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror { public Type getEnclosingType() { return this; } public Type getReturnType() { return this; } public Type asSub(Symbol sym) { return this; } - public Type map(Mapping f) { return this; } public boolean isGenType(Type t) { return true; } public boolean isErroneous() { return true; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index b1386a94e0f..3964371b7dd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1766,10 +1766,11 @@ public class Types { // public List cvarLowerBounds(List ts) { - return map(ts, cvarLowerBoundMapping); + return ts.map(cvarLowerBoundMapping); } - private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") { - public Type apply(Type t) { + private final TypeMapping cvarLowerBoundMapping = new TypeMapping() { + @Override + public Type visitCapturedType(CapturedType t, Void _unused) { return cvarLowerBound(t); } }; @@ -1879,9 +1880,15 @@ public class Types { /** * Mapping to take element type of an arraytype */ - private Mapping elemTypeFun = new Mapping ("elemTypeFun") { - public Type apply(Type t) { - return elemtype(skipTypeVars(t, false)); + private TypeMapping elemTypeFun = new TypeMapping() { + @Override + public Type visitArrayType(ArrayType t, Void _unused) { + return t.elemtype; + } + + @Override + public Type visitTypeVar(TypeVar t, Void _unused) { + return visit(skipTypeVars(t, false)); } }; @@ -2177,7 +2184,7 @@ public class Types { } } // where - private SimpleVisitor erasure = new SimpleVisitor() { + private TypeMapping erasure = new TypeMapping() { private Type combineMetadata(final Type ty, final TypeMetadata md) { if (!md.isEmpty()) { @@ -2202,8 +2209,8 @@ public class Types { if (t.isPrimitive()) return t; /*fast special case*/ else { - Type erased = t.map(recurse ? erasureRecFun : erasureFun); - return combineMetadata(erased, t.getMetadata()); + //other cases already handled + return combineMetadata(t, t.getMetadata()); } } @@ -2223,23 +2230,10 @@ public class Types { Type erased = erasure(t.bound, recurse); return combineMetadata(erased, t.getMetadata()); } - - @Override - public Type visitErrorType(ErrorType t, Boolean recurse) { - return t; - } }; - private Mapping erasureFun = new Mapping ("erasure") { - public Type apply(Type t) { return erasure(t); } - }; - - private Mapping erasureRecFun = new Mapping ("erasureRecursive") { - public Type apply(Type t) { return erasureRecursive(t); } - }; - public List erasure(List ts) { - return Type.map(ts, erasureFun); + return erasure.visit(ts, false); } public Type erasureRecursive(Type t) { @@ -2247,7 +2241,7 @@ public class Types { } public List erasureRecursive(List ts) { - return Type.map(ts, erasureRecFun); + return erasure.visit(ts, true); } // @@ -3177,15 +3171,18 @@ public class Types { * changing all recursive bounds from old to new list. */ public List newInstances(List tvars) { - List tvars1 = Type.map(tvars, newInstanceFun); + List tvars1 = tvars.map(newInstanceFun); for (List l = tvars1; l.nonEmpty(); l = l.tail) { TypeVar tv = (TypeVar) l.head; tv.bound = subst(tv.bound, tvars, tvars1); } return tvars1; } - private static final Mapping newInstanceFun = new Mapping("newInstanceFun") { - public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); } + private static final TypeMapping newInstanceFun = new TypeMapping() { + @Override + public TypeVar visitTypeVar(TypeVar t, Void _unused) { + return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); + } }; // diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index ce01abdc960..c3b467de0e5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -3734,7 +3734,7 @@ public class Attr extends JCTree.Visitor { DeferredAttr.DeferredTypeMap checkDeferredMap = deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase); - argtypes = Type.map(argtypes, checkDeferredMap); + argtypes = argtypes.map(checkDeferredMap); if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { chk.warnUnchecked(env.tree.pos(), @@ -3742,7 +3742,7 @@ public class Attr extends JCTree.Visitor { kindName(sym), sym.name, rs.methodArguments(sym.type.getParameterTypes()), - rs.methodArguments(Type.map(argtypes, checkDeferredMap)), + rs.methodArguments(argtypes.map(checkDeferredMap)), kindName(sym.location()), sym.location()); owntype = new MethodType(owntype.getParameterTypes(), @@ -3766,7 +3766,7 @@ public class Attr extends JCTree.Visitor { return new Pair<>(sym, diag); } }; - List argtypes2 = Type.map(argtypes, + List argtypes2 = argtypes.map( rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, env.tree, sym, site, sym.name, argtypes2, typeargtypes); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index 84c59427cc2..8a7156155fd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -27,6 +27,7 @@ package com.sun.tools.javac.comp; import com.sun.source.tree.LambdaExpressionTree.BodyKind; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Type.TypeMapping; import com.sun.tools.javac.comp.Resolve.ResolveError; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; @@ -44,7 +45,6 @@ import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler; import java.util.ArrayList; import java.util.Collections; -import java.util.EnumMap; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -300,13 +300,6 @@ public class DeferredAttr extends JCTree.Visitor { } }; - DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() { - public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { - Assert.check(deferredAttrContext.mode == AttrMode.CHECK); - return dt.tree.type = Type.stuckType; - } - }; - /** * Policy for detecting stuck expressions. Different criteria might cause * an expression to be judged as stuck, depending on whether the check @@ -849,33 +842,24 @@ public class DeferredAttr extends JCTree.Visitor { /** an empty deferred attribution context - all methods throw exceptions */ final DeferredAttrContext emptyDeferredAttrContext; - /** The AttrMode to descriptive name mapping */ - private static final EnumMap deferredTypeMapDescriptions; - static { - deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class); - deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]"); - deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]"); - } - /** * Map a list of types possibly containing one or more deferred types * into a list of ordinary types. Each deferred type D is mapped into a type T, * where T is computed by retrieving the type that has already been * computed for D during a previous deferred attribution round of the given kind. */ - class DeferredTypeMap extends Type.Mapping { + class DeferredTypeMap extends TypeMapping { DeferredAttrContext deferredAttrContext; protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { - super(deferredTypeMapDescriptions.get(mode)); this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); } @Override - public Type apply(Type t) { + public Type visitType(Type t, Void _unused) { if (!t.hasTag(DEFERRED)) { - return t.map(this); + return super.visitType(t, null); } else { DeferredType dt = (DeferredType)t; return typeOf(dt); @@ -928,7 +912,7 @@ public class DeferredAttr extends JCTree.Visitor { return chk.checkNonVoid(pos, super.check(pos, found)); } }); - return super.apply(dt); + return super.visit(dt); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index d2da81aefb5..40d94858b54 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -25,6 +25,7 @@ package com.sun.tools.javac.comp; +import com.sun.tools.javac.code.Type.TypeMapping; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.TreeInfo; @@ -477,7 +478,7 @@ public class Infer { restype = syms.objectType; } - List paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step)); + List paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step)); List exType = spMethod != null ? spMethod.getThrownTypes() : List.of(syms.throwableType); // make it throw all exceptions @@ -495,9 +496,16 @@ public class Infer { (rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase); } - public Type apply(Type t) { - t = types.erasure(super.apply(t)); - if (t.hasTag(BOT)) + @Override + public Type visitClassType(ClassType t, Void aVoid) { + return types.erasure(t); + } + + @Override + public Type visitType(Type t, Void _unused) { + if (t.hasTag(DEFERRED)) { + return visit(super.visitType(t, null)); + } else if (t.hasTag(BOT)) // nulls type as the marker type Null (which has no instances) // infer as java.lang.Void for now t = types.boxedClass(syms.voidType).type; @@ -2046,23 +2054,19 @@ public class Infer { List freetypeListeners = List.nil(); public InferenceContext(List inferencevars) { - this.undetvars = Type.map(inferencevars, fromTypeVarFun); + this.undetvars = inferencevars.map(fromTypeVarFun); this.inferencevars = inferencevars; } //where - Mapping fromTypeVarFun = new Mapping("fromTypeVarFunWithBounds") { - // mapping that turns inference variables into undet vars - public Type apply(Type t) { - if (t.hasTag(TYPEVAR)) { - TypeVar tv = (TypeVar)t; - if (tv.isCaptured()) { - return new CapturedUndetVar((CapturedType)tv, types); - } else { - return new UndetVar(tv, types); - } - } else { - return t.map(this); - } + TypeMapping fromTypeVarFun = new TypeMapping() { + @Override + public Type visitTypeVar(TypeVar tv, Void aVoid) { + return new UndetVar(tv, types); + } + + @Override + public Type visitCapturedType(CapturedType t, Void aVoid) { + return new CapturedUndetVar(t, types); } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index ceefa7584ae..5e1fb9e8040 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -232,8 +232,7 @@ public class Resolve { } } String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; - List argtypes2 = Type.map(argtypes, - deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); + List argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, mostSpecificPos, currentResolutionContext.step, methodArguments(argtypes2), @@ -2259,7 +2258,7 @@ public class Resolve { (typeargtypes == null || !Type.isErroneous(typeargtypes)); } public List getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List argtypes) { - return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); + return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java index ee2cb9acab4..cab4f18eb0b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java @@ -33,6 +33,7 @@ import java.util.Iterator; import java.util.AbstractCollection; import java.util.ListIterator; import java.util.NoSuchElementException; +import java.util.function.Function; import java.util.stream.Collector; /** A class for generic linked lists. Links are supposed to be @@ -416,6 +417,14 @@ public class List extends AbstractCollection implements java.util.List return last; } + public List map(Function mapper) { + ListBuffer buf = new ListBuffer<>(); + for (A a : this) { + buf.add(mapper.apply(a)); + } + return buf.toList(); + } + @SuppressWarnings("unchecked") public static List convert(Class klass, List list) { if (list == null) From 24c51e1e1b95b8f94f917895b12e9f6a1083ce21 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 19 Mar 2015 11:40:47 +0000 Subject: [PATCH 40/79] 8048838: type inference performance regression Reduce redundant bounds before attempting to do pairwise lub computation during bound incorporation. Reviewed-by: vromero --- .../com/sun/tools/javac/code/Types.java | 65 ++++++++++++++--- .../com/sun/tools/javac/comp/Infer.java | 3 +- .../generics/inference/8048838/T8048838.java | 72 +++++++++++++++++++ 3 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 langtools/test/tools/javac/generics/inference/8048838/T8048838.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 3964371b7dd..70ce0435abb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -32,6 +32,8 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import java.util.function.BiPredicate; +import java.util.stream.Collector; import javax.tools.JavaFileObject; @@ -3405,42 +3407,87 @@ public class Types { return cl; } + /** + * Collect types into a new closure (using a @code{ClosureHolder}) + */ + public Collector> closureCollector(boolean minClosure, BiPredicate shouldSkip) { + return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip), + ClosureHolder::add, + ClosureHolder::merge, + ClosureHolder::closure); + } + //where + class ClosureHolder { + List closure; + final boolean minClosure; + final BiPredicate shouldSkip; + + ClosureHolder(boolean minClosure, BiPredicate shouldSkip) { + this.closure = List.nil(); + this.minClosure = minClosure; + this.shouldSkip = shouldSkip; + } + + void add(Type type) { + closure = insert(closure, type, shouldSkip); + } + + ClosureHolder merge(ClosureHolder other) { + closure = union(closure, other.closure, shouldSkip); + return this; + } + + List closure() { + return minClosure ? closureMin(closure) : closure; + } + } + + BiPredicate basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym; + /** * Insert a type in a closure */ - public List insert(List cl, Type t) { + public List insert(List cl, Type t, BiPredicate shouldSkip) { if (cl.isEmpty()) { return cl.prepend(t); - } else if (t.tsym == cl.head.tsym) { + } else if (shouldSkip.test(t, cl.head)) { return cl; } else if (t.tsym.precedes(cl.head.tsym, this)) { return cl.prepend(t); } else { // t comes after head, or the two are unrelated - return insert(cl.tail, t).prepend(cl.head); + return insert(cl.tail, t, shouldSkip).prepend(cl.head); } } + public List insert(List cl, Type t) { + return insert(cl, t, basicClosureSkip); + } + /** * Form the union of two closures */ - public List union(List cl1, List cl2) { + public List union(List cl1, List cl2, BiPredicate shouldSkip) { if (cl1.isEmpty()) { return cl2; } else if (cl2.isEmpty()) { return cl1; - } else if (cl1.head.tsym == cl2.head.tsym) { - return union(cl1.tail, cl2.tail).prepend(cl1.head); + } else if (shouldSkip.test(cl1.head, cl2.head)) { + return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head); } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) { - return union(cl1.tail, cl2).prepend(cl1.head); + return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) { - return union(cl1, cl2.tail).prepend(cl2.head); + return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head); } else { // unrelated types - return union(cl1.tail, cl2).prepend(cl1.head); + return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); } } + public List union(List cl1, List cl2) { + return union(cl1, cl2, basicClosureSkip); + } + /** * Intersect two closures */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index 40d94858b54..23c961ec638 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -873,7 +873,8 @@ public class Infer { @Override public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { Infer infer = inferenceContext.infer(); - List boundList = uv.getBounds(InferenceBound.UPPER); + List boundList = uv.getBounds(InferenceBound.UPPER).stream() + .collect(infer.types.closureCollector(true, infer.types::isSameType)); List boundListTail = boundList.tail; while (boundList.nonEmpty()) { List tmpTail = boundListTail; diff --git a/langtools/test/tools/javac/generics/inference/8048838/T8048838.java b/langtools/test/tools/javac/generics/inference/8048838/T8048838.java new file mode 100644 index 00000000000..162d94c5f97 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8048838/T8048838.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/* + * @test + * @bug 8048838 + * @summary type inference performance regression + * @compile T8048838.java + */ +class T8048838 { + + + T1 foo(T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8, T9 x9, T10 x10, T11 x11, T12 x12, + T13 x13, T14 x14, T15 x15, T16 x16, T17 x17, T18 x18, T19 x19, T20 x20, T21 x21, T22 x22, + T23 x23, T24 x24, T25 x25, T26 x26, T27 x27, T28 x28, T29 x29, T30 x30, T31 x31, T32 x32, + T33 x33, T34 x34, T35 x35, T36 x36, T37 x37, T38 x38, T39 x39, T40 x40, T41 x41, T42 x42, + T43 x43, T44 x44, T45 x45, T46 x46, T47 x47, T48 x48, T49 x49, T50 x50, T51 x51, T52 x52, + T53 x53, T54 x54, T55 x55, T56 x56, T57 x57, T58 x58, T59 x59, T60 x60, T61 x61, T62 x62, + T63 x63, T64 x64, T65 x65, T66 x66, T67 x67, T68 x68, T69 x69, T70 x70, T71 x71, T72 x72, + T73 x73, T74 x74, T75 x75, T76 x76, T77 x77, T78 x78, T79 x79, T80 x80, T81 x81, T82 x82, + T83 x83, T84 x84, T85 x85, T86 x86, T87 x87, T88 x88, T89 x89, T90 x90, T91 x91, T92 x92, + T93 x93, T94 x94, T95 x95, T96 x96, T97 x97, T98 x98, T99 x99, T100 x100) { return null; } + + Object test() { + return foo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100); // type inference expected + } +} From 4d20e7cb9b179b065c255da90d0cddda4cabff87 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Thu, 19 Mar 2015 15:28:22 +0100 Subject: [PATCH 41/79] 8075515: AIX: cleanup xlc options and use -bernotok to detect missing symbols at build time Reviewed-by: erikj --- common/autoconf/flags.m4 | 7 ++++--- common/autoconf/generated-configure.sh | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 045a7922b2f..84df8837c7e 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -481,9 +481,8 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" fi if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then @@ -762,6 +761,8 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -liconv -bexpall -bernotok" fi # Customize LDFLAGS for executables diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 5ec19ef9854..d7648b21e96 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4369,7 +4369,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1426763441 +DATE_WHEN_GENERATED=1426774983 ############################################################################### # @@ -42373,9 +42373,8 @@ $as_echo "$ac_cv_c_bigendian" >&6; } CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" fi if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then @@ -42669,6 +42668,8 @@ fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -liconv -bexpall -bernotok" fi # Customize LDFLAGS for executables From c399e03fe203aa5b82b0dbff26acb17a8fe7ed04 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 19 Mar 2015 16:23:21 +0000 Subject: [PATCH 42/79] 8075509: List.map should return itself if list is unchanged Fix List.map to match semantics of old Type.map Reviewed-by: jlahoda --- .../share/classes/com/sun/tools/javac/util/List.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java index cab4f18eb0b..53990dc74e7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java @@ -417,12 +417,15 @@ public class List extends AbstractCollection implements java.util.List return last; } + @SuppressWarnings("unchecked") public List map(Function mapper) { - ListBuffer buf = new ListBuffer<>(); - for (A a : this) { - buf.add(mapper.apply(a)); + if (nonEmpty()) { + List tail1 = tail.map(mapper); + Z head1 = mapper.apply(head); + if (tail1 != tail || head1 != head) + return tail1.prepend(head1); } - return buf.toList(); + return (List)this; } @SuppressWarnings("unchecked") From 2953ddaf4f5f4f202b2a74b336e2c354ebf19056 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:17 -0700 Subject: [PATCH 43/79] Added tag jdk9-b55 for changeset 5d1b73337681 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 26a93cd5862..289a8ebab69 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -297,3 +297,4 @@ d1f37d39ff2421f956a6ddf316cf763807bc3363 jdk9-b50 1822e59f17121b09e7899cf338cfb6e37fe5fceb jdk9-b52 d6ed47125a76cd1cf8a100568507bfb5e9669d9f jdk9-b53 cb7367141e910e265b8344a8facee740bd1e5467 jdk9-b54 +0c37a832458f0e0b7d2a3f1a6f69aeae311aeb18 jdk9-b55 From 8406d7ff8eb40c02220297729445f52798756b44 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:19 -0700 Subject: [PATCH 44/79] Added tag jdk9-b55 for changeset 18da5010f46a --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 69d0b8f6543..047cd1035a0 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -457,3 +457,4 @@ e0947f58c9c1426aa0d98b98ebb78357b27a7b99 jdk9-b50 9fb7fdc554db5be5c5b10f88f529ec3b870c44e3 jdk9-b52 effd5ef0c3eb4bb85aa975c489d6761dbf13ad6a jdk9-b53 c3b117fa5bdedfafd9ed236403e6d406911195b1 jdk9-b54 +be49ab55e5c498c5077bbf58c2737100d1992339 jdk9-b55 From c44b9df4a572b8f493f3b953da93b2f38531b475 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:19 -0700 Subject: [PATCH 45/79] Added tag jdk9-b55 for changeset 73b85977a990 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index c5b68217544..fd64f5a34f9 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -297,3 +297,4 @@ a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48 b8538bbb6f224ab1dabba579137099c166ad4724 jdk9-b52 aadc16ca5ab7d56f92ef9dbfa443595a939241b4 jdk9-b53 d469c5ad0c763e325a78e0af3016878a57dfc5cc jdk9-b54 +734ca5311a225711b79618f3e92f47f07c82154a jdk9-b55 From b080fe28b773e870aec3fa1192adb2b2fe34faed Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:21 -0700 Subject: [PATCH 46/79] Added tag jdk9-b55 for changeset 0331c66492b3 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index c4ae975ef76..df7e243ac25 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -297,3 +297,4 @@ e391de88e69b59d7c618387e3cf91032f6991ce9 jdk9-b47 57b26c883d54f45912bc3885ccad3c6b80960b1f jdk9-b52 d5b5a010a16688f188f5a9247ed873f5100b530c jdk9-b53 542c0c855ad467624cbedf11bff08e44b86b068d jdk9-b54 +2a460ce60ed47081f756f0cc0321d8e9ba7cac17 jdk9-b55 From a275baa0f1fe0d6050b2b785c85e723f77929774 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:22 -0700 Subject: [PATCH 47/79] Added tag jdk9-b55 for changeset 58a0852cabd5 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 4d619c61980..cacd4546124 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -300,3 +300,4 @@ bb9cf97a5ac6aa1aa2a1034676d64413071f58ea jdk9-b51 1d1e7704eca9c77ebe6a8705d17ac568801f7a3b jdk9-b52 b8fbe40efa97fe0753076ccc6dfc50747c7877d0 jdk9-b53 83a0cf0e08788c33872e1fe3e87bf9a0d1e59eaa jdk9-b54 +ca481b0492c82cc38fa0e6b746305ed88c26b4fd jdk9-b55 From 74ec9dddfb479185b37f05a99b675668d1178de5 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:23 -0700 Subject: [PATCH 48/79] Added tag jdk9-b55 for changeset 3fa4537eefef --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 6c1c4c33d69..4e2ce2b244e 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -297,3 +297,4 @@ a0dad230aeb3b0d5cfd5b0715029e48d50573f8c jdk9-b51 607ea68032cd4a4cf2c7a7a41fcb39602d6a75e2 jdk9-b52 6cb5f5c34009630749a40cefe116d143f0b2583e jdk9-b53 568a62ab7d764d7c74ac1d87387dbe500662b551 jdk9-b54 +d49e247dade61f29f771f09b2105857492241156 jdk9-b55 From 1df4a8aa4c8b154b1a8eaa380656f3d07c5f5471 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:26 -0700 Subject: [PATCH 49/79] Added tag jdk9-b55 for changeset 94880c5f1226 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 0d0e8539556..315de464668 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -297,3 +297,4 @@ e272d9be5f90edb6bb6b40f7816ec85eec0f5dc2 jdk9-b46 ee20efe0255d7ac6e06e88e06f7c72f6c6da7bf9 jdk9-b52 99ff00581f3633c1787bec21f2a8f3a2ffe57665 jdk9-b53 ed34864f3b43a7df394fce6c3f0bc86b70a5d686 jdk9-b54 +32a2e724988499e6f68611a65168c5f2fde0f6b9 jdk9-b55 From 7f20824ddabf25934441e311014070f35b24f29b Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 19 Mar 2015 12:59:27 -0700 Subject: [PATCH 50/79] Added tag jdk9-b55 for changeset 6fae74f3f890 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index b2a596b8216..4fa8971a714 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -288,3 +288,4 @@ f08660f30051ba0b38ad00e692979b37d107c9c4 jdk9-b48 fada76c29db9c792ad7127e674ef5337e15d2225 jdk9-b52 6cd23482ca9bd0caa6bfa6bf9064251178083d17 jdk9-b53 26460b897225010a4c7664eaff7a71f1156cacb3 jdk9-b54 +b2b332e64b7b2e06e25bccae9c0c0b585a03b4b5 jdk9-b55 From 2596979bfe566db25b03277a68a5bcd12e3b3d11 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 19 Mar 2015 18:38:26 -0700 Subject: [PATCH 51/79] 8075565: Define @intermittent jtreg keyword and mark intermittently failing jdk tests Reviewed-by: lancea --- jdk/test/TEST.ROOT | 2 +- jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java | 1 + .../java/lang/invoke/MethodHandles/CatchExceptionTest.java | 1 + jdk/test/java/lang/ref/OOMEInReferenceHandler.java | 1 + .../Inet6Address/serialize/Inet6AddressSerializationTest.java | 1 + jdk/test/java/net/SocketPermission/SocketPermissionTest.java | 1 + .../java/nio/channels/AsynchronousSocketChannel/Basic.java | 1 + jdk/test/java/nio/channels/Selector/Wakeup.java | 1 + .../nio/channels/ServerSocketChannel/AdaptServerSocket.java | 1 + .../spi/SelectorProvider/inheritedChannel/run_tests.sh | 4 ++-- jdk/test/java/nio/file/FileStore/Basic.java | 1 + jdk/test/java/nio/file/Files/InterruptCopy.java | 1 + .../Activatable/checkActivateRef/CheckActivateRef.java | 1 + jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java | 1 + .../UnicastRemoteObject/exportObject/GcDuringExport.java | 1 + jdk/test/javax/net/ssl/TLS/TestJSSE.java | 1 + 16 files changed, 17 insertions(+), 3 deletions(-) diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index 20863c62a87..0e6fa003234 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -2,7 +2,7 @@ # It also contains test-suite configuration information. # The list of keywords supported in the entire test suite -keys=2d dnd i18n +keys=2d dnd i18n intermittent # Tests that must run in othervm mode othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation diff --git a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java index 9a5580028a4..e5bce16e655 100644 --- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java +++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java @@ -26,6 +26,7 @@ * @run main/othervm LdapTimeoutTest * @bug 7094377 8000487 6176036 7056489 * @summary Timeout tests for ldap + * @key intermittent */ import java.net.Socket; diff --git a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java index 996ed526413..44e11e0985d 100644 --- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java +++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java @@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit; * @library /lib/testlibrary/jsr292 /lib/testlibrary/ * @compile CatchExceptionTest.java * @run main/othervm -esa test.java.lang.invoke.MethodHandles.CatchExceptionTest + * @key intermittent */ public class CatchExceptionTest { private static final List> ARGS_CLASSES; diff --git a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java index cd09b070aa8..95383787a93 100644 --- a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java +++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java @@ -27,6 +27,7 @@ * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler * @author peter.levart@gmail.com + * @key intermittent */ import java.lang.ref.*; diff --git a/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java b/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java index b6431acc84b..a969986ae8c 100644 --- a/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java +++ b/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java @@ -42,6 +42,7 @@ import java.util.List; * @test * @bug 8007373 * @summary jdk7 backward compatibility serialization problem + * @key intermittent */ public class Inet6AddressSerializationTest { diff --git a/jdk/test/java/net/SocketPermission/SocketPermissionTest.java b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java index 3188f8695a8..5cc25ab0c02 100644 --- a/jdk/test/java/net/SocketPermission/SocketPermissionTest.java +++ b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java @@ -27,6 +27,7 @@ * @summary SocketPermission tests for legacy socket types * @library ../../../lib/testlibrary * @run testng/othervm/policy=policy SocketPermissionTest + * @key intermittent */ import java.io.IOException; import java.net.DatagramPacket; diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index 9442f9b5408..8f9e426a740 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -25,6 +25,7 @@ * @bug 4607272 6842687 6878369 6944810 7023403 * @summary Unit test for AsynchronousSocketChannel * @run main Basic -skipSlowConnectTest + * @key intermittent */ import java.nio.ByteBuffer; diff --git a/jdk/test/java/nio/channels/Selector/Wakeup.java b/jdk/test/java/nio/channels/Selector/Wakeup.java index 40aa71729c8..e51bd1d38fc 100644 --- a/jdk/test/java/nio/channels/Selector/Wakeup.java +++ b/jdk/test/java/nio/channels/Selector/Wakeup.java @@ -25,6 +25,7 @@ * @bug 6405995 * @summary Unit test for selector wakeup and interruption * @library .. + * @key intermittent */ import java.io.*; diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java index f0a44a5ad1a..3c88d408853 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java @@ -23,6 +23,7 @@ /* @test * @summary Unit test for server-socket-channel adaptors + * @key intermittent */ import java.io.*; diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh index 37d56a84ed9..8c6355073d6 100644 --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh @@ -24,12 +24,12 @@ # # @test -# @bug 4673940 -# @bug 4930794 +# @bug 4673940 4930794 # @summary Unit tests for inetd feature # # @build StateTest StateTestService EchoTest EchoService CloseTest Launcher Util # @run shell run_tests.sh +# @key intermittent os=`uname -s` diff --git a/jdk/test/java/nio/file/FileStore/Basic.java b/jdk/test/java/nio/file/FileStore/Basic.java index 176efef87a2..465f3f2a8d2 100644 --- a/jdk/test/java/nio/file/FileStore/Basic.java +++ b/jdk/test/java/nio/file/FileStore/Basic.java @@ -25,6 +25,7 @@ * @bug 4313887 6873621 6979526 7006126 7020517 * @summary Unit test for java.nio.file.FileStore * @library .. + * @key intermittent */ import java.nio.file.*; diff --git a/jdk/test/java/nio/file/Files/InterruptCopy.java b/jdk/test/java/nio/file/Files/InterruptCopy.java index c83479c9e46..29cfa006e40 100644 --- a/jdk/test/java/nio/file/Files/InterruptCopy.java +++ b/jdk/test/java/nio/file/Files/InterruptCopy.java @@ -25,6 +25,7 @@ * @bug 4313887 6993267 * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option * @library .. + * @key intermittent */ import java.nio.file.*; diff --git a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java index f37fdec54dc..58f1f253517 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java +++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java @@ -39,6 +39,7 @@ * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef + * @key intermittent */ import java.io.*; diff --git a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java index 2eba1d6ac1a..88188639322 100644 --- a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java +++ b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java @@ -38,6 +38,7 @@ * @library ../../testlibrary * @build TestLibrary ReferenceRegistryStub * @run main/othervm InterfaceHash + * @key intermittent */ import java.lang.reflect.Constructor; diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java index 4e65d8049b7..5f4036db5e5 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java @@ -31,6 +31,7 @@ * @summary GC'ing objects whilst being exported to RMI should not cause exceptions * @author Neil Richards , * @run main/othervm GcDuringExport + * @key intermittent */ import java.rmi.Remote; diff --git a/jdk/test/javax/net/ssl/TLS/TestJSSE.java b/jdk/test/javax/net/ssl/TLS/TestJSSE.java index 6e440836b1f..756a5226f96 100644 --- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java +++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java @@ -70,6 +70,7 @@ import java.security.Security; * -DCLIENT_PROTOCOL=DEFAULT -Djdk.tls.client.protocols=TLSv1.2 * -DCIPHER=SSL_RSA_WITH_RC4_128_MD5 * TestJSSE javax.net.ssl.SSLHandshakeException + * @key intermittent * */ From 636ae484e4b8dff3aa71e7fcf8904fcf6cd71968 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Fri, 20 Mar 2015 16:01:59 +0800 Subject: [PATCH 52/79] 8048147: Privilege tests with JAAS Subject.doAs Reviewed-by: weijun --- .../auth/Subject/doAs/NestedActions.java | 541 ++++++++++++++++++ .../auth/Subject/doAs/policy.expect.ace | 27 + .../auth/Subject/doAs/policy.expect.pae | 19 + .../auth/Subject/doAs/policy.one.principal | 36 ++ .../auth/Subject/doAs/policy.two.principals | 37 ++ 5 files changed, 660 insertions(+) create mode 100644 jdk/test/javax/security/auth/Subject/doAs/NestedActions.java create mode 100644 jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace create mode 100644 jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae create mode 100644 jdk/test/javax/security/auth/Subject/doAs/policy.one.principal create mode 100644 jdk/test/javax/security/auth/Subject/doAs/policy.two.principals diff --git a/jdk/test/javax/security/auth/Subject/doAs/NestedActions.java b/jdk/test/javax/security/auth/Subject/doAs/NestedActions.java new file mode 100644 index 00000000000..bde0aed1112 --- /dev/null +++ b/jdk/test/javax/security/auth/Subject/doAs/NestedActions.java @@ -0,0 +1,541 @@ +/* + * 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 + * 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. + */ + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; +import jdk.testlibrary.ProcessTools; + +/** + * @test + * @bug 8048147 + * @summary Check if proper AccessControlException is thrown + * in case of nested Subject.doAs() invocations + * when one of protection domains doesn't have permissions + * + * @library /lib/testlibrary + * + * @run main NestedActions jar NestedActionsACE.jar + * NestedActionsACE.class Utils.class + * @run main NestedActions jar NestedActionsPAE.jar + * NestedActionsPAE.class Utils.class + * @run main NestedActions jar NestedActionsOnePrincipal.jar + * NestedActionsOnePrincipal.class Utils.class + * @run main NestedActions jar NestedActionsTwoPrincipals.jar + * NestedActionsTwoPrincipals.class Utils.class + * @run main NestedActions jar WriteToFileAction.jar + * WriteToFileAction.class + * @run main NestedActions jar WriteToFileNegativeAction.jar + * WriteToFileNegativeAction.class + * @run main NestedActions jar WriteToFileExceptionAction.jar + * WriteToFileExceptionAction.class + * @run main NestedActions jar ReadFromFileAction.jar + * ReadFromFileAction.class + * @run main NestedActions jar ReadFromFileNegativeAction.jar + * ReadFromFileNegativeAction.class + * @run main NestedActions jar ReadFromFileExceptionAction.jar + * ReadFromFileExceptionAction.class + * @run main NestedActions jar ReadPropertyAction.jar + * ReadPropertyAction.class + * @run main NestedActions jar ReadPropertyNegativeAction.jar + * ReadPropertyNegativeAction.class + * @run main NestedActions jar ReadPropertyExceptionAction.jar + * ReadPropertyExceptionAction.class ReadPropertyException.class + * + * @run main NestedActions NestedActionsACE policy.expect.ace + * NestedActionsACE.jar WriteToFileNegativeAction.jar + * ReadFromFileNegativeAction.jar ReadPropertyNegativeAction.jar + * @run main NestedActions NestedActionsPAE policy.expect.pae + * NestedActionsPAE.jar WriteToFileExceptionAction.jar + * ReadFromFileExceptionAction.jar ReadPropertyExceptionAction.jar + * @run main NestedActions NestedActionsOnePrincipal policy.one.principal + * NestedActionsOnePrincipal.jar WriteToFileAction.jar + * ReadFromFileAction.jar ReadPropertyAction.jar + * @run main NestedActions NestedActionsTwoPrincipals policy.two.principals + * NestedActionsTwoPrincipals.jar WriteToFileAction.jar + * ReadFromFileAction.jar ReadPropertyAction.jar + */ +public class NestedActions { + + static final String file = "NestedActions.tmp"; + static final String PS = System.getProperty("path.separator"); + static final String FS = System.getProperty("file.separator"); + static final String TEST_CLASSES = System.getProperty("test.classes"); + static final String TEST_SOURCES = System.getProperty("test.src"); + static final String JAVA_OPTS = System.getProperty("test.java.opts"); + static final String JAVA = System.getProperty("java.home") + + FS + "bin" + FS + "java"; + + public static void main(String[] args) throws IOException { + if (args.length > 0) { + if ("jar".equals(args[0]) && args.length > 2) { + createJar(args[1], + Arrays.copyOfRange(args, 2, args.length)); + } else { + runJava(args); + } + } else { + throw new RuntimeException("Wrong parameters"); + } + } + + static void createJar(String dest, String... files) throws IOException { + System.out.println("Create " + dest + " with the following content:"); + try (JarOutputStream jos = new JarOutputStream( + new FileOutputStream(dest), new Manifest())) { + for (String file : files) { + System.out.println(" " + file); + jos.putNextEntry(new JarEntry(file)); + try (FileInputStream fis = new FileInputStream( + TEST_CLASSES + FS + file)) { + fis.transferTo(jos); + } + } + } + } + + static void runJava(String[] args) { + if (args == null || args.length < 3) { + throw new IllegalArgumentException("wrong parameters"); + } + + List cmds = new ArrayList<>(); + cmds.add(JAVA); + StringBuilder sb = new StringBuilder(); + cmds.add("-classpath"); + for (int i=2; i + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Duke principal) + * + * The test expects PrivilegedActionException + * that caused by AccessControlEception. + */ +class NestedActionsPAE { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + try { + WriteToFileExceptionAction writeToFile = + new WriteToFileExceptionAction(NestedActions.file); + Subject.doAs(subject, writeToFile); + throw new RuntimeException( + "Test failed: no PrivilegedActionException thrown"); + } catch (PrivilegedActionException pae) { + System.out.println( + "PrivilegedActionException thrown as expected: " + + pae); + + // check if AccessControlException caused PrivilegedActionException + Throwable exception = pae.getException(); + do { + if (!(exception instanceof PrivilegedActionException)) { + break; + } + exception = ((PrivilegedActionException) exception). + getException(); + } while (true); + + if (!(exception instanceof ReadPropertyException)) { + throw new RuntimeException( + "Test failed: PrivilegedActionException " + + "was not caused by ReadPropertyException"); + } + + exception = exception.getCause(); + if (!(exception instanceof AccessControlException)) { + throw new RuntimeException( + "Test failed: PrivilegedActionException " + + "was not caused by ReadPropertyException"); + } + + System.out.println( + "Test passed: PrivilegedActionException " + + "was caused by AccessControlException"); + } + } +} + +/** + * Test for nested Subject.doAs() invocation: + * + * WriteToFileAction (CN=Duke principal) -> + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Duke principal) + */ +class NestedActionsOnePrincipal { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + WriteToFileAction writeToFile = + new WriteToFileAction(NestedActions.file); + Subject.doAs(subject, writeToFile); + } +} + +/** + * Test for nested Subject.doAs() invocation: + * + * WriteToFileAction (CN=Duke principal) -> + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Java principal) + */ +class NestedActionsTwoPrincipals { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + Subject anotherSubject = new Subject(); + anotherSubject.getPrincipals().add(new X500Principal("CN=Java")); + ReadFromFileAction readFromFile + = new ReadFromFileAction(NestedActions.file, anotherSubject); + WriteToFileAction writeToFile + = new WriteToFileAction(NestedActions.file, readFromFile); + Subject.doAs(subject, writeToFile); + } +} + +/** + * Helper class. + */ +class Utils { + + static void readFile(String filename) { + System.out.println("ReadFromFileAction: try to read " + filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + try (FileInputStream fis = new FileInputStream(filename)) { + // do nothing + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException", e); + } + } + + static void writeFile(String filename) { + System.out.println("WriteToFileAction: try to write to " + filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + try (BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(filename))) { + bos.write(0); + bos.flush(); + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException", e); + } + } + +} + +class WriteToFileAction implements PrivilegedAction { + + private final String filename; + private final PrivilegedAction nextAction; + + WriteToFileAction(String filename, PrivilegedAction nextAction) { + this.filename = filename; + this.nextAction = nextAction; + } + + WriteToFileAction(String filename) { + this(filename, new ReadFromFileAction(filename)); + } + + @Override + public Object run() { + Utils.writeFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + return Subject.doAs(subject, nextAction); + } + +} + +class ReadFromFileAction implements PrivilegedAction { + + private final String filename; + private final Subject anotherSubject; + + ReadFromFileAction(String filename) { + this(filename, null); + } + + ReadFromFileAction(String filename, Subject anotherSubject) { + this.filename = filename; + this.anotherSubject = anotherSubject; + } + + @Override + public Object run() { + Utils.readFile(filename); + + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadPropertyAction readProperty = new ReadPropertyAction(); + if (anotherSubject != null) { + return Subject.doAs(anotherSubject, readProperty); + } else { + return Subject.doAs(subject, readProperty); + } + } + +} + +class ReadPropertyAction implements PrivilegedAction { + + @Override + public java.lang.Object run() { + System.out.println("ReadPropertyAction: " + + "try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + + return null; + } + +} + +class WriteToFileNegativeAction implements PrivilegedAction { + + private final String filename; + + public WriteToFileNegativeAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() { + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + + try { + Utils.writeFile(filename); + new File(filename).delete(); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + ReadFromFileNegativeAction readFromFile + = new ReadFromFileNegativeAction(filename); + return Subject.doAs(subject, readFromFile); + } + +} + +class ReadFromFileNegativeAction implements PrivilegedAction { + + private final String filename; + + public ReadFromFileNegativeAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() { + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + + try { + Utils.readFile(filename); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + ReadPropertyNegativeAction readProperty = + new ReadPropertyNegativeAction(); + return Subject.doAs(subject, readProperty); + } + +} + +class ReadPropertyNegativeAction implements PrivilegedAction { + + @Override + public java.lang.Object run() { + System.out.println("Try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + + try { + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + return null; + } + +} + +class WriteToFileExceptionAction implements PrivilegedExceptionAction { + + private final String filename; + + WriteToFileExceptionAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() throws Exception { + Utils.writeFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadFromFileExceptionAction readFromFile = + new ReadFromFileExceptionAction(filename); + return Subject.doAs(subject, readFromFile); + } + +} + +class ReadFromFileExceptionAction implements PrivilegedExceptionAction { + + private final String filename; + + ReadFromFileExceptionAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() throws Exception { + Utils.readFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadPropertyExceptionAction readProperty = + new ReadPropertyExceptionAction(); + return Subject.doAs(subject, readProperty); + } + +} + +class ReadPropertyExceptionAction implements PrivilegedExceptionAction { + + @Override + public java.lang.Object run() throws Exception { + System.out.println("Try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + + try { + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + throw new ReadPropertyException(ace); + } + } + +} + +class ReadPropertyException extends Exception { + + ReadPropertyException(Throwable cause) { + super(cause); + } +} diff --git a/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace new file mode 100644 index 00000000000..ac336192d3c --- /dev/null +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace @@ -0,0 +1,27 @@ +// this code has limited permissions that should cause ACE +grant codeBase "file:NestedActionsACE.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; +}; + +grant codeBase "file:WriteToFileNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadFromFileNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadPropertyNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; \ No newline at end of file diff --git a/jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae new file mode 100644 index 00000000000..c37cd7ec132 --- /dev/null +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae @@ -0,0 +1,19 @@ +grant codeBase "file:NestedActionsPAE.jar" { + permission java.security.AllPermission; +}; + +grant codeBase "file:WriteToFileExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadFromFileExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +// this code has limited permissions that should cause ACE +grant codeBase "file:ReadPropertyExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; +}; diff --git a/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal new file mode 100644 index 00000000000..1f560edb25a --- /dev/null +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal @@ -0,0 +1,36 @@ +grant codeBase "file:NestedActionsOnePrincipal.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:WriteToFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:ReadFromFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read"; +}; + +grant codeBase "file:ReadPropertyAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; +}; \ No newline at end of file diff --git a/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals new file mode 100644 index 00000000000..c260781261c --- /dev/null +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals @@ -0,0 +1,37 @@ +grant codeBase "file:NestedActionsTwoPrincipals.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write,delete"; +}; + +grant codeBase "file:WriteToFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:ReadFromFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke"{ + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read"; +}; + +grant codeBase "file:ReadPropertyAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Java" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; +}; \ No newline at end of file From b7d77b12979baa5dc133c014c43102b7f8854a17 Mon Sep 17 00:00:00 2001 From: Sergey Lugovoy Date: Fri, 20 Mar 2015 13:19:47 +0300 Subject: [PATCH 53/79] 8068306: Tests for AST presentation Nashorn Parser API 8068304: Tests for Diagnostic listener for Nashorn Parser API 8068303: Create tests for Nashorn Parser API for create Tree from some different source and parameters Reviewed-by: sundar, lagergren --- nashorn/test/script/nosecurity/parser-args.js | 71 ++++ nashorn/test/script/nosecurity/parser.js | 92 +++++ .../script/nosecurity/treeapi/array_access.js | 55 +++ .../treeapi/array_access.js.EXPECTED | 109 ++++++ .../nosecurity/treeapi/array_literal.js | 49 +++ .../treeapi/array_literal.js.EXPECTED | 105 +++++ .../script/nosecurity/treeapi/assignment.js | 50 +++ .../nosecurity/treeapi/assignment.js.EXPECTED | 149 ++++++++ .../nosecurity/treeapi/assignmentExpr.js | 55 +++ .../treeapi/assignmentExpr.js.EXPECTED | 189 +++++++++ .../script/nosecurity/treeapi/binaryExpr.js | 66 ++++ .../nosecurity/treeapi/binaryExpr.js.EXPECTED | 359 ++++++++++++++++++ .../test/script/nosecurity/treeapi/block.js | 48 +++ .../nosecurity/treeapi/block.js.EXPECTED | 68 ++++ .../script/nosecurity/treeapi/breakStat.js | 56 +++ .../nosecurity/treeapi/breakStat.js.EXPECTED | 38 ++ .../test/script/nosecurity/treeapi/case.js | 59 +++ .../nosecurity/treeapi/case.js.EXPECTED | 109 ++++++ .../nosecurity/treeapi/compilationUnitTree.js | 41 ++ .../script/nosecurity/treeapi/condExpr.js | 45 +++ .../nosecurity/treeapi/condExpr.js.EXPECTED | 25 ++ .../script/nosecurity/treeapi/continueStat.js | 49 +++ .../treeapi/continueStat.js.EXPECTED | 32 ++ .../script/nosecurity/treeapi/debuggerStat.js | 45 +++ .../treeapi/debuggerStat.js.EXPECTED | 7 + .../script/nosecurity/treeapi/diagnostic.js | 78 ++++ .../nosecurity/treeapi/diagnostic.js.EXPECTED | 95 +++++ .../test/script/nosecurity/treeapi/dowhile.js | 52 +++ .../nosecurity/treeapi/dowhile.js.EXPECTED | 169 +++++++++ .../test/script/nosecurity/treeapi/empty.js | 48 +++ .../nosecurity/treeapi/empty.js.EXPECTED | 12 + .../script/nosecurity/treeapi/erroneous.js | 52 +++ .../nosecurity/treeapi/erroneous.js.EXPECTED | 27 ++ nashorn/test/script/nosecurity/treeapi/for.js | 50 +++ .../script/nosecurity/treeapi/for.js.EXPECTED | 281 ++++++++++++++ .../test/script/nosecurity/treeapi/forin.js | 48 +++ .../nosecurity/treeapi/forin.js.EXPECTED | 50 +++ .../script/nosecurity/treeapi/functionCall.js | 54 +++ .../treeapi/functionCall.js.EXPECTED | 255 +++++++++++++ .../nosecurity/treeapi/functionDeclaration.js | 52 +++ .../treeapi/functionDeclaration.js.EXPECTED | 161 ++++++++ .../script/nosecurity/treeapi/functionExpr.js | 51 +++ .../treeapi/functionExpr.js.EXPECTED | 128 +++++++ .../script/nosecurity/treeapi/identifier.js | 53 +++ .../nosecurity/treeapi/identifier.js.EXPECTED | 44 +++ nashorn/test/script/nosecurity/treeapi/if.js | 52 +++ .../script/nosecurity/treeapi/if.js.EXPECTED | 166 ++++++++ .../script/nosecurity/treeapi/instanceof.js | 54 +++ .../nosecurity/treeapi/instanceof.js.EXPECTED | 224 +++++++++++ .../script/nosecurity/treeapi/labelledStat.js | 52 +++ .../treeapi/labelledStat.js.EXPECTED | 176 +++++++++ .../test/script/nosecurity/treeapi/literal.js | 51 +++ .../nosecurity/treeapi/literal.js.EXPECTED | 26 ++ .../script/nosecurity/treeapi/memberSelect.js | 50 +++ .../treeapi/memberSelect.js.EXPECTED | 50 +++ nashorn/test/script/nosecurity/treeapi/new.js | 50 +++ .../script/nosecurity/treeapi/new.js.EXPECTED | 120 ++++++ .../nosecurity/treeapi/objectLiteral.js | 52 +++ .../treeapi/objectLiteral.js.EXPECTED | 310 +++++++++++++++ .../script/nosecurity/treeapi/property.js | 51 +++ .../nosecurity/treeapi/property.js.EXPECTED | 92 +++++ .../test/script/nosecurity/treeapi/regexp.js | 48 +++ .../nosecurity/treeapi/regexp.js.EXPECTED | 23 ++ .../test/script/nosecurity/treeapi/return.js | 65 ++++ .../nosecurity/treeapi/return.js.EXPECTED | 62 +++ .../test/script/nosecurity/treeapi/switch.js | 55 +++ .../nosecurity/treeapi/switch.js.EXPECTED | 162 ++++++++ .../test/script/nosecurity/treeapi/throw.js | 50 +++ .../nosecurity/treeapi/throw.js.EXPECTED | 106 ++++++ nashorn/test/script/nosecurity/treeapi/try.js | 50 +++ .../script/nosecurity/treeapi/try.js.EXPECTED | 230 +++++++++++ .../test/script/nosecurity/treeapi/unary.js | 56 +++ .../nosecurity/treeapi/unary.js.EXPECTED | 123 ++++++ .../test/script/nosecurity/treeapi/utils.js | 82 ++++ .../script/nosecurity/treeapi/variable.js | 48 +++ .../nosecurity/treeapi/variable.js.EXPECTED | 47 +++ .../test/script/nosecurity/treeapi/while.js | 51 +++ .../nosecurity/treeapi/while.js.EXPECTED | 138 +++++++ .../test/script/nosecurity/treeapi/with.js | 50 +++ .../nosecurity/treeapi/with.js.EXPECTED | 143 +++++++ 80 files changed, 6896 insertions(+) create mode 100644 nashorn/test/script/nosecurity/parser-args.js create mode 100644 nashorn/test/script/nosecurity/parser.js create mode 100644 nashorn/test/script/nosecurity/treeapi/array_access.js create mode 100644 nashorn/test/script/nosecurity/treeapi/array_access.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/array_literal.js create mode 100644 nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/assignment.js create mode 100644 nashorn/test/script/nosecurity/treeapi/assignment.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/assignmentExpr.js create mode 100644 nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/binaryExpr.js create mode 100644 nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/block.js create mode 100644 nashorn/test/script/nosecurity/treeapi/block.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/breakStat.js create mode 100644 nashorn/test/script/nosecurity/treeapi/breakStat.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/case.js create mode 100644 nashorn/test/script/nosecurity/treeapi/case.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/compilationUnitTree.js create mode 100644 nashorn/test/script/nosecurity/treeapi/condExpr.js create mode 100644 nashorn/test/script/nosecurity/treeapi/condExpr.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/continueStat.js create mode 100644 nashorn/test/script/nosecurity/treeapi/continueStat.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/debuggerStat.js create mode 100644 nashorn/test/script/nosecurity/treeapi/debuggerStat.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/diagnostic.js create mode 100644 nashorn/test/script/nosecurity/treeapi/diagnostic.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/dowhile.js create mode 100644 nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/empty.js create mode 100644 nashorn/test/script/nosecurity/treeapi/empty.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/erroneous.js create mode 100644 nashorn/test/script/nosecurity/treeapi/erroneous.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/for.js create mode 100644 nashorn/test/script/nosecurity/treeapi/for.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/forin.js create mode 100644 nashorn/test/script/nosecurity/treeapi/forin.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/functionCall.js create mode 100644 nashorn/test/script/nosecurity/treeapi/functionCall.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/functionDeclaration.js create mode 100644 nashorn/test/script/nosecurity/treeapi/functionDeclaration.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/functionExpr.js create mode 100644 nashorn/test/script/nosecurity/treeapi/functionExpr.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/identifier.js create mode 100644 nashorn/test/script/nosecurity/treeapi/identifier.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/if.js create mode 100644 nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/instanceof.js create mode 100644 nashorn/test/script/nosecurity/treeapi/instanceof.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/labelledStat.js create mode 100644 nashorn/test/script/nosecurity/treeapi/labelledStat.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/literal.js create mode 100644 nashorn/test/script/nosecurity/treeapi/literal.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/memberSelect.js create mode 100644 nashorn/test/script/nosecurity/treeapi/memberSelect.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/new.js create mode 100644 nashorn/test/script/nosecurity/treeapi/new.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/objectLiteral.js create mode 100644 nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/property.js create mode 100644 nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/regexp.js create mode 100644 nashorn/test/script/nosecurity/treeapi/regexp.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/return.js create mode 100644 nashorn/test/script/nosecurity/treeapi/return.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/switch.js create mode 100644 nashorn/test/script/nosecurity/treeapi/switch.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/throw.js create mode 100644 nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/try.js create mode 100644 nashorn/test/script/nosecurity/treeapi/try.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/unary.js create mode 100644 nashorn/test/script/nosecurity/treeapi/unary.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/utils.js create mode 100644 nashorn/test/script/nosecurity/treeapi/variable.js create mode 100644 nashorn/test/script/nosecurity/treeapi/variable.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/while.js create mode 100644 nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED create mode 100644 nashorn/test/script/nosecurity/treeapi/with.js create mode 100644 nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED diff --git a/nashorn/test/script/nosecurity/parser-args.js b/nashorn/test/script/nosecurity/parser-args.js new file mode 100644 index 00000000000..b88f0de2a8a --- /dev/null +++ b/nashorn/test/script/nosecurity/parser-args.js @@ -0,0 +1,71 @@ +/* + * Copyright (c) 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 + * 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. + */ + + /** + * @bug 8068303 + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "/../assert.js") + +var Parser = Java.type('jdk.nashorn.api.tree.Parser') + + +var code = <>= 314; +xyz >>>= 314; +xyz &= 314; +xyz ^= 314; +xyz |= 314; + +EOF + + +parse("assignmentExpr.js", code, "-nse", new (Java.extend(visitor, { + visitCompoundAssignment : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff --git a/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED new file mode 100644 index 00000000000..660cb536b34 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED @@ -0,0 +1,189 @@ +[ + { + "expression": { + "endPosition": "10", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "7" + }, + "endPosition": "10", + "kind": "PLUS_ASSIGNMENT", + "variable": { + "endPosition": "3", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "0" + }, + "startPosition": "0" + }, + { + "expression": { + "endPosition": "22", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "19" + }, + "endPosition": "22", + "kind": "MINUS_ASSIGNMENT", + "variable": { + "endPosition": "15", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "12" + }, + "startPosition": "12" + }, + { + "expression": { + "endPosition": "34", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "31" + }, + "endPosition": "34", + "kind": "MULTIPLY_ASSIGNMENT", + "variable": { + "endPosition": "27", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "24" + }, + "startPosition": "24" + }, + { + "expression": { + "endPosition": "46", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "43" + }, + "endPosition": "46", + "kind": "DIVIDE_ASSIGNMENT", + "variable": { + "endPosition": "39", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "36" + }, + "startPosition": "36" + }, + { + "expression": { + "endPosition": "58", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "55" + }, + "endPosition": "58", + "kind": "REMAINDER_ASSIGNMENT", + "variable": { + "endPosition": "51", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "48" + }, + "startPosition": "48" + }, + { + "expression": { + "endPosition": "71", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "68" + }, + "endPosition": "71", + "kind": "LEFT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "63", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "60" + }, + "startPosition": "60" + }, + { + "expression": { + "endPosition": "84", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "81" + }, + "endPosition": "84", + "kind": "RIGHT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "76", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "73" + }, + "startPosition": "73" + }, + { + "expression": { + "endPosition": "98", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "95" + }, + "endPosition": "98", + "kind": "UNSIGNED_RIGHT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "89", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "86" + }, + "startPosition": "86" + }, + { + "expression": { + "endPosition": "110", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "107" + }, + "endPosition": "110", + "kind": "AND_ASSIGNMENT", + "variable": { + "endPosition": "103", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "100" + }, + "startPosition": "100" + }, + { + "expression": { + "endPosition": "122", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "119" + }, + "endPosition": "122", + "kind": "XOR_ASSIGNMENT", + "variable": { + "endPosition": "115", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "112" + }, + "startPosition": "112" + }, + { + "expression": { + "endPosition": "134", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "131" + }, + "endPosition": "134", + "kind": "OR_ASSIGNMENT", + "variable": { + "endPosition": "127", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "124" + }, + "startPosition": "124" + } +] diff --git a/nashorn/test/script/nosecurity/treeapi/binaryExpr.js b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js new file mode 100644 index 00000000000..b1542f96001 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * Tests to check representation binary expression tree. + * + * @bug 8068306 + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = <> b; +a >>> b; +a < b; +a > b; +a <= b; +a >= b; +a instanceof b; +a == b; +a != b; +a === b; +a !== b; +a & b; +a ^ b; +a | b; +a && b; +a || b; + +EOF + + +parse("binaryExpr.js", code, "-nse", new (Java.extend(visitor, { + visitBinary : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff --git a/nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED new file mode 100644 index 00000000000..bd43c6cf76d --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED @@ -0,0 +1,359 @@ +[ + { + "leftOperand": { + "endPosition": "1", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "0" + }, + "endPosition": "5", + "kind": "MULTIPLY", + "rightOperand": { + "endPosition": "5", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "4" + }, + "startPosition": "0" + }, + { + "leftOperand": { + "endPosition": "7", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "6" + }, + "endPosition": "11", + "kind": "DIVIDE", + "rightOperand": { + "endPosition": "11", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "10" + }, + "startPosition": "6" + }, + { + "leftOperand": { + "endPosition": "14", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "13" + }, + "endPosition": "18", + "kind": "REMAINDER", + "rightOperand": { + "endPosition": "18", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "17" + }, + "startPosition": "13" + }, + { + "leftOperand": { + "endPosition": "21", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "20" + }, + "endPosition": "25", + "kind": "PLUS", + "rightOperand": { + "endPosition": "25", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "24" + }, + "startPosition": "20" + }, + { + "leftOperand": { + "endPosition": "28", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "27" + }, + "endPosition": "32", + "kind": "MINUS", + "rightOperand": { + "endPosition": "32", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "31" + }, + "startPosition": "27" + }, + { + "leftOperand": { + "endPosition": "35", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "34" + }, + "endPosition": "40", + "kind": "LEFT_SHIFT", + "rightOperand": { + "endPosition": "40", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "39" + }, + "startPosition": "34" + }, + { + "leftOperand": { + "endPosition": "43", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "42" + }, + "endPosition": "48", + "kind": "RIGHT_SHIFT", + "rightOperand": { + "endPosition": "48", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "47" + }, + "startPosition": "42" + }, + { + "leftOperand": { + "endPosition": "51", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "50" + }, + "endPosition": "57", + "kind": "UNSIGNED_RIGHT_SHIFT", + "rightOperand": { + "endPosition": "57", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "56" + }, + "startPosition": "50" + }, + { + "leftOperand": { + "endPosition": "60", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "59" + }, + "endPosition": "64", + "kind": "LESS_THAN", + "rightOperand": { + "endPosition": "64", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "63" + }, + "startPosition": "59" + }, + { + "leftOperand": { + "endPosition": "67", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "66" + }, + "endPosition": "71", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "71", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "70" + }, + "startPosition": "66" + }, + { + "leftOperand": { + "endPosition": "74", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "73" + }, + "endPosition": "79", + "kind": "LESS_THAN_EQUAL", + "rightOperand": { + "endPosition": "79", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "78" + }, + "startPosition": "73" + }, + { + "leftOperand": { + "endPosition": "82", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "81" + }, + "endPosition": "87", + "kind": "GREATER_THAN_EQUAL", + "rightOperand": { + "endPosition": "87", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "86" + }, + "startPosition": "81" + }, + { + "leftOperand": { + "endPosition": "106", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "105" + }, + "endPosition": "111", + "kind": "EQUAL_TO", + "rightOperand": { + "endPosition": "111", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "110" + }, + "startPosition": "105" + }, + { + "leftOperand": { + "endPosition": "114", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "113" + }, + "endPosition": "119", + "kind": "NOT_EQUAL_TO", + "rightOperand": { + "endPosition": "119", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "118" + }, + "startPosition": "113" + }, + { + "leftOperand": { + "endPosition": "122", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "121" + }, + "endPosition": "128", + "kind": "STRICT_EQUAL_TO", + "rightOperand": { + "endPosition": "128", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "127" + }, + "startPosition": "121" + }, + { + "leftOperand": { + "endPosition": "131", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "130" + }, + "endPosition": "137", + "kind": "STRICT_NOT_EQUAL_TO", + "rightOperand": { + "endPosition": "137", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "136" + }, + "startPosition": "130" + }, + { + "leftOperand": { + "endPosition": "140", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "139" + }, + "endPosition": "144", + "kind": "AND", + "rightOperand": { + "endPosition": "144", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "143" + }, + "startPosition": "139" + }, + { + "leftOperand": { + "endPosition": "147", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "146" + }, + "endPosition": "151", + "kind": "XOR", + "rightOperand": { + "endPosition": "151", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "150" + }, + "startPosition": "146" + }, + { + "leftOperand": { + "endPosition": "154", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "153" + }, + "endPosition": "158", + "kind": "OR", + "rightOperand": { + "endPosition": "158", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "157" + }, + "startPosition": "153" + }, + { + "leftOperand": { + "endPosition": "161", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "160" + }, + "endPosition": "166", + "kind": "CONDITIONAL_AND", + "rightOperand": { + "endPosition": "166", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "165" + }, + "startPosition": "160" + }, + { + "leftOperand": { + "endPosition": "169", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "168" + }, + "endPosition": "174", + "kind": "CONDITIONAL_OR", + "rightOperand": { + "endPosition": "174", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "173" + }, + "startPosition": "168" + } +] diff --git a/nashorn/test/script/nosecurity/treeapi/block.js b/nashorn/test/script/nosecurity/treeapi/block.js new file mode 100644 index 00000000000..1ffab5361f8 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/block.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * Tests to check representation block tree. + * + * @bug 8068306 + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = < 20) + +do call();while(NaN) + +EOF + +parse("dowhile.js", code, "-nse", new (Java.extend(visitor, { + visitDoWhileLoop : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff --git a/nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED new file mode 100644 index 00000000000..64165c31c63 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED @@ -0,0 +1,169 @@ +[ + { + "condition": { + "endPosition": "18", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "13" + }, + "endPosition": "19", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "6", + "kind": "BLOCK", + "statements": [], + "startPosition": "4" + }, + "startPosition": "1" + }, + { + "condition": { + "endPosition": "42", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "38" + }, + "endPosition": "43", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "31", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "30", + "kind": "BREAK", + "label": "null", + "startPosition": "24" + } + ], + "startPosition": "23" + }, + "startPosition": "20" + }, + { + "condition": { + "leftOperand": { + "endPosition": "76", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "75" + }, + "endPosition": "81", + "kind": "EQUAL_TO", + "rightOperand": { + "endPosition": "81", + "kind": "NUMBER_LITERAL", + "value": "2", + "startPosition": "80" + }, + "startPosition": "75" + }, + "endPosition": "82", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "68", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "67", + "kind": "BREAK", + "label": "label", + "startPosition": "55" + } + ], + "startPosition": "54" + }, + "startPosition": "51" + }, + { + "condition": { + "leftOperand": { + "leftOperand": { + "endPosition": "112", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "111" + }, + "endPosition": "116", + "kind": "PLUS", + "rightOperand": { + "endPosition": "116", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "115" + }, + "startPosition": "111" + }, + "endPosition": "121", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "121", + "kind": "NUMBER_LITERAL", + "value": "20", + "startPosition": "119" + }, + "startPosition": "111" + }, + "endPosition": "122", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "105", + "kind": "BLOCK", + "statements": [ + { + "condition": { + "endPosition": "103", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "101", + "kind": "IDENTIFIER", + "name": "func1", + "startPosition": "96" + }, + "arguments": [], + "startPosition": "96" + }, + "endPosition": "104", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "90", + "kind": "BLOCK", + "statements": [], + "startPosition": "88" + }, + "startPosition": "86" + } + ], + "startPosition": "85" + }, + "startPosition": "83" + }, + { + "condition": { + "endPosition": "143", + "kind": "IDENTIFIER", + "name": "NaN", + "startPosition": "140" + }, + "endPosition": "144", + "kind": "DO_WHILE_LOOP", + "statement": { + "expression": { + "endPosition": "133", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "131", + "kind": "IDENTIFIER", + "name": "call", + "startPosition": "127" + }, + "arguments": [], + "startPosition": "127" + }, + "endPosition": "133", + "kind": "EXPRESSION_STATEMENT", + "startPosition": "127" + }, + "startPosition": "124" + } +] diff --git a/nashorn/test/script/nosecurity/treeapi/empty.js b/nashorn/test/script/nosecurity/treeapi/empty.js new file mode 100644 index 00000000000..fe1ca4a7b1b --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/empty.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * Tests to check representation empty tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = < 10) {} else {} +if (a) {} else if (b) {} else {} + +EOF + +parse("if.js", code, "-nse", new (Java.extend(visitor, { + visitIf : function (node, obj) { + obj.push(convert(node)) + } +}))) + diff --git a/nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED new file mode 100644 index 00000000000..f9e6dcaa351 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED @@ -0,0 +1,166 @@ +[ + { + "condition": { + "endPosition": "9", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "5" + }, + "elseStatement": "null", + "endPosition": "13", + "kind": "IF", + "startPosition": "1", + "thenStatement": { + "endPosition": "13", + "kind": "BLOCK", + "statements": [], + "startPosition": "11" + } + }, + { + "condition": { + "endPosition": "23", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "18" + }, + "elseStatement": "null", + "endPosition": "27", + "kind": "IF", + "startPosition": "14", + "thenStatement": { + "endPosition": "27", + "kind": "BLOCK", + "statements": [], + "startPosition": "25" + } + }, + { + "condition": { + "endPosition": "33", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "32" + }, + "elseStatement": "null", + "endPosition": "43", + "kind": "IF", + "startPosition": "28", + "thenStatement": { + "expression": { + "endPosition": "43", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "40", + "kind": "IDENTIFIER", + "name": "print", + "startPosition": "35" + }, + "arguments": [ + { + "endPosition": "42", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "41" + } + ], + "startPosition": "35" + }, + "endPosition": "43", + "kind": "EXPRESSION_STATEMENT", + "startPosition": "35" + } + }, + { + "condition": { + "endPosition": "52", + "kind": "STRING_LITERAL", + "value": "STR", + "startPosition": "49" + }, + "elseStatement": "null", + "endPosition": "57", + "kind": "IF", + "startPosition": "44", + "thenStatement": { + "endPosition": "57", + "kind": "BLOCK", + "statements": [], + "startPosition": "55" + } + }, + { + "condition": { + "leftOperand": { + "endPosition": "64", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "63" + }, + "endPosition": "69", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "69", + "kind": "NUMBER_LITERAL", + "value": "10", + "startPosition": "67" + }, + "startPosition": "63" + }, + "elseStatement": { + "endPosition": "81", + "kind": "BLOCK", + "statements": [], + "startPosition": "79" + }, + "endPosition": "81", + "kind": "IF", + "startPosition": "58", + "thenStatement": { + "endPosition": "73", + "kind": "BLOCK", + "statements": [], + "startPosition": "71" + } + }, + { + "condition": { + "endPosition": "87", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "86" + }, + "elseStatement": { + "condition": { + "endPosition": "102", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "101" + }, + "elseStatement": { + "endPosition": "114", + "kind": "BLOCK", + "statements": [], + "startPosition": "112" + }, + "endPosition": "114", + "kind": "IF", + "startPosition": "97", + "thenStatement": { + "endPosition": "106", + "kind": "BLOCK", + "statements": [], + "startPosition": "104" + } + }, + "endPosition": "114", + "kind": "IF", + "startPosition": "82", + "thenStatement": { + "endPosition": "91", + "kind": "BLOCK", + "statements": [], + "startPosition": "89" + } + } +] diff --git a/nashorn/test/script/nosecurity/treeapi/instanceof.js b/nashorn/test/script/nosecurity/treeapi/instanceof.js new file mode 100644 index 00000000000..ccf4a377f10 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/instanceof.js @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. + * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * + * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it + * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s + * pu2lished 2y the Free Softw1re Found1tion. + * + * This code is distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT + * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or + * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License + * version 2 for more det1ils (1 copy is included in the LICENSE file th1t + * 1ccomp1nied this code). + * + * You should h1ve received 1 copy of the GNU Gener1l Pu2lic License version + * 2 1long with this work; if not, write to the Free Softw1re Found1tion, + * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * + * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 + * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * questions. + */ + +/** + * Tests to check representation instanceof statement tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = < 1) {} +label:while(fun()) { break label} +label:while(!fun()) continue label; +while(true) continue + +EOF + +parse("while.js", code, "-nse", new (Java.extend(visitor, { + visitWhileLoop: function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff --git a/nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED new file mode 100644 index 00000000000..8a721c74529 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED @@ -0,0 +1,138 @@ +[ + { + "condition": { + "endPosition": "11", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "7" + }, + "endPosition": "13", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "13", + "kind": "EMPTY_STATEMENT", + "startPosition": "12" + }, + "startPosition": "1" + }, + { + "condition": { + "endPosition": "25", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "20" + }, + "endPosition": "29", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "29", + "kind": "BLOCK", + "statements": [], + "startPosition": "27" + }, + "startPosition": "14" + }, + { + "condition": { + "leftOperand": { + "endPosition": "37", + "kind": "NUMBER_LITERAL", + "value": "2", + "startPosition": "36" + }, + "endPosition": "41", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "41", + "kind": "NUMBER_LITERAL", + "value": "1", + "startPosition": "40" + }, + "startPosition": "36" + }, + "endPosition": "45", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "45", + "kind": "BLOCK", + "statements": [], + "startPosition": "43" + }, + "startPosition": "30" + }, + { + "condition": { + "endPosition": "63", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "61", + "kind": "IDENTIFIER", + "name": "fun", + "startPosition": "58" + }, + "arguments": [], + "startPosition": "58" + }, + "endPosition": "79", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "79", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "78", + "kind": "BREAK", + "label": "label", + "startPosition": "67" + } + ], + "startPosition": "65" + }, + "startPosition": "52" + }, + { + "condition": { + "expression": { + "endPosition": "98", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "96", + "kind": "IDENTIFIER", + "name": "fun", + "startPosition": "93" + }, + "arguments": [], + "startPosition": "93" + }, + "endPosition": "98", + "kind": "LOGICAL_COMPLEMENT", + "startPosition": "92" + }, + "endPosition": "115", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "115", + "kind": "CONTINUE", + "label": "label", + "startPosition": "100" + }, + "startPosition": "86" + }, + { + "condition": { + "endPosition": "126", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "122" + }, + "endPosition": "136", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "136", + "kind": "CONTINUE", + "label": "null", + "startPosition": "128" + }, + "startPosition": "116" + } +] diff --git a/nashorn/test/script/nosecurity/treeapi/with.js b/nashorn/test/script/nosecurity/treeapi/with.js new file mode 100644 index 00000000000..63c53ef11fb --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/with.js @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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 + * 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. + */ + +/** + * Tests to check representation with statement tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = < Date: Fri, 20 Mar 2015 20:04:18 +0530 Subject: [PATCH 54/79] 8075604: jjs exits even when non-daemon threads are still active Reviewed-by: attila, jlaskey --- .../share/classes/jdk/nashorn/tools/Shell.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java index 58ab97c1896..ac630ccaa79 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java @@ -109,7 +109,10 @@ public class Shell { */ public static void main(final String[] args) { try { - System.exit(main(System.in, System.out, System.err, args)); + final int exitCode = main(System.in, System.out, System.err, args); + if (exitCode != SUCCESS) { + System.exit(exitCode); + } } catch (final IOException e) { System.err.println(e); //bootstrapping, Context.err may not exist System.exit(IO_ERROR); From 0198eb6feba5f8168be7f7baeb373d132ada3d39 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 20:24:26 +0200 Subject: [PATCH 55/79] Added tag jdk9-b55 for changeset c97e2d1bad97 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 02c963d4e45..ef7ee162e19 100644 --- a/.hgtags +++ b/.hgtags @@ -297,3 +297,4 @@ b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48 d6224d6021459ac8b3832e822f5acc849fa944af jdk9-b52 874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53 82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54 +c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55 From 28114420db9c0ab453a37360d78b63db6a1a988b Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 20 Mar 2015 10:00:30 -0700 Subject: [PATCH 56/79] 8075573: Add jdk_other and jdk_svc to jdk tier 2 test definition Reviewed-by: mchung --- jdk/test/TEST.groups | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 2ee1007a5e7..aa80127fbe8 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -38,7 +38,9 @@ tier2 = \ :jdk_time \ :jdk_security \ :jdk_text \ - :core_tools + :core_tools \ + :jdk_other \ + :jdk_svc ############################################################################### # From 49dec121161c162f4aa94caf8c09413253d89377 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 20 Mar 2015 10:02:44 -0700 Subject: [PATCH 57/79] 8074839: Resolve disabled warnings for libunpack and the unpack200 binary Reviewed-by: dholmes, ksrini --- jdk/make/launcher/Launcher-jdk.pack200.gmk | 3 -- jdk/make/lib/Lib-jdk.pack200.gmk | 5 -- .../share/native/common-unpack/bytes.h | 2 +- .../share/native/common-unpack/unpack.cpp | 50 ++++++++++--------- .../share/native/common-unpack/unpack.h | 2 +- .../share/native/common-unpack/utils.cpp | 2 +- .../share/native/common-unpack/zip.cpp | 8 +-- .../share/native/common-unpack/zip.h | 4 +- .../share/native/libunpack/jni.cpp | 5 +- .../share/native/unpack200/main.cpp | 39 +++++++-------- 10 files changed, 57 insertions(+), 63 deletions(-) diff --git a/jdk/make/launcher/Launcher-jdk.pack200.gmk b/jdk/make/launcher/Launcher-jdk.pack200.gmk index 6ee00f7ccd0..affdbdb26eb 100644 --- a/jdk/make/launcher/Launcher-jdk.pack200.gmk +++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk @@ -79,9 +79,6 @@ $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \ CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ - DISABLED_WARNINGS_gcc := sign-compare unused-result format-nonliteral \ - format-security parentheses, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(UNPACK_MAPFILE),\ LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ diff --git a/jdk/make/lib/Lib-jdk.pack200.gmk b/jdk/make/lib/Lib-jdk.pack200.gmk index 37e32d0a725..105f1f8b713 100644 --- a/jdk/make/lib/Lib-jdk.pack200.gmk +++ b/jdk/make/lib/Lib-jdk.pack200.gmk @@ -40,11 +40,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBUNPACK, \ -I$(JDK_TOPDIR)/src/jdk.pack200/share/native/common-unpack \ $(LIBJAVA_HEADER_FLAGS), \ CFLAGS_release := -DPRODUCT, \ - DISABLED_WARNINGS_gcc := conversion-null sign-compare format-security \ - format-nonliteral parentheses, \ - DISABLED_WARNINGS_clang := bool-conversion format-security, \ - DISABLED_WARNINGS_solstudio := truncwarn, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libunpack/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h b/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h index bdaf95a2f6a..60c5b4f2a69 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h +++ b/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h @@ -63,7 +63,7 @@ struct bytes { bytes res; res.ptr = ptr + beg; res.len = end - beg; - assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit()-1)); + assert(res.len == 0 || (inBounds(res.ptr) && inBounds(res.limit()-1))); return res; } // building C strings inside byte buffers: diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp index 5af0422661d..60aa3bfdf0c 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp @@ -225,9 +225,9 @@ struct entry { } #ifdef PRODUCT - char* string() { return 0; } + const char* string() { return NULL; } #else - char* string(); // see far below + const char* string(); // see far below #endif }; @@ -718,13 +718,13 @@ void unpacker::read_file_header() { // Now we can size the whole archive. // Read everything else into a mega-buffer. rp = hdr.rp; - int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int) - int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment - int header_size = header_size_0+header_size_1; + size_t header_size_0 = (rp - input.base()); // used-up header (4byte + 3int) + size_t header_size_1 = (rplimit - rp); // buffered unused initial fragment + size_t header_size = header_size_0 + header_size_1; unsized_bytes_read = header_size_0; CHECK; if (foreign_buf) { - if (archive_size > (size_t)header_size_1) { + if (archive_size > header_size_1) { abort("EOF reading fixed input buffer"); return; } @@ -738,7 +738,7 @@ void unpacker::read_file_header() { return; } input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)), - (size_t) header_size_0 + archive_size); + header_size_0 + archive_size); CHECK; assert(input.limit()[0] == 0); // Move all the bytes we read initially into the real buffer. @@ -961,13 +961,13 @@ void cpool::init(unpacker* u_, int counts[CONSTANT_Limit]) { nentries = next_entry; // place a limit on future CP growth: - int generous = 0; + size_t generous = 0; generous = add_size(generous, u->ic_count); // implicit name generous = add_size(generous, u->ic_count); // outer generous = add_size(generous, u->ic_count); // outer.utf8 generous = add_size(generous, 40); // WKUs, misc generous = add_size(generous, u->class_count); // implicit SourceFile strings - maxentries = add_size(nentries, generous); + maxentries = (uint)add_size(nentries, generous); // Note that this CP does not include "empty" entries // for longs and doubles. Those are introduced when @@ -985,8 +985,9 @@ void cpool::init(unpacker* u_, int counts[CONSTANT_Limit]) { } // Initialize *all* our entries once - for (int i = 0 ; i < maxentries ; i++) + for (uint i = 0 ; i < maxentries ; i++) { entries[i].outputIndex = REQUESTED_NONE; + } initGroupIndexes(); // Initialize hashTab to a generous power-of-two size. @@ -3680,21 +3681,22 @@ void cpool::computeOutputIndexes() { unpacker* debug_u; -static bytes& getbuf(int len) { // for debugging only! +static bytes& getbuf(size_t len) { // for debugging only! static int bn = 0; static bytes bufs[8]; bytes& buf = bufs[bn++ & 7]; - while ((int)buf.len < len+10) + while (buf.len < len + 10) { buf.realloc(buf.len ? buf.len * 2 : 1000); + } buf.ptr[0] = 0; // for the sake of strcat return buf; } -char* entry::string() { +const char* entry::string() { bytes buf; switch (tag) { case CONSTANT_None: - return (char*)""; + return ""; case CONSTANT_Signature: if (value.b.ptr == null) return ref(0)->string(); @@ -3714,26 +3716,28 @@ char* entry::string() { break; default: if (nrefs == 0) { - buf = getbuf(20); - sprintf((char*)buf.ptr, TAG_NAME[tag]); + return TAG_NAME[tag]; } else if (nrefs == 1) { return refs[0]->string(); } else { - char* s1 = refs[0]->string(); - char* s2 = refs[1]->string(); - buf = getbuf((int)strlen(s1) + 1 + (int)strlen(s2) + 4 + 1); + const char* s1 = refs[0]->string(); + const char* s2 = refs[1]->string(); + buf = getbuf(strlen(s1) + 1 + strlen(s2) + 4 + 1); buf.strcat(s1).strcat(" ").strcat(s2); if (nrefs > 2) buf.strcat(" ..."); } } - return (char*)buf.ptr; + return (const char*)buf.ptr; } void print_cp_entry(int i) { entry& e = debug_u->cp.entries[i]; - char buf[30]; - sprintf(buf, ((uint)e.tag < CONSTANT_Limit)? TAG_NAME[e.tag]: "%d", e.tag); - printf(" %d\t%s %s\n", i, buf, e.string()); + + if ((uint)e.tag < CONSTANT_Limit) { + printf(" %d\t%s %s\n", i, TAG_NAME[e.tag], e.string()); + } else { + printf(" %d\t%d %s\n", i, e.tag, e.string()); + } } void print_cp_entries(int beg, int end) { diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h index 621b1c1db01..ba3b7d5ad69 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h @@ -210,7 +210,7 @@ struct unpacker { byte* rp; // read pointer (< rplimit <= input.limit()) byte* rplimit; // how much of the input block has been read? julong bytes_read; - int unsized_bytes_read; + size_t unsized_bytes_read; // callback to read at least one byte, up to available input typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen); diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp index e5197e1a3f1..40a10055ea5 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp +++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp @@ -81,7 +81,7 @@ void breakpoint() { } // hook for debugger int assert_failed(const char* p) { char message[1<<12]; sprintf(message, "@assert failed: %s\n", p); - fprintf(stdout, 1+message); + fprintf(stdout, "%s", 1+message); breakpoint(); unpack_abort(message); return 0; diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp b/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp index 8dc2634987f..a540ab42d3d 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp @@ -84,7 +84,7 @@ void jar::init(unpacker* u_) { } // Write data to the ZIP output stream. -void jar::write_data(void* buff, int len) { +void jar::write_data(void* buff, size_t len) { while (len > 0) { int rc = (int)fwrite(buff, 1, len, jarfp); if (rc <= 0) { @@ -323,12 +323,12 @@ void jar::write_central_directory() { // Total number of disks (int) header64[36] = (ushort)SWAP_BYTES(1); header64[37] = 0; - write_data(header64, (int)sizeof(header64)); + write_data(header64, sizeof(header64)); } // Write the End of Central Directory structure. PRINTCR((2, "end-of-directory at %d\n", output_file_offset)); - write_data(header, (int)sizeof(header)); + write_data(header, sizeof(header)); PRINTCR((2, "writing zip comment\n")); // Write the comment. @@ -590,7 +590,7 @@ void gunzip::init(unpacker* u_) { zstream = NEW(z_stream, 1); u->gzin = this; u->read_input_fn = read_input_via_gzip; - u->gzcrc = crc32(0L, Z_NULL, 0); + u->gzcrc = crc32(0, Z_NULL, 0); } void gunzip::start(int magic) { diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/zip.h b/jdk/src/jdk.pack200/share/native/common-unpack/zip.h index 14ffc9d65bd..9877f6f68ca 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.h +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.h @@ -68,8 +68,8 @@ struct jar { } // Private Methods - void write_data(void* ptr, int len); - void write_data(bytes& b) { write_data(b.ptr, (int)b.len); } + void write_data(void* ptr, size_t len); + void write_data(bytes& b) { write_data(b.ptr, b.len); } void add_to_jar_directory(const char* fname, bool store, int modtime, int len, int clen, uLong crc); void write_jar_header(const char* fname, bool store, int modtime, diff --git a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp index e9109cbec96..4915590aeaa 100644 --- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp +++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp @@ -292,7 +292,7 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); - return false; + return null; } // We have fetched all the files. @@ -310,7 +310,7 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { unpacker* uPtr = get_unpacker(env, pObj, false); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, 0); size_t consumed = uPtr->input_consumed(); free_unpacker(env, pObj, uPtr); return consumed; @@ -320,6 +320,7 @@ JNIEXPORT jboolean JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, jstring pProp, jstring pValue) { unpacker* uPtr = get_unpacker(env, pObj); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); CHECK_EXCEPTION_RETURN_VALUE(prop, false); const char* value = env->GetStringUTFChars(pValue, JNI_FALSE); diff --git a/jdk/src/jdk.pack200/share/native/unpack200/main.cpp b/jdk/src/jdk.pack200/share/native/unpack200/main.cpp index fdce8857c2c..d03db583c38 100644 --- a/jdk/src/jdk.pack200/share/native/unpack200/main.cpp +++ b/jdk/src/jdk.pack200/share/native/unpack200/main.cpp @@ -149,31 +149,28 @@ static const char* nbasename(const char* progname) { return progname; } -static const char* usage_lines[] = { - "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "\n", - "Unpacking Options\n", - " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n", - " -r, --remove-pack-file remove input file after unpacking\n", - " -v, --verbose increase program verbosity\n", - " -q, --quiet set verbosity to lowest level\n", - " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n", - " -?, -h, --help print this message\n", - " -V, --version print program version\n", - " -J{X} Java VM argument (ignored)\n", - null -}; +#define USAGE_HEADER "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n" +#define USAGE_OPTIONS \ + "\n" \ + "Unpacking Options\n" \ + " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n" \ + " -r, --remove-pack-file remove input file after unpacking\n" \ + " -v, --verbose increase program verbosity\n" \ + " -q, --quiet set verbosity to lowest level\n" \ + " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n" \ + " -?, -h, --help print this message\n" \ + " -V, --version print program version\n" \ + " -J{X} Java VM argument (ignored)\n" static void usage(unpacker* u, const char* progname, bool full = false) { // WinMain does not set argv[0] to the progrname progname = (progname != null) ? nbasename(progname) : "unpack200"; - for (int i = 0; usage_lines[i] != null; i++) { - fprintf(u->errstrm, usage_lines[i], progname); - if (!full) { - fprintf(u->errstrm, - "(For more information, run %s --help .)\n", progname); - break; - } + + fprintf(u->errstrm, USAGE_HEADER, progname); + if (full) { + fprintf(u->errstrm, USAGE_OPTIONS); + } else { + fprintf(u->errstrm, "(For more information, run %s --help .)\n", progname); } } From 89c87896e2b9c089efbe9219af1f3e2e96a9b798 Mon Sep 17 00:00:00 2001 From: Rob McKenna Date: Fri, 20 Mar 2015 17:07:15 +0000 Subject: [PATCH 58/79] 8075039: (sctp) com/sun/nio/sctp/SctpMultiChannel/SendFailed.java fails on Solaris only Reviewed-by: chegar --- jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java b/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java index 18f7a4c7815..be50b4efb2f 100644 --- a/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java +++ b/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java @@ -43,11 +43,16 @@ public class SendFailed { void test(String[] args) throws IOException { SocketAddress address = null; + String os = System.getProperty("os.name").toLowerCase(); if (!Util.isSCTPSupported()) { out.println("SCTP protocol is not supported"); out.println("Test cannot be run"); return; + } else if (os.startsWith("sunos")) { + out.println("Test not supported on Solaris"); + out.println("Test cannot be run"); + return; } System.out.println("remote address: " + remoteAddress); From d7419560c26c6d74d59f7c9954b1f6aa5615406e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 20 Mar 2015 10:37:03 -0700 Subject: [PATCH 59/79] 8075362: j.u.Properties.load() methods have misaligned @throws clauses Add spaces to align the @throws clauses, and rename Basic.java test and its @summary clause. Reviewed-by: rriggs --- jdk/src/java.base/share/classes/java/util/Properties.java | 4 ++-- .../util/Properties/{Basic.java => LoadAndStoreNPE.java} | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) rename jdk/test/java/util/Properties/{Basic.java => LoadAndStoreNPE.java} (91%) diff --git a/jdk/src/java.base/share/classes/java/util/Properties.java b/jdk/src/java.base/share/classes/java/util/Properties.java index 04397c3f9f2..a075da67d1c 100644 --- a/jdk/src/java.base/share/classes/java/util/Properties.java +++ b/jdk/src/java.base/share/classes/java/util/Properties.java @@ -309,7 +309,7 @@ class Properties extends Hashtable { * input stream. * @throws IllegalArgumentException if a malformed Unicode escape * appears in the input. - * @throws NullPointerException if {@code reader} is null. + * @throws NullPointerException if {@code reader} is null. * @since 1.6 */ public synchronized void load(Reader reader) throws IOException { @@ -335,7 +335,7 @@ class Properties extends Hashtable { * input stream. * @throws IllegalArgumentException if the input stream contains a * malformed Unicode escape sequence. - * @throws NullPointerException if {@code inStream} is null. + * @throws NullPointerException if {@code inStream} is null. * @since 1.2 */ public synchronized void load(InputStream inStream) throws IOException { diff --git a/jdk/test/java/util/Properties/Basic.java b/jdk/test/java/util/Properties/LoadAndStoreNPE.java similarity index 91% rename from jdk/test/java/util/Properties/Basic.java rename to jdk/test/java/util/Properties/LoadAndStoreNPE.java index 7827ed02957..5050139007a 100644 --- a/jdk/test/java/util/Properties/Basic.java +++ b/jdk/test/java/util/Properties/LoadAndStoreNPE.java @@ -28,10 +28,10 @@ import java.util.Properties; /* * @test - * @bug 8073214 - * @summary Basic tests of Properties methods. + * @bug 8073214 8075362 + * @summary Tests to verify that load() and store() throw NPEs as advertised. */ -public class Basic +public class LoadAndStoreNPE { public static void main(String[] args) throws Exception { @@ -68,7 +68,7 @@ public class Basic } if (failures != 0) { - throw new RuntimeException("Basic failed with " + throw new RuntimeException("LoadAndStoreNPE failed with " + failures + " errors!"); } } From 1eb4f850a6a8195862d24f7e23b5e196e8232de4 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 20 Mar 2015 15:25:07 -0700 Subject: [PATCH 60/79] 8075655: NIO test generation scripts have incorrect path to Spp.java Correct the path to Spp.java Reviewed-by: rriggs --- jdk/test/java/nio/Buffer/genBasic.sh | 4 ++-- jdk/test/java/nio/Buffer/genCopyDirectMemory.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/test/java/nio/Buffer/genBasic.sh b/jdk/test/java/nio/Buffer/genBasic.sh index df271b948cd..1090476807c 100644 --- a/jdk/test/java/nio/Buffer/genBasic.sh +++ b/jdk/test/java/nio/Buffer/genBasic.sh @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 Basic$2.java diff --git a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh index b6c2421b13e..64c51e52904 100644 --- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh +++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2002, 2008, 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 @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java > Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3CopyDirect$2Memory.java From ed05aef3fc58d9d263272e711fc11de494d6138a Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sun, 22 Mar 2015 10:27:22 -0700 Subject: [PATCH 61/79] 8075567: Mark intermittently failuring security-libs tests Reviewed-by: mullan --- jdk/test/sun/security/mscapi/ShortRSAKey1024.sh | 1 + jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh index 8c290ebbdec..f7094f210af 100644 --- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh @@ -30,6 +30,7 @@ # @run shell ShortRSAKey1024.sh 1024 # @run shell ShortRSAKey1024.sh 768 # @run shell ShortRSAKey1024.sh 512 +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory diff --git a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh index 961d1e5e3f1..e8c93a75781 100644 --- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh +++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh @@ -28,6 +28,7 @@ # @bug 6578658 # @run shell SignUsingNONEwithRSA.sh # @summary Sign using the NONEwithRSA signature algorithm from SunMSCAPI +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory From 3fbfa7ee8992b150d8cf27c83c0a549c3ec27dc5 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 23 Mar 2015 08:51:51 +0800 Subject: [PATCH 62/79] 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did Reviewed-by: mullan --- .../classes/sun/security/pkcs10/PKCS10.java | 3 +- .../sun/security/provider/X509Factory.java | 4 +- .../sun/security/tools/keytool/Main.java | 13 ++-- .../share/classes/sun/security/util/Pem.java | 52 +++++++++++++ .../sun/security/x509/X509CertImpl.java | 2 +- .../security/provider/X509Factory/BadPem.java | 76 +++++++++++++++++++ .../security/tools/keytool/KeyToolTest.java | 22 ++++++ 7 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 jdk/src/java.base/share/classes/sun/security/util/Pem.java create mode 100644 jdk/test/sun/security/provider/X509Factory/BadPem.java diff --git a/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java b/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java index af4e8a4a178..02ed730b9af 100644 --- a/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java +++ b/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java @@ -290,8 +290,9 @@ public class PKCS10 { throw new SignatureException("Cert request was not signed"); + byte[] CRLF = new byte[] {'\r', '\n'}; out.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); - out.println(Base64.getMimeEncoder().encodeToString(encoded)); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(encoded)); out.println("-----END NEW CERTIFICATE REQUEST-----"); } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java index 46b1a3c8d7d..5fa9416e60d 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java @@ -28,6 +28,8 @@ package sun.security.provider; import java.io.*; import java.util.*; import java.security.cert.*; + +import sun.security.util.Pem; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.pkcs.PKCS7; @@ -633,7 +635,7 @@ public class X509Factory extends CertificateFactorySpi { checkHeaderFooter(header.toString(), footer.toString()); - return Base64.getMimeDecoder().decode(new String(data, 0, pos)); + return Pem.decode(new String(data, 0, pos)); } } diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index faf8d58dae0..c1e58b5714f 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -80,6 +80,7 @@ import sun.security.pkcs.PKCS9Attribute; import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.util.DerValue; +import sun.security.util.Pem; import sun.security.x509.*; import static java.security.KeyStore.*; @@ -100,6 +101,8 @@ import static sun.security.tools.keytool.Main.Option.*; */ public final class Main { + private static final byte[] CRLF = new byte[] {'\r', '\n'}; + private boolean debug = false; private Command command = null; private String sigAlgName = null; @@ -1266,7 +1269,7 @@ public final class Main { sb.append(s); } } - byte[] rawReq = Base64.getMimeDecoder().decode(new String(sb)); + byte[] rawReq = Pem.decode(new String(sb)); PKCS10 req = new PKCS10(rawReq); info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo())); @@ -1343,7 +1346,7 @@ public final class Main { crl.sign(privateKey, sigAlgName); if (rfc) { out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(crl.getEncodedInternal())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal())); out.println("-----END X509 CRL-----"); } else { out.write(crl.getEncodedInternal()); @@ -2304,7 +2307,7 @@ public final class Main { if (rfc) { X509CRL xcrl = (X509CRL)crl; out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(xcrl.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded())); out.println("-----END X509 CRL-----"); } else { out.println(crl.toString()); @@ -2331,7 +2334,7 @@ public final class Main { sb.append(s); } } - PKCS10 req = new PKCS10(Base64.getMimeDecoder().decode(new String(sb))); + PKCS10 req = new PKCS10(Pem.decode(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."), @@ -3115,7 +3118,7 @@ public final class Main { { if (rfc) { out.println(X509Factory.BEGIN_CERT); - out.println(Base64.getMimeEncoder().encodeToString(cert.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(cert.getEncoded())); out.println(X509Factory.END_CERT); } else { out.write(cert.getEncoded()); // binary diff --git a/jdk/src/java.base/share/classes/sun/security/util/Pem.java b/jdk/src/java.base/share/classes/sun/security/util/Pem.java new file mode 100644 index 00000000000..7e7a0e6d5fb --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/util/Pem.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 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 + * 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. + */ + +package sun.security.util; + +import java.io.IOException; +import java.util.Base64; + +/** + * The Length interface defines the length of an object + */ +public class Pem { + + /** + * Decodes a PEM-encoded block. + * + * @param input the input string, according to RFC 1421, can only contain + * characters in the base-64 alphabet and whitespaces. + * @return the decoded bytes + * @throws java.io.IOException if input is invalid + */ + public static byte[] decode(String input) throws IOException { + byte[] src = input.replaceAll("\\s+", "").getBytes(); + try { + return Base64.getDecoder().decode(src); + } catch (IllegalArgumentException e) { + throw new IOException(e); + } + } +} diff --git a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java index aa24360f46f..201e10a6cfe 100644 --- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java @@ -271,7 +271,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { der = new DerValue(decstream.toByteArray()); break; } else { - decstream.write(Base64.getMimeDecoder().decode(line)); + decstream.write(Pem.decode(line)); } } } catch (IOException ioe2) { diff --git a/jdk/test/sun/security/provider/X509Factory/BadPem.java b/jdk/test/sun/security/provider/X509Factory/BadPem.java new file mode 100644 index 00000000000..9147ab8ce93 --- /dev/null +++ b/jdk/test/sun/security/provider/X509Factory/BadPem.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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 + * 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 8074935 + * @summary jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did + */ + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.Base64; + +import sun.security.provider.X509Factory; +import java.security.cert.CertificateFactory; +import java.io.ByteArrayInputStream; + +public class BadPem { + + public static void main(String[] args) throws Exception { + String ks = System.getProperty("test.src", ".") + + "/../../../../javax/net/ssl/etc/keystore"; + String pass = "passphrase"; + String alias = "dummy"; + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream(ks), pass.toCharArray()); + byte[] cert = keyStore.getCertificate(alias).getEncoded(); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream pout = new PrintStream(bout); + byte[] CRLF = new byte[] {'\r', '\n'}; + pout.println(X509Factory.BEGIN_CERT); + for (int i=0; i i + 48) ? 48 : (cert.length - i); + pout.println("!" + Base64.getEncoder() + .encodeToString(Arrays.copyOfRange(cert, i, i + blockLen))); + } + pout.println(X509Factory.END_CERT); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + try { + cf.generateCertificate(new ByteArrayInputStream(bout.toByteArray())); + throw new Exception("Should fail"); + } catch (CertificateException e) { + // Good + } + } +} + diff --git a/jdk/test/sun/security/tools/keytool/KeyToolTest.java b/jdk/test/sun/security/tools/keytool/KeyToolTest.java index 74290da1c81..a036db96da0 100644 --- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java +++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java @@ -56,6 +56,8 @@ * NSS PKCS11 config file are changed, DSA not supported now. */ +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import sun.security.x509.*; import java.io.*; @@ -1222,6 +1224,24 @@ public class KeyToolTest { remove("mykey.cert"); } + // 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness + static void checkPem(String file) throws Exception { + boolean maybeLast = false; + for (String s: Files.readAllLines(Paths.get(file))) { + if (s.isEmpty()) continue; + if (s.startsWith("---")) continue; + if (maybeLast) { + throw new Exception("Last line already seen"); + } + if (s.length() > 64) { + throw new Exception(s); + } + if (s.length() < 64) { + maybeLast = true; + } + } + } + void v3extTest(String keyAlg) throws Exception { KeyStore ks; remove("x.jks"); @@ -1588,12 +1608,14 @@ public class KeyToolTest { "-rfc -file test.req"); // printcertreq testOK("", "-printcertreq -file test.req"); + checkPem("test.req"); // issue: deny KU, change criticality of 1.2.3 and 1.2.4, // change content of BC, add 2.3.4 testOK("", simple+"-gencert -alias ca -infile test.req -ext " + "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " + "-ext BC=2 -ext 2.3.4=01020304 " + "-debug -rfc -outfile test.cert"); + checkPem("test.cert"); testOK("", simple+"-importcert -file test.cert -alias a"); ks = loadStore("x.jks", "changeit", "JKS"); X509CertImpl a = (X509CertImpl)ks.getCertificate("a"); From 35c411ea7e09c8d3f1a944efc55864cae0763d95 Mon Sep 17 00:00:00 2001 From: Zaiyao Liu Date: Mon, 23 Mar 2015 15:37:03 +0800 Subject: [PATCH 63/79] 8048618: Tests for PKCS12 write operations Reviewed-by: weijun --- .../KeyStore/PKCS12/WriteP12Test.java | 371 ++++++++++++++++++ .../PKCS12/certs/writeP12/keystoreCA.jks.data | 38 ++ .../PKCS12/certs/writeP12/keystoreEU.jks.data | 79 ++++ 3 files changed, 488 insertions(+) create mode 100644 jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java create mode 100644 jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data create mode 100644 jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data diff --git a/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java new file mode 100644 index 00000000000..f4024090f2f --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2003, 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 + * 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. + */ + +import static java.lang.System.out; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Base64; +import java.util.Enumeration; + +/* + * @test + * @bug 8048618 + * @summary Write different types p12 key store to Check the write related + * APIs. + * @run main WriteP12Test + */ + +public class WriteP12Test { + + private static final String IN_KEYSTORE_TYPE = "jks"; + private static final String IN_KEYSTORE_PRV = "SUN"; + + private static final String IN_KEYSTORE_ENDUSER = "keystoreEU.jks.data"; + private static final String IN_KEYSTORE_CA = "keystoreCA.jks.data"; + private static final String OUT_KEYSTORE = "outKeyStore.p12"; + + private static final String IN_STORE_PASS = "storepass"; + private static final String IN_KEY_PASS = "keypass"; + + private static final String CERT_PATH = System.getProperty("test.src", ".") + + File.separator + "certs" + File.separator + "writeP12" + + File.separator; + + private static final String CA_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIIDFzCCAf8CBD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCV\n" + + "VMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUU\n" + + "UxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAwNTUxMlo\n" + + "XDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEph\n" + + "dmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ\n" + + "1MxMiBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ\n" + + "EAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG00yi9aL\n" + + "SsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7I\n" + + "wRTYYy9clFkeeK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4e\n" + + "f1mUASo6+dea0UZA/FHCuV7O6z3hr5VHlyhJL2/o/8M5tGBTBISODJSnn\n" + + "GNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1XnIkiiXR3\n" + + "tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0\n" + + "dQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhx\n" + + "i18YQc2LPWBDLYTTxoFEazWmYLv1k/JT7Nta1qu1quvxXJ4uV1XHbd9NF\n" + + "AJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhqvO03G0Q\n" + + "imhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Yb\n" + + "k5qe3lviMZPkkSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUr\n" + + "sVOVWh7IBCqC/V7FqUTkmD1IFlzkkinatpl42s1MbhJId2yQkzaeBRc\n" + + "suE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di\n" + + "-----END CERTIFICATE-----"; + private static final String LEAD_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICwDCCAaigAwIBAgIEPz7S1jANBgkqhkiG9w0BAQQFADBQMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEXMBUGA1UEAxMOUEtDUzEyIFRlc3QgQ0EwHhcNMDAwODA5MDc\n" + + "wMDAwWhcNMTAwODA3MDcwMDAwWjBSMQswCQYDVQQGEwJVUzERMA8GA1UE\n" + + "ChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaXR5IFNRRTEZMBcGA1UEA\n" + + "xMQUEtDUzEyIFRlc3QgTGVhZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgY\n" + + "kCgYEAzq9X2USz/WjDhT+jUyZWqB5h4A33tS11YqH5qYvqjTXjcUI6gOp\n" + + "moXMafDG9RHRlIccvp51xLp7Ap3WMrv411lWBttqtZi5c1/DEC1cEM/Sl\n" + + "PCk1r2zFbkJu7QKieXeMcrjZEo6LcBHMwQjIpI+up9cr3VjuyqG/olQkU\n" + + "mXVuS0CAwEAAaMkMCIwDwYDVR0PAQH/BAUDAweAADAPBgNVHRMBAf8EBT\n" + + "ADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBhbuim98TWmtv9vSldRE7RvQ8\n" + + "FlS0TyZVO7kcSNtfCUE4R76J1ElN74Koc5pQnUtduLeQJs2ao/mEcCZsE\n" + + "zVcwI3mSZrSzPhc8s7w5gOQA4TUwVLSSjKgBCaZ7R3+qJ3QeqPJ5O6sFz\n" + + "pvBYkgSa4MWptK41jbmT8cwZQJXFCi8WxFFJ+p97F1Ppm3LgmYmtiUP4M\n" + + "ZQwOBvpTZWXU0WrqFXpzWQx0mg4SX19fZm4nLcJAerCEUphf8ILagtpQM\n" + + "EErT3/jg6mfCdT3Rj055QXPfF4OiRFevPF5a1fZgrCePCukRQZcd7s8K5\n" + + "OBIaryuM0MdFtlzxi6XWeUNpVFFHURcy\n" + + "-----END CERTIFICATE-----"; + private static final String END_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICNjCCAZ+gAwIBAgIEPz7WtzANBgkqhkiG9w0BAQQFADBSMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEZMBcGA1UEAxMQUEtDUzEyIFRlc3QgTGVhZDAeFw0wMDA4MDk\n" + + "wNzAwMDBaFw0xMDA4MDcwNzAwMDBaMFgxCzAJBgNVBAYTAlVTMREwDwYD\n" + + "VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMR8wHQYDV\n" + + "QQDExZQS0NTMTIgVGVzdCBFbmQgVXNlciAxMIGfMA0GCSqGSIb3DQEBAQ\n" + + "UAA4GNADCBiQKBgQDIKomSYomDzH/V63eDQEG7od0DLcnnVZ81pbWhDss\n" + + "8gHV2m8pADdRqdihBmnSQEaMW4D3uZ4sFE1LtkQls6hjd7SdOsG5Y24L8\n" + + "15jot9a2JcB73H8H0VKirrObL5BZdt7BtASPDnYtW4Spt++YjDoJFxyF0\n" + + "HchkavzXaVTlexakwIDAQABoxMwETAPBgNVHQ8BAf8EBQMDB4AAMA0GCS\n" + + "qGSIb3DQEBBAUAA4GBAIFA3JXEmb9AXn3RD7t+Mn6DoyVDIy5jsn6xOKT\n" + + "JV25I0obpDUzgw4QaAMmM0ZvusOmZ2wZNS8MtyTUgdANyakbzn5SdxbTy\n" + + "TLEqQsFbX8UVC38fx5ZM6ExA5YSAvgmXudZpOVC0ATccoZS3JFU8CxSfW\n" + + "+Q3IC2MLh+QTg3hUJ5b\n-----END CERTIFICATE-----"; + + private final Certificate testerCert; + private final Certificate testLeadCert; + private final Certificate caCert; + + WriteP12Test() throws CertificateException { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + caCert = cf.generateCertificate(new ByteArrayInputStream(CA_CERT_STR + .getBytes())); + testLeadCert = cf.generateCertificate(new ByteArrayInputStream( + LEAD_CERT.getBytes())); + testerCert = cf.generateCertificate(new ByteArrayInputStream(END_CERT + .getBytes())); + } + + public static void main(String[] args) throws CertificateException, + UnrecoverableKeyException, KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, IOException { + WriteP12Test jstest = new WriteP12Test(); + out.println("test WriteP12CertChain"); + /* + * WriteP12CertChain: This test creates a p12 keystore contains one + * entry with private key and a certificate chains contains three + * certificates in the order of user->lead->ca. This case expects to + * pass. + */ + jstest.test(new Certificate[] { jstest.testerCert, jstest.testLeadCert, + jstest.caCert }, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", + "pass", "pass"); + + /* + * WriteP12CertChainBad: same as WriteP12CertChain but chains order is + * user-ca-lead, the order is wrong so expects to fail. + */ + out.println("test WriteP12CertChainBad"); + try { + jstest.test(new Certificate[] { jstest.testerCert, jstest.caCert, + jstest.testLeadCert }, IN_KEYSTORE_ENDUSER, + "pkcs12testenduser1", "pass", "pass"); + throw new RuntimeException( + " Certificate chain is not valid, test should not pass." + + " Test failed."); + } catch (KeyStoreException e) { + e.printStackTrace(); + out.println(" Certificate chain is not valid,exception is" + + " expected. Test passed."); + } + /* + * WriteP12PrivateKey:This test creates a p12 contains a self-signed + * cert and private key,expects no exception + */ + out.println("test WriteP12PrivateKey"); + jstest.test(null, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", "pass", + "pass"); + + /* + * WriteP12TwoEntry: This test creates a p12 keystore with different + * storepass and keypass, and contains two entries. + */ + out.println("test WriteP12TwoEntry"); + jstest.testTwoEntry(IN_KEYSTORE_ENDUSER, IN_KEYSTORE_CA, + "pkcs12testenduser1", "pass", "pass"); + /* + * WriteP12TwoPass: This test creates a p12 keystore with different + * storepass and keypass, and contains one entry with private key and a + * certificate + */ + out.println("test WriteP12TwoPass"); + jstest.test(null, IN_KEYSTORE_CA, "pkcs12testCA", "storepass", + "keypass"); + } + + private void test(Certificate certs[], String inKeyStorePath, + String userAlias, String outStorePass, String outKeyPass) + throws KeyStoreException, NoSuchProviderException, IOException, + CertificateException, UnrecoverableKeyException, + NoSuchAlgorithmException { + // init output key store + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + outputKeyStore.load(null, null); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE)) { + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] input = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStorePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(input)); + // input key store + KeyStore inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray()); + // add key/certificate to output key store + Key key = inputKeyStore + .getKey(userAlias, IN_KEY_PASS.toCharArray()); + out.println("Input Key Algorithm " + key.getAlgorithm()); + out.println("====Input Certs====="); + if (certs == null) { + certs = new Certificate[] { inputKeyStore + .getCertificate(userAlias) }; + } + for (Certificate cert : certs) { + out.println(((X509Certificate) cert).getSubjectDN()); + } + outputKeyStore.setKeyEntry(userAlias, key, + outKeyPass.toCharArray(), certs); + Certificate retCerts[] = outputKeyStore + .getCertificateChain(userAlias); + out.println("====Output Certs====="); + for (Certificate retCert : retCerts) { + out.println(((X509Certificate) retCert).getSubjectDN()); + } + out.println("====Output Key Algorithm====="); + Key outKey = outputKeyStore.getKey(userAlias, + outKeyPass.toCharArray()); + out.println(outKey.getAlgorithm()); + + if (!key.equals(outKey)) { + throw new RuntimeException("key don't match"); + } + if (!Arrays.equals(certs, retCerts)) { + throw new RuntimeException("certs don't match"); + } + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testTwoEntry(String inKeyStoreOnePath, + String inKeyStoreTwoPath, String userAlias, String outStorePass, + String outKeyPass) throws KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, + CertificateException, IOException, UnrecoverableKeyException { + // initial KeyStore + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE);) { + outputKeyStore.load(null, null); + KeyStore inputKeyStoreOne, inputKeyStoreTwo; + inputKeyStoreOne = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreOnePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(inputBytes)); + // input key store + inputKeyStoreOne.load(arrayIn, IN_STORE_PASS.toCharArray()); + + inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreTwoPath)); + arrayIn = new ByteArrayInputStream(Base64.getMimeDecoder().decode( + inputBytes)); + inputKeyStoreTwo = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStoreTwo.load(arrayIn, IN_STORE_PASS.toCharArray()); + + // add key/certificate to output key store + out.println("====First Entry====="); + Key inputKey = inputKeyStoreOne.getKey(userAlias, + IN_KEY_PASS.toCharArray()); + Certificate cert = inputKeyStoreOne.getCertificate(userAlias); + Certificate certs[] = new Certificate[1]; + certs[0] = cert; + + out.println("====Input1 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input1 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("USER", inputKey, + outKeyPass.toCharArray(), certs); + out.println("====Second Entry====="); + String caAlias = "pkcs12testca"; + inputKey = inputKeyStoreTwo.getKey(caAlias, + IN_KEY_PASS.toCharArray()); + cert = inputKeyStoreTwo.getCertificate(caAlias); + certs[0] = cert; + out.println("====Input2 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input2 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("CA", inputKey, + outKeyPass.toCharArray(), certs); + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testKeyStore(KeyStore inputKeyStore, char[] keypass) + throws KeyStoreException, UnrecoverableKeyException, + NoSuchAlgorithmException { + out.println("========== Key Store =========="); + out.println("getProvider : " + inputKeyStore.getProvider()); + out.println("getType : " + inputKeyStore.getType()); + out.println("getDefaultType : " + KeyStore.getDefaultType()); + + int idx = 0; + Enumeration e = inputKeyStore.aliases(); + String alias; + while (e.hasMoreElements()) { + alias = e.nextElement(); + if (!inputKeyStore.containsAlias(alias)) { + throw new RuntimeException("Alias not found"); + } + out.println("Alias " + idx + " : " + alias); + out.println("getCreationDate : " + + inputKeyStore.getCreationDate(alias)); + X509Certificate cert = (X509Certificate) inputKeyStore + .getCertificate(alias); + out.println("getCertificate : " + cert.getSubjectDN()); + String retAlias = inputKeyStore.getCertificateAlias(cert); + if (!retAlias.equals(alias)) { + throw new RuntimeException("Alias mismatch, actually " + + retAlias + ", expected " + alias); + } + out.println("getCertificateAlias : " + retAlias); + Certificate[] certs = inputKeyStore.getCertificateChain(alias); + int i = 0; + for (Certificate certification : certs) { + out.println("getCertificateChain " + i + + ((X509Certificate) certification).getSubjectDN()); + i++; + } + if (inputKeyStore.isCertificateEntry(alias)) { + throw new RuntimeException( + "inputKeystore should not be certEntry because this" + + " keystore only contain key pair entries."); + } + if (!inputKeyStore.isKeyEntry(alias)) { + throw new RuntimeException("Entry type unknown."); + } + idx++; + } + int size = inputKeyStore.size(); + if (idx != size) { + throw new RuntimeException("Size not match, actually " + idx + + ", expected " + size); + } + } + +} diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data new file mode 100644 index 00000000000..1d6b5a4b6ac --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data @@ -0,0 +1,38 @@ +/u3+7QAAAAIAAAABAAAAAQAMcGtjczEydGVzdGNhAAAA9w1mDAMAAAUCMIIE/jAOBgorBgEEASoC +EQEBBQAEggTqFhceJz85XyVsicsfonXYx+vvFXkb9Jmr11eh9n570ZdiFZ1hv4XRk/x/1C1spy5X +J2wv4lABGAOA5gV0aTKij+82NLoEz9zDW5fwAnrBKVjAq/NxdwEi9lvipiSVx1qglx/mQAHeEi4i +6vDoai3hVNQqVmd/TG2deyk/fQ9MZ7U2fmWcJDH4YbP39psQ+7rp9cDJ0P7GWoLXwbWs1vftbN0R +4fWitH1+6hBbIbVT9o0cM9ilAjpkNFr10pBEsfrikaE8IsN562soWfNxGwwrsjExEFeKlMrtNtWM +Wc4+YZ1ybVi/6krK/kFfOa+R3mtjBoD7zM4TSG9dptuvBLVgey8RXh3BQ8pU7uN5q+9Omqo1SsRN +wHYKjTrfWMozt+37ZlyCZ70Kb/2jJYWFuo9+wqXQU+MYnpZZB+cLt3PIFMakhIu1vpMpJCcoceaS +bjDWxCG8HHZjjFJPxAE3HEbCzaj4BevxQfxtp57llmtI2I0NJvua8JbFjf0U9MK6iRi4IpmBztpP +vxvaetT54wC+2c0QaDqANIn3Oc4tmvD4RGJfmFrEYEX6dQbCwYHAJF8sczqDb4xIYwrGmiMNeeha +4g9fcEa7Q+t1o1XLmNOp5e6I/TjUfXGvKlEyYeQ1FNLRqTtI5KvHQ1l71n1aQyEPvcff93NlF3jv +jWuqOqLzFT7sIZQxgjoum4i0DwLzOtuAWIDELNJ03MCciq5j0SjoLO2/ISctNTyGuYBmerjGCI9c +CLhGYnwLCOvvZN1yIqT79Se6qe/tBV5nEYUdXEt4ROJNabf1H4GmkXYeDQvtHrQ1IHM+Kg1UyEJz +fwdhJ68EU3gFenTtFgVJ+90YpemGtptgS6CvS3qC2H/H3XaKKQGpsXRCMSCRZcfMMOQEc6WLPsVY +rEhorQIAbbgHp4//H+RkNzG+5NN4pac5bo0kDTpeQkiOXGZZKyMHgagFvwLCN35rTi2HnHEXnYoi +jU1sGmUV+kRgRJ+N3Gx6D+uWNctkZMeTuVg+9ftIhEClGdtBSXWZu9lr/48cXkWJBubd4CWYrFMm +cTYezlQiTvmQgodrrwtcdo17J/L4PK74C72aIqPlWdEImGQs7I4n1mvceXoHvjYu5+tOxS0HH4sm +Y4iMr3hsqVAag2/LeLCG1gumpGiTdh9hk/aOcSWASv7rjq8JVpxWJe3JbrQ5k0U3e1nE2AdSXjEj +knBDpDFpGsnJaP2xxTdvQ+oV1pZ3m30xOeCTVV+0VBIw8eL0PDATSgqQ7FuWnYZ/FGaOrgnn14JM +HQicEfFN7TOa8q3/lbY5JTRtuG5umoWL2AWaaAW6G5GRTUNMOvBI5xTvR/kr3iNKTK2caKi0XTJ3 +WXd9jeuyLstpbtokG6xBbSiAb/SSL9yoh400DbKFTlVHKD8cijfuLKIM1TmL2ZksEh6JvF8GfdLl +FXZH7Ny8aJ63Ef947P9Y8+6WMzZDrkyoV+uInRq1TVXk6Ps6qiqI0j9fhMI8XMju61vjkeXprzBE +Pk2GbXo7MtHrBTobffkD3BszrFJai8n9vDrQgsaZYwWi4IxlKYefmWDaagiq/qDBZhKQCgyuJNN/ +5sQZDb6+J/MIgDk0M2bXEs6f2gT1rAyuH+rbnsnfUu9jRQupP4q0/ZCY2WOIaf8W34FnMdNzOUH8 +iE2T59UbMGQ0DLJeHwAAAAEABVguNTA5AAADGzCCAxcwggH/AgQ/PtJwMA0GCSqGSIb3DQEBBQUA +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcwMDU1MTJaFw0xMzA4MTQwMDU1MTJa +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEMBtNMovWi0rGQKjaSUgg76YMkjgFJ +gXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZHniuHR2sW7hTD6VLu8kH8Ek14Lzg +P1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+VR5coSS9v6P/DObRgUwSEjgyUp5x +jQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V5yJIol0d7Y2gUgfl4aAn7hvCrSJ1 +1xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAc12f +Mx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZPyU+zbWtartarr8VyeLldVx23fTRQ +CVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThIarztNxtEIpoZIjbfTBey+vctlNP1 +O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT5JEl3qUySPJtAIlwo4vnl4/e41S3 +h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JIp2raZeNrNTG4SSHdskJM2ngUXLLh +Ot2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4nYQH5SPMKBNY+nGGfmMLaFPAelF \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data new file mode 100644 index 00000000000..c8e4ecf4705 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data @@ -0,0 +1,79 @@ +/u3+7QAAAAIAAAADAAAAAgAMcGtjczEydGVzdGNhAAAA9w18bwQABVguNTA5AAADGzCCAxcwggH/ +AgQ/PtJwMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcw +MDU1MTJaFw0xMzA4MTQwMDU1MTJaMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEM +BtNMovWi0rGQKjaSUgg76YMkjgFJgXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZ +HniuHR2sW7hTD6VLu8kH8Ek14LzgP1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+ +VR5coSS9v6P/DObRgUwSEjgyUp5xjQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V +5yJIol0d7Y2gUgfl4aAn7hvCrSJ11xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATAN +BgkqhkiG9w0BAQUFAAOCAQEAc12fMx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZP +yU+zbWtartarr8VyeLldVx23fTRQCVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThI +arztNxtEIpoZIjbfTBey+vctlNP1O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT +5JEl3qUySPJtAIlwo4vnl4/e41S3h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JI +p2raZeNrNTG4SSHdskJM2ngUXLLhOt2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4gAAAAIADnBrY3Mx +MnRlc3RsZWFkAAAA9w1+meMABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcN +AQEEBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3 +MDAwMFowUjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxGTAXBgNVBAMTEFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ +AoGBAM6vV9lEs/1ow4U/o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6ed +cS6ewKd1jK7+NdZVgbbarWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSP +rqfXK91Y7sqhv6JUJFJl1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBO +Ee+idRJTe+CqHOaUJ1LXbi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmm +e0d/qid0HqjyeTurBc6bwWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DG +UMDgb6U2Vl1NFq6hV6c1kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9Oe +UFz3xeDokRXrzxeWtX2YKwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAAAAEA +EnBrY3MxMnRlc3RlbmR1c2VyMQAAAPcNgTivAAACuTCCArUwDgYKKwYBBAEqAhEBAQUABIICoU6N +bD6qkNDM8KJFHCTHUevURAV8SUuzzBwsfYC0tEDMa2zGNUEvrmgyM3b5z7qR8XbTZvVBFJJLp3Jx +HmQpg0vLltDFFIPiVgRVcUEDPSmks1KP/bP/mE1uos31R6VyfNMGS3JnQblcSipcB893NrFFXNu2 +PUPjKCC9GrQZAmSM78BBTrwWD/Yd4rKcVh57DLKtUySoF29qXthusJjhSaqRZERaMV6egviE5+W8 +f8ppTYLx2gJmOyi9edJEdHxMcPzRvWgxlmUqUCDg0KVsosbxjjJKcmJ9b1KWuadKyAYkqxSDi8sx +2iwEQW3PQjLGBVHeQNntUF1wapp21sD1lVmDV3+61+fIphAUVRQXjmoYsEhrTc93IkDtQWgfJsgz +xjVVDbcy29VnMAK4f3tT/p5HeFO6yRQBE2B3IngSomRxbNh143VswNYqtZYy03UhOm8vbF2OfOJ/ +NzwC/F+19XgntnC0qv5j6VzwMGTt2NYPWXUqSzVIFswSunj70+ZsprCRX5IEFnpHDSL7OwDjEMFc +z6dpYQ9pwgyKh7JiLZxAr/9Nhb8QQDGrolzHoDt1QnC/DYvDGfTKu0ZjlXR4EQN4XFV+FAiykRfA +N1jIsTY7fCmLpLuW4paQnR1lPSGLeSvi63DOgN+lfVSJ5YjZm4yIRIS6lpvLVgcqodDqBRmPMP7x +fJ3osv1Wt4L/77BdJpZrUUygysRpzyUKlC6NwXr338HKPyAnfrkzIpHKnhTUaRVmfgAuzrXMFp8C +ejyYXJQwPPFAL5mIdUMkLDQKzESI0T3AD1LWVDM/0mGud9GhqiycI6AqC0j7MynRCvQG0LyRunFG +EQ2KipM//qPFKqwoVukxrLTunmGyeOe6UxodtK+qcn7SIXZ8jJM14a5rSDwAAAADAAVYLjUwOQAA +AjowggI2MIIBn6ADAgECAgQ/Pta3MA0GCSqGSIb3DQEBBAUAMFIxCzAJBgNVBAYTAlVTMREwDwYD +VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMRkwFwYDVQQDExBQS0NTMTIgVGVz +dCBMZWFkMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowWDELMAkGA1UEBhMCVVMxETAP +BgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBU +ZXN0IEVuZCBVc2VyIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMgqiZJiiYPMf9Xrd4NA +Qbuh3QMtyedVnzWltaEOyzyAdXabykAN1Gp2KEGadJARoxbgPe5niwUTUu2RCWzqGN3tJ06wbljb +gvzXmOi31rYlwHvcfwfRUqKus5svkFl23sG0BI8Odi1bhKm375iMOgkXHIXQdyGRq/NdpVOV7FqT +AgMBAAGjEzARMA8GA1UdDwEB/wQFAwMHgAAwDQYJKoZIhvcNAQEEBQADgYEAgUDclcSZv0BefdEP +u34yfoOjJUMjLmOyfrE4pMlXbkjShukNTODDhBoAyYzRm+6w6ZnbBk1Lwy3JNSB0A3JqRvOflJ3F +tPJMsSpCwVtfxRULfx/HlkzoTEDlhIC+CZe51mk5ULQBNxyhlLckVTwLFJ9b5DcgLYwuH5BODeFQ +nlsABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcNAQEEBQAwUDELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMT +DlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowUjELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxGTAXBgNVBAMT +EFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM6vV9lEs/1ow4U/ +o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6edcS6ewKd1jK7+NdZVgbba +rWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSPrqfXK91Y7sqhv6JUJFJl +1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBOEe+idRJTe+CqHOaUJ1LX +bi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmme0d/qid0HqjyeTurBc6b +wWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DGUMDgb6U2Vl1NFq6hV6c1 +kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9OeUFz3xeDokRXrzxeWtX2Y +KwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAFWC41MDkAAAMbMIIDFzCCAf8C +BD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAw +NTUxMloXDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG +00yi9aLSsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7IwRTYYy9clFke +eK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4ef1mUASo6+dea0UZA/FHCuV7O6z3hr5V +HlyhJL2/o/8M5tGBTBISODJSnnGNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1Xn +IkiiXR3tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0dQIDAQABMA0G +CSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhxi18YQc2LPWBDLYTTxoFEazWmYLv1k/J +T7Nta1qu1quvxXJ4uV1XHbd9NFAJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhq +vO03G0QimhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Ybk5qe3lviMZPk +kSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUrsVOVWh7IBCqC/V7FqUTkmD1IFlzkkin +atpl42s1MbhJId2yQkzaeBRcsuE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di7p2dz0wNRNimbVP4 +VL+NWQOgtME= \ No newline at end of file From 7e09df43e65bdd56df31e0b6eb48db194739923f Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Mon, 23 Mar 2015 02:29:47 -0700 Subject: [PATCH 64/79] 8075569: jmap test fails due to "ERROR: java.nio.file.NoSuchFileException: 2906081d-06bc-4738-a7e8-f37b8bf13658.lck" Lock file is deleted while we are setting modified time Reviewed-by: alanb --- jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java index 1ac1a137088..a6f1a64ee88 100644 --- a/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java +++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java @@ -417,7 +417,9 @@ public class LingeredApp { setLastModified(theLockFileName, epoch()); Thread.sleep(spinDelay); } - + } catch (NoSuchFileException ex) { + // Lock deleted while we are setting last modified time. + // Ignore error and lets the app exits } catch (Exception ex) { System.err.println("LingeredApp ERROR: " + ex); // Leave exit_code = 1 to Java launcher From 497fe8d068fc9caa720424dadfe32b6a4a5d0032 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Mon, 23 Mar 2015 14:20:39 +0100 Subject: [PATCH 65/79] 8075560: Typo in Javadoc for java.util.Optional.equals() Reviewed-by: alanb --- jdk/src/java.base/share/classes/java/util/Optional.java | 2 +- jdk/src/java.base/share/classes/java/util/OptionalDouble.java | 2 +- jdk/src/java.base/share/classes/java/util/OptionalInt.java | 2 +- jdk/src/java.base/share/classes/java/util/OptionalLong.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Optional.java b/jdk/src/java.base/share/classes/java/util/Optional.java index 21fef4c13e0..cc5c1309663 100644 --- a/jdk/src/java.base/share/classes/java/util/Optional.java +++ b/jdk/src/java.base/share/classes/java/util/Optional.java @@ -346,7 +346,7 @@ public final class Optional { * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff --git a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java index 3de841e80f4..88c4cbf04b2 100644 --- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java +++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java @@ -244,7 +244,7 @@ public final class OptionalDouble { * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff --git a/jdk/src/java.base/share/classes/java/util/OptionalInt.java b/jdk/src/java.base/share/classes/java/util/OptionalInt.java index 38b9bd0294c..92a1d855be8 100644 --- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java +++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java @@ -244,7 +244,7 @@ public final class OptionalInt { * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff --git a/jdk/src/java.base/share/classes/java/util/OptionalLong.java b/jdk/src/java.base/share/classes/java/util/OptionalLong.java index d6d56b9aee4..9a4c4d22f48 100644 --- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java +++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java @@ -244,7 +244,7 @@ public final class OptionalLong { * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override From 7cb7ae5914c92a86a44c64882f1cde82974cc309 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 23 Mar 2015 09:52:42 -0400 Subject: [PATCH 66/79] 8071480: (process spec) ProcessBuilder.start spec linked to the wrong checkRead and checkWrite methods Disambiguate with links to checkRead(String) and checkWrite(String) Reviewed-by: alanb, martin --- jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index 940084cfbc6..0cb6f741326 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -988,14 +988,14 @@ public final class ProcessBuilder *
  • the standard input to the subprocess was * {@linkplain #redirectInput redirected from a file} * and the security manager's - * {@link SecurityManager#checkRead checkRead} method + * {@link SecurityManager#checkRead(String) checkRead} method * denies read access to the file, or * *
  • the standard output or standard error of the * subprocess was * {@linkplain #redirectOutput redirected to a file} * and the security manager's - * {@link SecurityManager#checkWrite checkWrite} method + * {@link SecurityManager#checkWrite(String) checkWrite} method * denies write access to the file * * From c92b8a33a683928764bcd4eabba90443a43f062a Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 23 Mar 2015 09:53:08 -0400 Subject: [PATCH 67/79] 8073220: A typo in the documentation for class ProcessBuilder Correct reference to be OutputStream Reviewed-by: martin, alanb --- jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index 0cb6f741326..f49b6a9cb9b 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -82,7 +82,7 @@ import java.util.Map; *
  • a destination for standard output * and standard error. By default, the subprocess writes standard * output and standard error to pipes. Java code can access these pipes - * via the input streams returned by {@link Process#getInputStream()} and + * via the input streams returned by {@link Process#getOutputStream()} and * {@link Process#getErrorStream()}. However, standard output and * standard error may be redirected to other destinations using * {@link #redirectOutput(Redirect) redirectOutput} and From a056457b52b51d01b2fcb2cd327145e9219fee6a Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 23 Mar 2015 10:13:32 -0400 Subject: [PATCH 68/79] 8067796: (process) Process.waitFor(timeout, unit) doesn't throw NPE if timeout is less than, or equal to zero when unit == null Implement checking for NPE in Process implementation before other conditions Reviewed-by: martin, chegar --- .../unix/classes/java/lang/ProcessImpl.java | 3 +- .../classes/java/lang/ProcessImpl.java | 3 +- jdk/test/java/lang/ProcessBuilder/Basic.java | 51 +++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java index a35405fc8d9..42d40592633 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -496,12 +496,11 @@ final class ProcessImpl extends Process { public synchronized boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (hasExited) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos; - do { // Round up to next millisecond wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L)); diff --git a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java index ec90ea0da3a..f6ed286d991 100644 --- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -458,12 +458,11 @@ final class ProcessImpl extends Process { public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos ; - do { // Round up to next millisecond long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L); diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index cfc4d443ff8..93855f19bcb 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -27,6 +27,7 @@ * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464 + * 8067796 * @summary Basic tests for Process and Environment Variable code * @run main/othervm/timeout=300 Basic * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic @@ -2386,6 +2387,56 @@ public class Basic { p.destroy(); } catch (Throwable t) { unexpected(t); } + //---------------------------------------------------------------- + // Check that Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process p = new ProcessBuilder(childArgs).start(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // Check that default implementation of Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process proc = new ProcessBuilder(childArgs).start(); + final DelegatingProcess p = new DelegatingProcess(proc); + + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + //---------------------------------------------------------------- // Check the default implementation for // Process.waitFor(long, TimeUnit) From 07cd37173808518d4e2a71e6945785741ec277ab Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 23 Mar 2015 09:45:32 -0700 Subject: [PATCH 69/79] 8075670: Remove intermittent keyword from some tests Reviewed-by: alanb --- jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java | 1 - jdk/test/java/nio/channels/Selector/Wakeup.java | 1 - jdk/test/java/nio/file/Files/InterruptCopy.java | 1 - 3 files changed, 3 deletions(-) diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index 8f9e426a740..9442f9b5408 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -25,7 +25,6 @@ * @bug 4607272 6842687 6878369 6944810 7023403 * @summary Unit test for AsynchronousSocketChannel * @run main Basic -skipSlowConnectTest - * @key intermittent */ import java.nio.ByteBuffer; diff --git a/jdk/test/java/nio/channels/Selector/Wakeup.java b/jdk/test/java/nio/channels/Selector/Wakeup.java index e51bd1d38fc..40aa71729c8 100644 --- a/jdk/test/java/nio/channels/Selector/Wakeup.java +++ b/jdk/test/java/nio/channels/Selector/Wakeup.java @@ -25,7 +25,6 @@ * @bug 6405995 * @summary Unit test for selector wakeup and interruption * @library .. - * @key intermittent */ import java.io.*; diff --git a/jdk/test/java/nio/file/Files/InterruptCopy.java b/jdk/test/java/nio/file/Files/InterruptCopy.java index 29cfa006e40..c83479c9e46 100644 --- a/jdk/test/java/nio/file/Files/InterruptCopy.java +++ b/jdk/test/java/nio/file/Files/InterruptCopy.java @@ -25,7 +25,6 @@ * @bug 4313887 6993267 * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option * @library .. - * @key intermittent */ import java.nio.file.*; From 2b63b5d1d76914fa75b884e386f7f84bbcde53f4 Mon Sep 17 00:00:00 2001 From: Lev Priima Date: Tue, 24 Mar 2015 03:46:57 -0400 Subject: [PATCH 70/79] 8075071: [TEST_BUG] TimSortStackSize2.java: OOME: Java heap space: MaxHeap shrinked by MaxRAMFraction Reviewed-by: dholmes --- .../java/util/Arrays/TimSortStackSize2.java | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/util/Arrays/TimSortStackSize2.java b/jdk/test/java/util/Arrays/TimSortStackSize2.java index a456c883000..9e212fd00bd 100644 --- a/jdk/test/java/util/Arrays/TimSortStackSize2.java +++ b/jdk/test/java/util/Arrays/TimSortStackSize2.java @@ -24,22 +24,63 @@ /* * @test * @bug 8072909 - * @run main/othervm -Xms385m TimSortStackSize2 67108864 + * @library /lib/testlibrary /../../test/lib + * @build jdk.testlibrary.* + * @build TimSortStackSize2 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TimSortStackSize2 * @summary Test TimSort stack size on big arrays - * big tests not for regular execution on all platforms: - * run main/othervm -Xmx8g TimSortStackSize2 1073741824 - * run main/othervm -Xmx16g TimSortStackSize2 2147483644 */ import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.function.Consumer; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; +import sun.hotspot.WhiteBox; + public class TimSortStackSize2 { public static void main(String[] args) { - int lengthOfTest = Integer.parseInt(args[0]); + if ( args == null || args.length == 0 ){ + startMeWithArgs(); + } else { + doTestOfTwoTimSorts(Integer.parseInt(args[0])); + } + } + + private static void startMeWithArgs(){ + /* + * big tests not for regular execution on all platforms: + * run main/othervm -Xmx8g TimSortStackSize2 1073741824 + * run main/othervm -Xmx16g TimSortStackSize2 2147483644 + */ + try { + Boolean compressedOops = WhiteBox.getWhiteBox() + .getBooleanVMFlag("UseCompressedOops"); + final String xmsValue = "-Xms" + + ((compressedOops == null || compressedOops) ? "385" : "770") + + "m"; + System.out.println( "compressedOops: " + compressedOops + + "; Test will be started with \"" + xmsValue + "\""); + ProcessBuilder processBuilder = ProcessTools + .createJavaProcessBuilder(Utils.addTestJavaOpts(xmsValue, + "TimSortStackSize2", "67108864" + ) + ); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println(output.getOutput()); + output.shouldHaveExitValue(0); + } catch( Exception e ){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + private static void doTestOfTwoTimSorts(final int lengthOfTest){ boolean passed = doTest("TimSort", lengthOfTest, (Integer [] a) -> Arrays.sort(a)); passed = doTest("ComparableTimSort", lengthOfTest, (Integer [] a) -> From 82dd135b5fb6b3262c5fbbb6c047d16025b5ec8a Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 24 Mar 2015 14:48:11 +0000 Subject: [PATCH 71/79] 8075824: Add default[Read|Write]Object to java.util.Date Reviewed-by: alanb, rriggs --- jdk/src/java.base/share/classes/java/util/Date.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/src/java.base/share/classes/java/util/Date.java b/jdk/src/java.base/share/classes/java/util/Date.java index c05f50c4b95..253b67a792a 100644 --- a/jdk/src/java.base/share/classes/java/util/Date.java +++ b/jdk/src/java.base/share/classes/java/util/Date.java @@ -1317,6 +1317,7 @@ public class Date private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); s.writeLong(getTimeImpl()); } @@ -1326,6 +1327,7 @@ public class Date private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); fastTime = s.readLong(); } From 6a2c954d633d1edbb1aaff3c7f46900c0330a9ea Mon Sep 17 00:00:00 2001 From: Jason Uh Date: Tue, 24 Mar 2015 11:31:04 -0700 Subject: [PATCH 72/79] 8074531: Remove javax.security.cert.X509Certificate usage in internal networking packages Reviewed-by: mullan --- .../com/sun/net/ssl/HttpsURLConnection.java | 9 +++---- .../https/HttpsURLConnectionOldImpl.java | 21 +--------------- .../AbstractDelegateHttpsURLConnection.java | 21 ---------------- .../net/www/protocol/https/HttpsClient.java | 15 ------------ .../https/HttpsURLConnectionImpl.java | 24 ------------------- .../net/ssl/FixingJavadocs/ComURLNulls.java | 4 ++-- .../https/NewImpl/ComHTTPSConnection.java | 8 +++---- 7 files changed, 12 insertions(+), 90 deletions(-) diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java index c60435331ec..6ce3b16ff0b 100644 --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -32,10 +32,10 @@ package com.sun.net.ssl; import java.net.URL; import java.net.HttpURLConnection; import java.io.IOException; +import java.security.cert.Certificate; import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; - -import javax.security.cert.X509Certificate; +import javax.net.ssl.SSLPeerUnverifiedException; /** * HTTP URL connection with support for HTTPS-specific features. See @@ -70,7 +70,8 @@ class HttpsURLConnection extends HttpURLConnection * the server did not authenticate. * @return the server certificate chain */ - public abstract X509Certificate [] getServerCertificateChain(); + public abstract Certificate[] getServerCertificates() + throws SSLPeerUnverifiedException; /** * HostnameVerifier provides a callback mechanism so that diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java index fba0b3befce..07ff87ba85a 100644 --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -187,25 +187,6 @@ public class HttpsURLConnectionOldImpl return delegate.getServerCertificates(); } - /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - */ - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - /* * Allowable input/output sequences: * [interpreted as POST/PUT] diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java index 9d70053d35f..cb80173b506 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java @@ -261,27 +261,6 @@ public abstract class AbstractDelegateHttpsURLConnection extends } } - /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() - throws SSLPeerUnverifiedException { - if (cachedResponse != null) { - throw new UnsupportedOperationException("this method is not supported when using cache"); - } - if (http == null) { - throw new IllegalStateException("connection not yet open"); - } else { - return ((HttpsClient)http).getServerCertificateChain(); - } - } - /** * Returns the server's principal, or throws SSLPeerUnverifiedException * if the server did not authenticate. diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 5bc55ed9e50..3aecc419cb2 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -696,21 +696,6 @@ final class HttpsClient extends HttpClient return session.getPeerCertificates(); } - /** - * Returns the X.509 certificate chain with which the server - * authenticated itself, or null if the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - javax.security.cert.X509Certificate [] getServerCertificateChain() - throws SSLPeerUnverifiedException - { - return session.getPeerCertificateChain(); - } - /** * Returns the principal with which the server authenticated * itself, or throw a SSLPeerUnverifiedException if the diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java index 5477b2cab80..429079804f0 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java @@ -197,30 +197,6 @@ public class HttpsURLConnectionImpl return delegate.getServerCertificates(); } - /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - /** * Returns the principal with which the server authenticated itself, * or throw a SSLPeerUnverifiedException if the server did not authenticate. diff --git a/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java index 88aa92772c8..e0dc82a2dc1 100644 --- a/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java +++ b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, 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 @@ -80,7 +80,7 @@ public class ComURLNulls { } try { - urlc.getServerCertificateChain(); + urlc.getServerCertificates(); } catch (IllegalStateException e) { System.out.print("Caught proper exception: "); System.out.println(e.getMessage()); diff --git a/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java index 486d234003c..24e2572f78f 100644 --- a/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java +++ b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, 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 @@ -34,8 +34,8 @@ import java.io.*; import java.net.*; +import java.security.cert.Certificate; import javax.net.ssl.*; -import javax.security.cert.*; import com.sun.net.ssl.HostnameVerifier; import com.sun.net.ssl.HttpsURLConnection; @@ -240,8 +240,8 @@ public class ComHTTPSConnection { System.out.println("Cipher Suite: " + ((HttpsURLConnection)urlc).getCipherSuite()); - X509Certificate[] certs = - ((HttpsURLConnection)urlc).getServerCertificateChain(); + Certificate[] certs = + ((HttpsURLConnection)urlc).getServerCertificates(); for (int i = 0; i < certs.length; i++) { System.out.println(certs[0]); } From 78c0bdbda5a48726d64b9ffb9308288a80137873 Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Wed, 25 Mar 2015 17:59:59 +0900 Subject: [PATCH 73/79] 8075173: DateFormat in german locale returns wrong value for month march Reviewed-by: naoto, peytoia --- .../share/classes/sun/text/resources/de/FormatData_de.java | 4 ++-- jdk/test/sun/text/resources/LocaleData | 3 +++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java index 435a79742d2..85c079cbb32 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -142,7 +142,7 @@ public class FormatData_de extends ParallelListResourceBundle { new String[] { "Jan", // abb january "Feb", // abb february - "Mrz", // abb march + "M\u00e4r", // abb march "Apr", // abb april "Mai", // abb may "Jun", // abb june diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 719cc3df066..9033fe6c125 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -8279,3 +8279,6 @@ FormatData/fi/DatePatterns/0=d. MMMM yyyy FormatData/fi/DatePatterns/1=d. MMMM yyyy FormatData/fi/DatePatterns/2=d.M.yyyy FormatData/fi/DatePatterns/3=d.M.yyyy + +# bug #8075173 +FormatData/de/standalone.MonthAbbreviations/2=M\u00e4r diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 96d6d1d9a75..bd2b331fc78 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -36,7 +36,7 @@ * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 8017142 - * 8037343 8055222 8042126 8074791 + * 8037343 8055222 8042126 8074791 8075173 * @summary Verify locale data * */ From b220e6cb1dd273dc4e97ae81dff1f0f6d795ea38 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Wed, 25 Mar 2015 10:50:08 +0000 Subject: [PATCH 74/79] 8075307: Pipeline calculating inconsistent flag state for parallel stateful ops Reviewed-by: smarks --- .../java/util/stream/AbstractPipeline.java | 120 ++++++++---------- .../classes/java/util/stream/ReduceOps.java | 20 +++ .../java/util/stream/UnorderedTest.java | 4 +- .../tests/java/util/stream/CountTest.java | 58 ++++++++- .../java/util/stream/DistinctOpTest.java | 4 +- 5 files changed, 137 insertions(+), 69 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java index e0ca02101da..c4cc508421c 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -379,60 +379,6 @@ abstract class AbstractPipeline> return StreamOpFlag.toStreamFlags(combinedFlags); } - /** - * Prepare the pipeline for a parallel execution. As the pipeline is built, - * the flags and depth indicators are set up for a sequential execution. - * If the execution is parallel, and there are any stateful operations, then - * some of these need to be adjusted, as well as adjusting for flags from - * the terminal operation (such as back-propagating UNORDERED). - * Need not be called for a sequential execution. - * - * @param terminalFlags Operation flags for the terminal operation - */ - private void parallelPrepare(int terminalFlags) { - @SuppressWarnings("rawtypes") - AbstractPipeline backPropagationHead = sourceStage; - if (sourceStage.sourceAnyStateful) { - int depth = 1; - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage; - p != null; - u = p, p = p.nextStage) { - int thisOpFlags = p.sourceOrOpFlags; - if (p.opIsStateful()) { - // If the stateful operation is a short-circuit operation - // then move the back propagation head forwards - // NOTE: there are no size-injecting ops - if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { - backPropagationHead = p; - // Clear the short circuit flag for next pipeline stage - // This stage encapsulates short-circuiting, the next - // stage may not have any short-circuit operations, and - // if so spliterator.forEachRemaining should be used - // for traversal - thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; - } - - depth = 0; - // The following injects size, it is equivalent to: - // StreamOpFlag.combineOpFlags(StreamOpFlag.IS_SIZED, p.combinedFlags); - thisOpFlags = (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED; - } - p.depth = depth++; - p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); - } - } - - // Apply the upstream terminal flags - if (terminalFlags != 0) { - int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; - for ( @SuppressWarnings("rawtypes") AbstractPipeline p = backPropagationHead; p.nextStage != null; p = p.nextStage) { - p.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, p.combinedFlags); - } - - combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); - } - } - /** * Get the source spliterator for this pipeline stage. For a sequential or * stateless parallel pipeline, this is the source spliterator. For a @@ -456,24 +402,70 @@ abstract class AbstractPipeline> throw new IllegalStateException(MSG_CONSUMED); } - if (isParallel()) { - // @@@ Merge parallelPrepare with the loop below and use the - // spliterator characteristics to determine if SIZED - // should be injected - parallelPrepare(terminalFlags); + boolean hasTerminalFlags = terminalFlags != 0; + if (isParallel() && sourceStage.sourceAnyStateful) { + // Adjust pipeline stages if there are stateful ops, + // and find the last short circuiting op, if any, that + // defines the head stage for back-propagation of terminal flags + @SuppressWarnings("rawtypes") + AbstractPipeline backPropagationHead = sourceStage; + int depth = 1; + for (@SuppressWarnings("rawtypes") AbstractPipeline p = sourceStage.nextStage; + p != null; + p = p.nextStage) { + if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(p.sourceOrOpFlags)) { + // If the stateful operation is a short-circuit operation + // then move the back propagation head forwards + // NOTE: there are no size-injecting ops + backPropagationHead = p; + } + + depth = 0; + } + p.depth = depth++; + } // Adapt the source spliterator, evaluating each stateful op // in the pipeline up to and including this pipeline stage - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; + // Flags for each pipeline stage are adjusted accordingly + boolean backPropagate = false; + int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; + for (@SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; u != e; u = p, p = p.nextStage) { - if (p.opIsStateful()) { - spliterator = p.opEvaluateParallelLazy(u, spliterator); + if (hasTerminalFlags && + (backPropagate || (backPropagate = (u == backPropagationHead)))) { + // Back-propagate flags from the terminal operation + u.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, u.combinedFlags); } + + int thisOpFlags = p.sourceOrOpFlags; + if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { + // Clear the short circuit flag for next pipeline stage + // This stage encapsulates short-circuiting, the next + // stage may not have any short-circuit operations, and + // if so spliterator.forEachRemaining should be used + // for traversal + thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; + } + + spliterator = p.opEvaluateParallelLazy(u, spliterator); + + // Inject or clear SIZED on the source pipeline stage + // based on the stage's spliterator + thisOpFlags = spliterator.hasCharacteristics(Spliterator.SIZED) + ? (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED + : (thisOpFlags & ~StreamOpFlag.IS_SIZED) | StreamOpFlag.NOT_SIZED; + } + p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); } } - else if (terminalFlags != 0) { + + if (hasTerminalFlags) { + // Apply flags from the terminal operation to last pipeline stage combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); } diff --git a/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java b/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java index e3cf2979f45..6928409760b 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java +++ b/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java @@ -264,6 +264,11 @@ final class ReduceOps { return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -433,6 +438,11 @@ final class ReduceOps { return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -602,6 +612,11 @@ final class ReduceOps { return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -771,6 +786,11 @@ final class ReduceOps { return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java index 47eb533d8a2..4254b15765f 100644 --- a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java +++ b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java @@ -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 @@ -251,7 +251,7 @@ public class UnorderedTest extends OpTestCase { final int lastLimitIndex = l; return s -> { - if (lastLimitIndex == -1) + if (lastLimitIndex == -1 && fs.size() > 0) s = fi.apply(s); for (int i = 0; i < fs.size(); i++) { s = fs.get(i).apply(s); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java index 0ed5ddc1a17..41f6ecf00b9 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java @@ -24,11 +24,12 @@ /** * @test * @summary Tests counting of streams - * @bug 8031187 8067969 + * @bug 8031187 8067969 8075307 */ package org.openjdk.tests.java.util.stream; +import java.util.HashSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.DoubleStream; import java.util.stream.DoubleStreamTestDataProvider; @@ -59,6 +60,19 @@ public class CountTest extends OpTestCase { terminal(s -> s.filter(e -> true), Stream::count). expectedResult(expectedCount). exercise(); + + // Test with stateful distinct op that is a barrier or lazy + // depending if source is not already distinct and encounter order is + // preserved or not + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(Stream::distinct, Stream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), Stream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) @@ -74,6 +88,16 @@ public class CountTest extends OpTestCase { terminal(s -> s.filter(e -> true), IntStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(IntStream::distinct, IntStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), IntStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) @@ -89,6 +113,16 @@ public class CountTest extends OpTestCase { terminal(s -> s.filter(e -> true), LongStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(LongStream::distinct, LongStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), LongStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) @@ -104,6 +138,16 @@ public class CountTest extends OpTestCase { terminal(s -> s.filter(e -> true), DoubleStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(DoubleStream::distinct, DoubleStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), DoubleStream::count). + expectedResult(expectedCount). + exercise(); } public void testNoEvaluationForSizedStream() { @@ -111,24 +155,36 @@ public class CountTest extends OpTestCase { AtomicInteger ai = new AtomicInteger(); Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } } } diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java index 69432cfedf6..89f762010ee 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -128,7 +128,7 @@ public class DistinctOpTest extends OpTestCase { @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) public void testDistinctDistinct(String name, TestData.OfRef data) { Collection result = withData(data) - .stream(s -> s.distinct().distinct(), new CollectorOps.TestParallelSizedOp<>()) + .stream(s -> s.distinct().distinct()) .exercise(); assertUnique(result); } From 39b55b3d5ab5f1881853090d6d3bcd4f8ad3517d Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Wed, 25 Mar 2015 15:42:41 +0000 Subject: [PATCH 75/79] 8075959: Change parameter names in some IOException subclasses Reviewed-by: rriggs --- .../share/classes/java/io/ObjectStreamException.java | 6 +++--- .../java.base/share/classes/java/net/ProtocolException.java | 6 +++--- .../share/classes/java/net/UnknownHostException.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java b/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java index d87a56fb8c5..94fc560139f 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java @@ -38,10 +38,10 @@ public abstract class ObjectStreamException extends IOException { /** * Create an ObjectStreamException with the specified argument. * - * @param classname the detailed message for the exception + * @param message the detailed message for the exception */ - protected ObjectStreamException(String classname) { - super(classname); + protected ObjectStreamException(String message) { + super(message); } /** diff --git a/jdk/src/java.base/share/classes/java/net/ProtocolException.java b/jdk/src/java.base/share/classes/java/net/ProtocolException.java index 828636e8461..e2bd4111cc1 100644 --- a/jdk/src/java.base/share/classes/java/net/ProtocolException.java +++ b/jdk/src/java.base/share/classes/java/net/ProtocolException.java @@ -42,10 +42,10 @@ class ProtocolException extends IOException { * Constructs a new {@code ProtocolException} with the * specified detail message. * - * @param host the detail message. + * @param message the detail message. */ - public ProtocolException(String host) { - super(host); + public ProtocolException(String message) { + super(message); } /** diff --git a/jdk/src/java.base/share/classes/java/net/UnknownHostException.java b/jdk/src/java.base/share/classes/java/net/UnknownHostException.java index a990f69cecd..9a9fea53fa0 100644 --- a/jdk/src/java.base/share/classes/java/net/UnknownHostException.java +++ b/jdk/src/java.base/share/classes/java/net/UnknownHostException.java @@ -41,10 +41,10 @@ class UnknownHostException extends IOException { * Constructs a new {@code UnknownHostException} with the * specified detail message. * - * @param host the detail message. + * @param message the detail message. */ - public UnknownHostException(String host) { - super(host); + public UnknownHostException(String message) { + super(message); } /** From 8ab93c84ecc491e7b98f10a7fd58406b203f82a6 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 25 Mar 2015 15:36:43 -0700 Subject: [PATCH 76/79] 8073158: zip files with total entry count 0xFFFF need not be ZIP64 files Minor rewrite of crufty zip implementation in parse_manifest.c Reviewed-by: sherman --- .../share/native/libjli/manifest_info.h | 2 + .../share/native/libjli/parse_manifest.c | 249 ++++++++++-------- jdk/test/java/util/zip/EntryCount64k.java | 75 +++++- 3 files changed, 197 insertions(+), 129 deletions(-) diff --git a/jdk/src/java.base/share/native/libjli/manifest_info.h b/jdk/src/java.base/share/native/libjli/manifest_info.h index 5f9773e0bca..1e04058f87e 100644 --- a/jdk/src/java.base/share/native/libjli/manifest_info.h +++ b/jdk/src/java.base/share/native/libjli/manifest_info.h @@ -109,6 +109,8 @@ /* * Macros for getting end of central directory header (END) fields */ +#define ENDNMD(b) SH(b, 4) /* number of this disk */ +#define ENDDSK(b) SH(b, 6) /* disk number of start */ #define ENDSUB(b) SH(b, 8) /* number of entries on this disk */ #define ENDTOT(b) SH(b, 10) /* total number of entries */ #define ENDSIZ(b) LG(b, 12) /* central directory size */ diff --git a/jdk/src/java.base/share/native/libjli/parse_manifest.c b/jdk/src/java.base/share/native/libjli/parse_manifest.c index 9ce82c1a1d6..cc0bc370f2f 100644 --- a/jdk/src/java.base/share/native/libjli/parse_manifest.c +++ b/jdk/src/java.base/share/native/libjli/parse_manifest.c @@ -111,52 +111,127 @@ inflate_file(int fd, zentry *entry, int *size_out) return (NULL); } -static jboolean zip64_present = JNI_FALSE; +/* + * Implementation notes: + * + * This is a zip format reader for seekable files, that tolerates + * leading and trailing garbage, and tolerates having had internal + * offsets adjusted for leading garbage (as with Info-Zip's zip -A). + * + * We find the end header by scanning backwards from the end of the + * file for the end signature. This may fail in the presence of + * trailing garbage or a ZIP file comment that contains binary data. + * Similarly, the ZIP64 end header may need to be located by scanning + * backwards from the end header. It may be misidentified, but this + * is very unlikely to happen in practice without adversarial input. + * + * The zip file format is documented at: + * https://www.pkware.com/documents/casestudies/APPNOTE.TXT + * + * TODO: more informative error messages + */ + +/** Reads count bytes from fd at position pos into given buffer. */ +static jboolean +readAt(int fd, jlong pos, size_t count, void *buf) { + return (pos >= 0 + && JLI_Lseek(fd, pos, SEEK_SET) == pos + && read(fd, buf, count) == (jlong) count); +} + /* - * Checks to see if we have ZIP64 archive, and save - * the check for later use + * Tells whether given header values (obtained from either ZIP64 or + * non-ZIP64 header) appear to be correct, by checking the first LOC + * and CEN headers. + */ +static jboolean +is_valid_end_header(int fd, jlong endpos, + jlong censiz, jlong cenoff, jlong entries) { + Byte cenhdr[CENHDR]; + Byte lochdr[LOCHDR]; + // Expected offset of the first central directory header + jlong censtart = endpos - censiz; + // Expected position within the file that offsets are relative to + jlong base_offset = endpos - (censiz + cenoff); + return censtart >= 0 && cenoff >= 0 && + (censiz == 0 || + // Validate first CEN and LOC header signatures. + // Central directory must come directly before the end header. + (readAt(fd, censtart, CENHDR, cenhdr) + && CENSIG_AT(cenhdr) + && readAt(fd, base_offset + CENOFF(cenhdr), LOCHDR, lochdr) + && LOCSIG_AT(lochdr) + && CENNAM(cenhdr) == LOCNAM(lochdr))); +} + +/* + * Tells whether p appears to be pointing at a valid ZIP64 end header. + * Values censiz, cenoff, and entries are the corresponding values + * from the non-ZIP64 end header. We perform extra checks to avoid + * misidentifying data from the last entry as a ZIP64 end header. + */ +static jboolean +is_zip64_endhdr(int fd, const Byte *p, jlong end64pos, + jlong censiz, jlong cenoff, jlong entries) { + if (ZIP64_ENDSIG_AT(p)) { + jlong censiz64 = ZIP64_ENDSIZ(p); + jlong cenoff64 = ZIP64_ENDOFF(p); + jlong entries64 = ZIP64_ENDTOT(p); + return (censiz64 == censiz || censiz == ZIP64_MAGICVAL) + && (cenoff64 == cenoff || cenoff == ZIP64_MAGICVAL) + && (entries64 == entries || entries == ZIP64_MAGICCOUNT) + && is_valid_end_header(fd, end64pos, censiz64, cenoff64, entries64); + } + return JNI_FALSE; +} + +/* + * Given a non-ZIP64 end header located at endhdr and endpos, look for + * an adjacent ZIP64 end header, finding the base offset and censtart + * from the ZIP64 header if available, else from the non-ZIP64 header. + * @return 0 if successful, -1 in case of failure */ static int -haveZIP64(Byte *p) { - jlong cenlen, cenoff, centot; - cenlen = ENDSIZ(p); - cenoff = ENDOFF(p); - centot = ENDTOT(p); - zip64_present = (cenlen == ZIP64_MAGICVAL || - cenoff == ZIP64_MAGICVAL || - centot == ZIP64_MAGICCOUNT); - return zip64_present; -} - -static jlong -find_end64(int fd, Byte *ep, jlong pos) +find_positions64(int fd, const Byte * const endhdr, const jlong endpos, + jlong* base_offset, jlong* censtart) { + jlong censiz = ENDSIZ(endhdr); + jlong cenoff = ENDOFF(endhdr); + jlong entries = ENDTOT(endhdr); jlong end64pos; - jlong bytes; - if ((end64pos = JLI_Lseek(fd, pos - ZIP64_LOCHDR, SEEK_SET)) < (jlong)0) - return -1; - if ((bytes = read(fd, ep, ZIP64_LOCHDR)) < 0) - return -1; - if (ZIP64_LOCSIG_AT(ep)) - return end64pos; - return -1; + Byte buf[ZIP64_ENDHDR + ZIP64_LOCHDR]; + if (censiz + cenoff != endpos + && (end64pos = endpos - sizeof(buf)) >= (jlong)0 + && readAt(fd, end64pos, sizeof(buf), buf) + && ZIP64_LOCSIG_AT(buf + ZIP64_ENDHDR) + && (jlong) ZIP64_LOCDSK(buf + ZIP64_ENDHDR) == ENDDSK(endhdr) + && (is_zip64_endhdr(fd, buf, end64pos, censiz, cenoff, entries) + || // A variable sized "zip64 extensible data sector" ? + ((end64pos = ZIP64_LOCOFF(buf + ZIP64_ENDHDR)) >= (jlong)0 + && readAt(fd, end64pos, ZIP64_ENDHDR, buf) + && is_zip64_endhdr(fd, buf, end64pos, censiz, cenoff, entries))) + ) { + *censtart = end64pos - ZIP64_ENDSIZ(buf); + *base_offset = *censtart - ZIP64_ENDOFF(buf); + } else { + if (!is_valid_end_header(fd, endpos, censiz, cenoff, entries)) + return -1; + *censtart = endpos - censiz; + *base_offset = *censtart - cenoff; + } + return 0; } /* - * A very little used routine to handle the case that zip file has - * a comment at the end. Believe it or not, the only way to find the - * END record is to walk backwards, byte by bloody byte looking for - * the END record signature. + * Finds the base offset and censtart of the zip file. * - * fd: File descriptor of the jar file. - * eb: Pointer to a buffer to receive a copy of the END header. - * - * Returns the offset of the END record in the file on success, - * -1 on failure. + * @param fd file descriptor of the jar file + * @param eb scratch buffer + * @return 0 if successful, -1 in case of failure */ -static jlong -find_end(int fd, Byte *eb) +static int +find_positions(int fd, Byte *eb, jlong* base_offset, jlong* censtart) { jlong len; jlong pos; @@ -177,7 +252,7 @@ find_end(int fd, Byte *eb) if ((bytes = read(fd, eb, ENDHDR)) < 0) return (-1); if (ENDSIG_AT(eb)) { - return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; + return find_positions64(fd, eb, pos, base_offset, censtart); } /* @@ -208,7 +283,7 @@ find_end(int fd, Byte *eb) (void) memcpy(eb, cp, ENDHDR); free(buffer); pos = flen - (endpos - cp); - return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; + return find_positions64(fd, eb, pos, base_offset, censtart); } free(buffer); return (-1); @@ -217,82 +292,6 @@ find_end(int fd, Byte *eb) #define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ) #define MINREAD 1024 -/* - * Computes and positions at the start of the CEN header, ie. the central - * directory, this will also return the offset if there is a zip file comment - * at the end of the archive, for most cases this would be 0. - */ -static jlong -compute_cen(int fd, Byte *bp) -{ - int bytes; - Byte *p; - jlong base_offset; - jlong offset; - char buffer[MINREAD]; - p = (Byte*) buffer; - /* - * Read the END Header, which is the starting point for ZIP files. - * (Clearly designed to make writing a zip file easier than reading - * one. Now isn't that precious...) - */ - if ((base_offset = find_end(fd, bp)) == -1) { - return (-1); - } - p = bp; - /* - * There is a historical, but undocumented, ability to allow for - * additional "stuff" to be prepended to the zip/jar file. It seems - * that this has been used to prepend an actual java launcher - * executable to the jar on Windows. Although this is just another - * form of statically linking a small piece of the JVM to the - * application, we choose to continue to support it. Note that no - * guarantees have been made (or should be made) to the customer that - * this will continue to work. - * - * Therefore, calculate the base offset of the zip file (within the - * expanded file) by assuming that the central directory is followed - * immediately by the end record. - */ - if (zip64_present) { - if ((offset = ZIP64_LOCOFF(p)) < (jlong)0) { - return -1; - } - if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong) 0) { - return (-1); - } - if ((bytes = read(fd, buffer, MINREAD)) < 0) { - return (-1); - } - if (!ZIP64_ENDSIG_AT(buffer)) { - return -1; - } - if ((offset = ZIP64_ENDOFF(buffer)) < (jlong)0) { - return -1; - } - if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong)0) { - return (-1); - } - p = (Byte*) buffer; - base_offset = base_offset - ZIP64_ENDSIZ(p) - ZIP64_ENDOFF(p) - ZIP64_ENDHDR; - } else { - base_offset = base_offset - ENDSIZ(p) - ENDOFF(p); - /* - * The END Header indicates the start of the Central Directory - * Headers. Remember that the desired Central Directory Header (CEN) - * will almost always be the second one and the first one is a small - * directory entry ("META-INF/"). Keep the code optimized for - * that case. - * - * Seek to the beginning of the Central Directory. - */ - if (JLI_Lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (jlong) 0) { - return (-1); - } - } - return base_offset; -} - /* * Locate the manifest file with the zip/jar file. * @@ -327,7 +326,23 @@ find_file(int fd, zentry *entry, const char *file_name) int res; int entry_size; int read_size; + + /* + * The (imaginary) position within the file relative to which + * offsets within the zip file refer. This is usually the + * location of the first local header (the start of the zip data) + * (which in turn is usually 0), but if the zip file has content + * prepended, then it will be either 0 or the length of the + * prepended content, depending on whether or not internal offsets + * have been adjusted (via e.g. zip -A). May be negative if + * content is prepended, zip -A is run, then the prefix is + * detached! + */ jlong base_offset; + + /** The position within the file of the start of the central directory. */ + jlong censtart; + Byte *p; Byte *bp; Byte *buffer; @@ -338,9 +353,11 @@ find_file(int fd, zentry *entry, const char *file_name) } bp = buffer; - base_offset = compute_cen(fd, bp); - if (base_offset == -1) { - free(buffer); + + if (find_positions(fd, bp, &base_offset, &censtart) == -1) { + return -1; + } + if (JLI_Lseek(fd, censtart, SEEK_SET) < (jlong) 0) { return -1; } diff --git a/jdk/test/java/util/zip/EntryCount64k.java b/jdk/test/java/util/zip/EntryCount64k.java index c815efdded6..b391ea99a7c 100644 --- a/jdk/test/java/util/zip/EntryCount64k.java +++ b/jdk/test/java/util/zip/EntryCount64k.java @@ -24,31 +24,64 @@ /** * @test * @summary Test java.util.zip behavior with ~64k entries + * @library /lib/testlibrary * @run main/othervm EntryCount64k * @run main/othervm -Djdk.util.zip.inhibitZip64=true EntryCount64k * @run main/othervm -Djdk.util.zip.inhibitZip64=false EntryCount64k */ import java.io.*; +import java.nio.file.Paths; import java.util.*; import java.util.zip.*; -public class EntryCount64k { +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; - public static void main(String[] args) throws Exception { - for (int i = (1 << 16) - 2; i < (1 << 16) + 2; i++) +public class EntryCount64k { + public static class Main { + public static void main(String[] args) { + System.out.println("Main"); + } + } + + static final String mainClass = "EntryCount64k$Main"; + + public static void main(String[] args) throws Throwable { + for (int i = (1 << 16) - 3; i < (1 << 16) + 2; i++) test(i); } - static void test(int entryCount) throws Exception { + static void test(int entryCount) throws Throwable { File zipFile = new File("EntryCount64k-tmp.zip"); zipFile.delete(); - try (ZipOutputStream zos = - new ZipOutputStream( - new BufferedOutputStream( - new FileOutputStream(zipFile)))) { - for (int i = 0; i < entryCount; i++) { + try (FileOutputStream fos = new FileOutputStream(zipFile); + BufferedOutputStream bos = new BufferedOutputStream(fos); + ZipOutputStream zos = new ZipOutputStream(bos)) { + + // Add 2 special entries, manifest and main class, + // to allow the zip file to be used with "java -jar" + ZipEntry man = new ZipEntry("META-INF/MANIFEST.MF"); + zos.putNextEntry(man); + zos.write("Manifest-Version: 1.0\n".getBytes("US-ASCII")); + zos.write(("Main-Class: " + mainClass + "\n").getBytes("US-ASCII")); + zos.closeEntry(); + + String mainName = mainClass + ".class"; + ZipEntry mainEntry = new ZipEntry(mainName); + String testClasses = System.getProperty("test.classes"); + File mainFile = new File(testClasses, mainName); + zos.putNextEntry(mainEntry); + try (FileInputStream fis = new FileInputStream(mainFile)) { + byte[] buf = new byte[4096]; + int n; + while ((n = fis.read(buf)) > 0) + zos.write(buf, 0, n); + } + zos.closeEntry(); + + for (int i = 2; i < entryCount; i++) { ZipEntry e = new ZipEntry(Integer.toString(i)); zos.putNextEntry(e); zos.closeEntry(); @@ -86,16 +119,19 @@ public class EntryCount64k { return false; } - static void checkCanRead(File zipFile, int entryCount) throws Exception { + static void checkCanRead(File zipFile, int entryCount) throws Throwable { // Check ZipInputStream API try (ZipInputStream zis = new ZipInputStream( new BufferedInputStream( new FileInputStream(zipFile)))) { - for (int i = 0; i < entryCount; i++) { + // skip over first two entries + for (int i = 0; i < 2; i++) + zis.getNextEntry(); + for (int i = 2; i < entryCount; i++) { ZipEntry e = zis.getNextEntry(); if (Integer.parseInt(e.getName()) != i) - throw new AssertionError(); + throw new AssertionError(e.getName()); } if (zis.getNextEntry() != null) throw new AssertionError(); @@ -104,7 +140,10 @@ public class EntryCount64k { // Check ZipFile API try (ZipFile zf = new ZipFile(zipFile)) { Enumeration en = zf.entries(); - for (int i = 0; i < entryCount; i++) { + // skip over first two entries + for (int i = 0; i < 2; i++) + en.nextElement(); + for (int i = 2; i < entryCount; i++) { ZipEntry e = en.nextElement(); if (Integer.parseInt(e.getName()) != i) throw new AssertionError(); @@ -115,5 +154,15 @@ public class EntryCount64k { || (zf.getEntry(Integer.toString(entryCount)) != null)) throw new AssertionError(); } + + // Check java -jar + String javaHome = System.getProperty("java.home"); + String java = Paths.get(javaHome, "bin", "java").toString(); + String[] cmd = { java, "-jar", zipFile.getName() }; + ProcessBuilder pb = new ProcessBuilder(cmd); + OutputAnalyzer a = ProcessTools.executeProcess(pb); + a.shouldHaveExitValue(0); + a.stdoutShouldMatch("\\AMain\n\\Z"); + a.stderrShouldMatch("\\A\\Z"); } } From 33c1f7d181fc65116ff0a0b655ce9f8f3a3835dd Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Tue, 10 Mar 2015 14:23:03 -0700 Subject: [PATCH 77/79] 8075774: Small readability and performance improvements for zipfs Reviewed-by: sherman, alanb --- .../share/classes/jdk/nio/zipfs/ZipConstants.java | 13 +++++++++++-- .../share/classes/jdk/nio/zipfs/ZipFileSystem.java | 12 ++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java index 0a080a261ed..211e5a393f8 100644 --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java @@ -184,10 +184,19 @@ class ZipConstants { return (LG(b, n)) | (LG(b, n + 4) << 32); } - static final long GETSIG(byte[] b) { - return LG(b, 0); + static long getSig(byte[] b, int n) { return LG(b, n); } + + private static boolean pkSigAt(byte[] b, int n, int b1, int b2) { + return b[n] == 'P' & b[n + 1] == 'K' & b[n + 2] == b1 & b[n + 3] == b2; } + static boolean cenSigAt(byte[] b, int n) { return pkSigAt(b, n, 1, 2); } + static boolean locSigAt(byte[] b, int n) { return pkSigAt(b, n, 3, 4); } + static boolean endSigAt(byte[] b, int n) { return pkSigAt(b, n, 5, 6); } + static boolean extSigAt(byte[] b, int n) { return pkSigAt(b, n, 7, 8); } + static boolean end64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 6); } + static boolean locator64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 7); } + // local file (LOC) header fields static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract diff --git a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index aa584943d3f..d5cd4cf1125 100644 --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1060,7 +1060,7 @@ class ZipFileSystem extends FileSystem { int pos = 0; int limit = cen.length - ENDHDR; while (pos < limit) { - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); int method = CENHOW(cen, pos); int nlen = CENNAM(cen, pos); @@ -1894,7 +1894,7 @@ class ZipFileSystem extends FileSystem { throws IOException { byte[] cen = zipfs.cen; - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); versionMade = CENVEM(cen, pos); version = CENVER(cen, pos); @@ -2057,9 +2057,9 @@ class ZipFileSystem extends FileSystem { assert (buf.length >= LOCHDR); if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); //startPos = pos; version = LOCVER(buf); flag = LOCFLG(buf); @@ -2289,9 +2289,9 @@ class ZipFileSystem extends FileSystem { if (zipfs.readFullyAt(buf, 0, buf.length , locoff) != buf.length) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); int locElen = LOCEXT(buf); if (locElen < 9) // EXTT is at lease 9 bytes From 47ed235f367aa188457612c38c7ec56a19f3ea62 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 4 Mar 2015 17:35:40 -0800 Subject: [PATCH 78/79] 8074578: Document memory visibility effects of Unsafe compareAndSwap methods Reviewed-by: psandoz, jrose, dholmes --- jdk/src/java.base/share/classes/sun/misc/Unsafe.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java index ef25c517f03..5ca9cb3059d 100644 --- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java @@ -631,6 +631,10 @@ public final class Unsafe { /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapObject(Object o, long offset, @@ -640,6 +644,10 @@ public final class Unsafe { /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapInt(Object o, long offset, @@ -649,6 +657,10 @@ public final class Unsafe { /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapLong(Object o, long offset, From f0fb07515ac90f03d152a795b9d29ba23a0fbf9d Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 26 Mar 2015 16:17:33 +0100 Subject: [PATCH 79/79] 8076060: Improve make bootstrap process Reviewed-by: erikj --- jdk/make/Makefile | 49 ----------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 jdk/make/Makefile diff --git a/jdk/make/Makefile b/jdk/make/Makefile deleted file mode 100644 index ce3a3333405..00000000000 --- a/jdk/make/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (c) 2012, 2013, 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. -# - -# Locate this Makefile -ifeq ($(filter /%, $(lastword $(MAKEFILE_LIST))), ) - makefile_path := $(CURDIR)/$(lastword $(MAKEFILE_LIST)) -else - makefile_path := $(lastword $(MAKEFILE_LIST)) -endif -repo_dir := $(patsubst %/make/Makefile, %, $(makefile_path)) - -# What is the name of this subsystem (langtools, corba, etc)? -subsystem_name := $(notdir $(repo_dir)) - -# Try to locate top-level makefile -top_level_makefile := $(repo_dir)/../Makefile -ifneq ($(wildcard $(top_level_makefile)), ) - $(info Will run $(subsystem_name) target on top-level Makefile) - $(info WARNING: This is a non-recommended way of building!) - $(info ===================================================) -else - $(info Cannot locate top-level Makefile. Is this repo not checked out as part of a complete forest?) - $(error Build from top-level Makefile instead) -endif - -all: - @$(MAKE) -f $(top_level_makefile) $(subsystem_name)