This commit is contained in:
Phil Race 2019-05-07 11:52:28 -07:00
commit 1b03f22dff
272 changed files with 7154 additions and 1904 deletions

View File

@ -387,7 +387,7 @@ else # $(HAS_SPEC)=true
fi
# Re-run configure with the same arguments (and possibly some additional),
# must be done after patching.
( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \
( cd $(CONFIGURE_START_DIR) && PATH="$(ORIGINAL_PATH)" \
$(BASH) $(topdir)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
endef

View File

@ -219,7 +219,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
-Wunused-function -Wundef -Wunused-value -Woverloaded-virtual"
WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
DISABLED_WARNINGS="unused-parameter unused"
DISABLED_WARNINGS="unknown-warning-option unused-parameter unused"
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
# missing-method-return-type triggers in JavaNativeFoundation framework

View File

@ -76,7 +76,8 @@ $(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc) \
undef, \
DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang) \
undef switch format-nonliteral tautological-undefined-compare, \
undef switch format-nonliteral tautological-undefined-compare \
self-assign-overloaded, \
DISABLED_WARNINGS_solstudio := $(DISABLED_WARNINGS_solstudio) \
identexpected, \
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft) \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019, 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
@ -346,17 +346,26 @@ public class CLDRConverter {
if (sb.indexOf("root") == -1) {
sb.append("root");
}
Bundle b = new Bundle(id, sb.toString(), null, null);
// Insert the bundle for root at the top so that it will get
// processed first.
if ("root".equals(id)) {
retList.add(0, b);
} else {
retList.add(b);
}
retList.add(new Bundle(id, sb.toString(), null, null));
}
}
}
// Sort the bundles based on id. This will make sure all the parent bundles are
// processed first, e.g., for en_GB bundle, en_001, and "root" comes before
// en_GB. In order for "root" to come at the beginning, "root" is replaced with
// empty string on comparison.
retList.sort((o1, o2) -> {
String id1 = o1.getID();
String id2 = o2.getID();
if(id1.equals("root")) {
id1 = "";
}
if(id2.equals("root")) {
id2 = "";
}
return id1.compareTo(id2);
});
return retList;
}

View File

@ -46,12 +46,14 @@ void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) {
// Apply storeval barrier to newval.
ShenandoahBarrierSet::assembler()->storeval_barrier(masm->masm(), newval, tmp1);
#ifdef _LP64
if (UseCompressedOops) {
__ encode_heap_oop(cmpval);
__ mov(rscratch1, newval);
__ encode_heap_oop(rscratch1);
newval = rscratch1;
}
#endif
ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), result, Address(addr, 0), cmpval, newval, false, tmp1, tmp2);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. 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
@ -65,9 +65,7 @@
#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory");
// 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_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
inline void OrderAccess::loadload() { inlasm_lwsync(); }
inline void OrderAccess::storestore() { inlasm_lwsync(); }

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. 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
@ -302,7 +302,6 @@ JVM_handle_linux_signal(int sig,
address stub = NULL;
address pc = NULL;
//%note os_trap_1
if (info != NULL && uc != NULL && thread != NULL) {
pc = (address) os::Linux::ucontext_get_pc(uc);
@ -311,17 +310,17 @@ JVM_handle_linux_signal(int sig,
// si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
// comment below). Use get_stack_bang_address instead of si_addr.
// If SIGSEGV is caused due to a branch to an invalid address an
// "Instruction Storage" interruption is generated and 'pc' (NIP) already
// "Instruction Storage Interrupt" is generated and 'pc' (NIP) already
// contains the invalid address. Otherwise, the SIGSEGV is caused due to
// load/store instruction trying to load/store from/to an invalid address
// and causing a "Data Storage" interruption, so we inspect the intruction
// and causing a "Data Storage Interrupt", so we inspect the intruction
// in order to extract the faulty data addresss.
address addr;
if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) {
// Instruction interruption
// Instruction Storage Interrupt (ISI)
addr = pc;
} else {
// Data interruption (0x0300): extract faulty data address
// Data Storage Interrupt (DSI), i.e. 0x0300: extract faulty data address
addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
}

View File

@ -1988,8 +1988,9 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
}
if (cha_monomorphic_target != NULL) {
assert(!target->can_be_statically_bound() || target == cha_monomorphic_target, "");
assert(!cha_monomorphic_target->is_abstract(), "");
if (!target->is_final_method() && !target->is_private()) {
if (!cha_monomorphic_target->can_be_statically_bound(actual_recv)) {
// If we inlined because CHA revealed only a single target method,
// then we are dependent on that target method not getting overridden
// by dynamic class loading. Be sure to test the "static" receiver

View File

@ -764,6 +764,14 @@ ciMethod* ciMethod::find_monomorphic_target(ciInstanceKlass* caller,
return CURRENT_THREAD_ENV->get_method(target());
}
// ------------------------------------------------------------------
// ciMethod::can_be_statically_bound
//
// Tries to determine whether a method can be statically bound in some context.
bool ciMethod::can_be_statically_bound(ciInstanceKlass* context) const {
return (holder() == context) && can_be_statically_bound();
}
// ------------------------------------------------------------------
// ciMethod::resolve_invoke
//

View File

@ -352,6 +352,8 @@ class ciMethod : public ciMetadata {
bool is_unboxing_method() const;
bool is_object_initializer() const;
bool can_be_statically_bound(ciInstanceKlass* context) const;
// Replay data methods
void dump_name_as_ascii(outputStream* st);
void dump_replay_data(outputStream* st);

View File

@ -108,6 +108,7 @@ void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) {
void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) {
check_ctxk(ctxk);
check_unique_method(ctxk, uniqm);
assert_common_2(unique_concrete_method, ctxk, uniqm);
}
@ -180,6 +181,7 @@ void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Kla
void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) {
check_ctxk(ctxk);
check_unique_method(ctxk, uniqm);
assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
}

View File

@ -27,6 +27,7 @@
#include "ci/ciCallSite.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodHandle.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/compressedStream.hpp"
@ -341,6 +342,9 @@ class Dependencies: public ResourceObj {
check_ctxk(ctxk);
assert(!is_concrete_klass(ctxk->as_instance_klass()), "must be abstract");
}
static void check_unique_method(ciKlass* ctxk, ciMethod* m) {
assert(!m->can_be_statically_bound(ctxk->as_instance_klass()), "redundant");
}
void assert_common_1(DepType dept, ciBaseObject* x);
void assert_common_2(DepType dept, ciBaseObject* x0, ciBaseObject* x1);
@ -368,6 +372,11 @@ class Dependencies: public ResourceObj {
check_ctxk(ctxk);
assert(ctxk->is_abstract(), "must be abstract");
}
static void check_unique_method(Klass* ctxk, Method* m) {
// Graal can register redundant dependencies
assert(UseJVMCICompiler || !m->can_be_statically_bound(InstanceKlass::cast(ctxk)), "redundant");
}
void assert_common_1(DepType dept, DepValue x);
void assert_common_2(DepType dept, DepValue x0, DepValue x1);

View File

@ -70,7 +70,6 @@
#if INCLUDE_JVMCI
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "runtime/vframe.hpp"
#endif
#ifdef COMPILER2
#include "opto/c2compiler.hpp"
@ -1063,20 +1062,22 @@ void CompileBroker::compile_method_base(const methodHandle& method,
}
#if INCLUDE_JVMCI
if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
if (UseJVMCICompiler && blocking) {
// Don't allow blocking compiles for requests triggered by JVMCI.
if (thread->is_Compiler_thread()) {
blocking = false;
}
// Don't allow blocking compiles if inside a class initializer or while performing class loading
vframeStream vfst((JavaThread*) thread);
for (; !vfst.at_end(); vfst.next()) {
if (vfst.method()->is_static_initializer() ||
(vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
vfst.method()->name() == vmSymbols::loadClass_name())) {
blocking = false;
break;
if (!UseJVMCINativeLibrary) {
// Don't allow blocking compiles if inside a class initializer or while performing class loading
vframeStream vfst((JavaThread*) thread);
for (; !vfst.at_end(); vfst.next()) {
if (vfst.method()->is_static_initializer() ||
(vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
vfst.method()->name() == vmSymbols::loadClass_name())) {
blocking = false;
break;
}
}
}
@ -2063,7 +2064,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
compilable = ciEnv::MethodCompilable_never;
} else {
JVMCICompileState compile_state(task, system_dictionary_modification_counter);
JVMCIEnv env(&compile_state, __FILE__, __LINE__);
JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__);
methodHandle method(thread, target_handle);
env.runtime()->compile_method(&env, jvmci, method, osr_bci);

View File

@ -229,7 +229,6 @@ class CompileBroker: AllStatic {
static JavaThread* make_thread(jobject thread_oop, CompileQueue* queue, AbstractCompiler* comp, TRAPS);
static void init_compiler_sweeper_threads();
static void possibly_add_compiler_threads();
static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded);
static void preload_classes (const methodHandle& method, TRAPS);
@ -285,6 +284,7 @@ public:
return NULL;
}
static bool compilation_is_complete(const methodHandle& method, int osr_bci, int comp_level);
static bool compilation_is_in_queue(const methodHandle& method);
static void print_compile_queues(outputStream* st);
static void print_directives(outputStream* st);

View File

@ -1036,7 +1036,7 @@ void G1CollectedHeap::prepare_heap_for_full_collection() {
void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) {
assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
assert(used() == recalculate_used(), "Should be equal");
assert_used_and_recalculate_used_equal(this);
_verifier->verify_region_sets_optional();
_verifier->verify_before_gc(G1HeapVerifier::G1VerifyFull);
_verifier->check_bitmaps("Full GC Start");
@ -1092,7 +1092,7 @@ void G1CollectedHeap::verify_after_full_collection() {
// the full GC has compacted objects and updated TAMS but not updated
// the prev bitmap.
if (G1VerifyBitmaps) {
GCTraceTime(Debug, gc)("Clear Prev Bitmap for Verification");
GCTraceTime(Debug, gc) tm("Clear Prev Bitmap for Verification");
_cm->clear_prev_bitmap(workers());
}
// This call implicitly verifies that the next bitmap is clear after Full GC.
@ -4539,9 +4539,7 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
_archive_allocator->clear_used();
}
}
assert(used() == recalculate_used(),
"inconsistent used(), value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT,
used(), recalculate_used());
assert_used_and_recalculate_used_equal(this);
}
// Methods for the mutator alloc region

View File

@ -354,6 +354,15 @@ private:
assert(Thread::current()->is_VM_thread(), "current thread is not VM thread"); \
} while (0)
#define assert_used_and_recalculate_used_equal(g1h) \
do { \
size_t cur_used_bytes = g1h->used(); \
size_t recal_used_bytes = g1h->recalculate_used(); \
assert(cur_used_bytes == recal_used_bytes, "Used(" SIZE_FORMAT ") is not" \
" same as recalculated used(" SIZE_FORMAT ").", \
cur_used_bytes, recal_used_bytes); \
} while (0)
const char* young_gc_name() const;
// The young region list.

View File

@ -289,6 +289,6 @@ void G1FullCollector::verify_after_marking() {
// fail. At the end of the GC, the original mark word values
// (including hash values) are restored to the appropriate
// objects.
GCTraceTime(Info, gc, verify)("Verifying During GC (full)");
GCTraceTime(Info, gc, verify) tm("Verifying During GC (full)");
_heap->verify(VerifyOption_G1UseFullMarking);
}

View File

@ -65,7 +65,6 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
_gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):");
_gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
_gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
_gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms):");
_gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms):");
if (G1HotCardCache::default_use_cache()) {
@ -406,7 +405,7 @@ double G1GCPhaseTimes::print_evacuate_collection_set() const {
trace_phase(_gc_par_phases[GCWorkerStart], false);
debug_phase(_gc_par_phases[ExtRootScan]);
for (int i = ExtRootScanSubPhasesStart; i <= ExtRootScanSubPhasesEnd; i++) {
for (int i = ExtRootScanSubPhasesFirst; i <= ExtRootScanSubPhasesLast; i++) {
trace_phase(_gc_par_phases[i]);
}
if (G1HotCardCache::default_use_cache()) {
@ -531,7 +530,6 @@ const char* G1GCPhaseTimes::phase_name(GCParPhases phase) {
"CMRefRoots",
"WaitForStrongCLD",
"WeakCLDRoots",
"SATBFiltering",
"UpdateRS",
"ScanHCC",
"ScanRS",

View File

@ -60,7 +60,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
CMRefRoots,
WaitForStrongCLD,
WeakCLDRoots,
SATBFiltering,
UpdateRS,
ScanHCC,
ScanRS,
@ -82,8 +81,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
GCParPhasesSentinel
};
static const GCParPhases ExtRootScanSubPhasesStart = ThreadRoots;
static const GCParPhases ExtRootScanSubPhasesEnd = SATBFiltering;
static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots;
static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots;
enum GCScanRSWorkItems {
ScanRSScannedCards,

View File

@ -487,10 +487,7 @@ void G1Policy::record_collection_pause_start(double start_time_sec) {
assert(max_survivor_regions() + _g1h->num_used_regions() <= _g1h->max_regions(),
"Maximum survivor regions %u plus used regions %u exceeds max regions %u",
max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions());
assert(_g1h->used() == _g1h->recalculate_used(),
"sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT,
_g1h->used(), _g1h->recalculate_used());
assert_used_and_recalculate_used_equal(_g1h);
phase_times()->record_cur_collection_start_sec(start_time_sec);
_pending_cards = _g1h->pending_card_num();
@ -581,8 +578,8 @@ bool G1Policy::need_to_start_conc_mark(const char* source, size_t alloc_word_siz
void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) {
double end_time_sec = os::elapsedTime();
assert_used_and_recalculate_used_equal(_g1h);
size_t cur_used_bytes = _g1h->used();
assert(cur_used_bytes == _g1h->recalculate_used(), "It should!");
bool this_pause_included_initial_mark = false;
bool this_pause_was_young_only = collector_state()->in_young_only_phase();

View File

@ -122,16 +122,6 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata.");
}
// During conc marking we have to filter the per-thread SATB buffers
// to make sure we remove any oops into the CSet (which will show up
// as implicitly live).
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
if (_process_strong_tasks.try_claim_task(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_or_rebuild_in_progress()) {
G1BarrierSet::satb_mark_queue_set().filter_thread_buffers();
}
}
_process_strong_tasks.all_tasks_completed(n_workers());
}

View File

@ -65,7 +65,6 @@ class G1RootProcessor : public StackObj {
G1RP_PS_CodeCache_oops_do,
AOT_ONLY(G1RP_PS_aot_oops_do COMMA)
JVMCI_ONLY(G1RP_PS_JVMCI_oops_do COMMA)
G1RP_PS_filter_satb_buffers,
G1RP_PS_refProcessor_oops_do,
// Leave this one last.
G1RP_PS_NumElements

View File

@ -189,18 +189,6 @@ void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active)
Threads::threads_do(&closure);
}
void SATBMarkQueueSet::filter_thread_buffers() {
class FilterThreadBufferClosure : public ThreadClosure {
SATBMarkQueueSet* _qset;
public:
FilterThreadBufferClosure(SATBMarkQueueSet* qset) : _qset(qset) {}
virtual void do_thread(Thread* t) {
_qset->satb_queue_for_thread(t).filter();
}
} closure(this);
Threads::threads_do(&closure);
}
bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
BufferNode* nd = get_completed_buffer();
if (nd != NULL) {

View File

@ -125,9 +125,6 @@ public:
size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; }
virtual void filter(SATBMarkQueue* queue) = 0;
// Filter all the currently-active SATB buffers.
void filter_thread_buffers();
// If there exists some completed buffer, pop and process it, and
// return true. Otherwise return false. Processing a buffer
// consists of applying the closure to the active range of the

View File

@ -1333,8 +1333,8 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
}
}
}
if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) {
CallNode* call = ctrl->in(0)->as_CallJava();
if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) {
CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava();
CallProjections projs;
call->extract_projections(&projs, false, false);
@ -1362,7 +1362,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
if (idx < n->outcnt()) {
Node* u = n->raw_out(idx);
Node* c = phase->ctrl_or_self(u);
if (c == ctrl) {
if (phase->is_dominator(call, c) && phase->is_dominator(c, projs.fallthrough_proj)) {
stack.set_index(idx+1);
assert(!u->is_CFG(), "");
stack.push(u, 0);
@ -1404,14 +1404,11 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
}
}
} else {
// assert(n_clone->outcnt() > 0, "");
// assert(n->outcnt() > 0, "");
stack.pop();
clones.pop();
}
} while (stack.size() > 0);
assert(stack.size() == 0 && clones.size() == 0, "");
ctrl = projs.fallthrough_catchproj;
}
}
@ -1950,6 +1947,9 @@ void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, No
head->verify_strip_mined(0);
}
move_heap_stable_test_out_of_loop(iff, phase);
AutoNodeBudget node_budget(phase);
if (loop->policy_unswitching(phase)) {
if (head->is_strip_mined()) {
OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop();

View File

@ -45,10 +45,13 @@ void ShenandoahArguments::initialize() {
FLAG_SET_DEFAULT(ShenandoahGCHeuristics, "passive");
FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false);
FLAG_SET_DEFAULT(ShenandoahLoadRefBarrier, false);
FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false);
FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, false);
FLAG_SET_DEFAULT(ShenandoahCASBarrier, false);
FLAG_SET_DEFAULT(ShenandoahCloneBarrier, false);
FLAG_SET_DEFAULT(ShenandoahVerifyOptoBarriers, false);
#endif
#ifdef _LP64
@ -106,6 +109,7 @@ void ShenandoahArguments::initialize() {
// C2 barrier verification is only reliable when all default barriers are enabled
if (ShenandoahVerifyOptoBarriers &&
(!FLAG_IS_DEFAULT(ShenandoahSATBBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahLoadRefBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahKeepAliveBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahStoreValEnqueueBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahCASBarrier) ||

View File

@ -89,7 +89,6 @@ void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) {
AlwaysTrueClosure always_true;
WeakProcessor::weak_oops_do(&always_true, oops);
JvmtiExport::weak_oops_do(&always_true, oops);
if (ShenandoahStringDedup::is_enabled()) {
ShenandoahStringDedup::oops_do_slow(oops);

View File

@ -35,10 +35,10 @@ class ZGranuleMap {
friend class ZGranuleMapIterator<T>;
private:
T* const _map;
const size_t _size;
T* const _map;
size_t index_for_addr(uintptr_t addr) const;
size_t size() const;
public:
ZGranuleMap();

View File

@ -31,11 +31,12 @@
template <typename T>
inline ZGranuleMap<T>::ZGranuleMap() :
_map(MmapArrayAllocator<T>::allocate(size(), mtGC)) {}
_size(ZAddressOffsetMax >> ZGranuleSizeShift),
_map(MmapArrayAllocator<T>::allocate(_size, mtGC)) {}
template <typename T>
inline ZGranuleMap<T>::~ZGranuleMap() {
MmapArrayAllocator<T>::free(_map, size());
MmapArrayAllocator<T>::free(_map, _size);
}
template <typename T>
@ -43,16 +44,11 @@ inline size_t ZGranuleMap<T>::index_for_addr(uintptr_t addr) const {
assert(!ZAddress::is_null(addr), "Invalid address");
const size_t index = ZAddress::offset(addr) >> ZGranuleSizeShift;
assert(index < size(), "Invalid index");
assert(index < _size, "Invalid index");
return index;
}
template <typename T>
inline size_t ZGranuleMap<T>::size() const {
return ZAddressOffsetMax >> ZGranuleSizeShift;
}
template <typename T>
inline T ZGranuleMap<T>::get(uintptr_t addr) const {
const size_t index = index_for_addr(addr);
@ -83,7 +79,7 @@ inline ZGranuleMapIterator<T>::ZGranuleMapIterator(const ZGranuleMap<T>* map) :
template <typename T>
inline bool ZGranuleMapIterator<T>::next(T* value) {
if (_next < _map->size()) {
if (_next < _map->_size) {
*value = _map->_map[_next++];
return true;
}
@ -94,7 +90,7 @@ inline bool ZGranuleMapIterator<T>::next(T* value) {
template <typename T>
inline bool ZGranuleMapIterator<T>::next(T** value) {
if (_next < _map->size()) {
if (_next < _map->_size) {
*value = _map->_map + _next++;
return true;
}

View File

@ -28,6 +28,7 @@
#include "compiler/disassembler.hpp"
#include "interpreter/bytecodeHistogram.hpp"
#include "interpreter/bytecodeInterpreter.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/interp_masm.hpp"
@ -36,6 +37,8 @@
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/arrayOop.hpp"
#include "oops/constantPool.hpp"
#include "oops/cpCache.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
@ -240,9 +243,36 @@ void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kin
// Return true if the interpreter can prove that the given bytecode has
// not yet been executed (in Java semantics, not in actual operation).
bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) {
Bytecodes::Code code = method()->code_at(bci);
BytecodeStream s(method, bci);
Bytecodes::Code code = s.next();
if (!Bytecodes::must_rewrite(code)) {
if (Bytecodes::is_invoke(code)) {
assert(!Bytecodes::must_rewrite(code), "invokes aren't rewritten");
ConstantPool* cpool = method()->constants();
Bytecode invoke_bc(s.bytecode());
switch (code) {
case Bytecodes::_invokedynamic: {
assert(invoke_bc.has_index_u4(code), "sanity");
int method_index = invoke_bc.get_index_u4(code);
return cpool->invokedynamic_cp_cache_entry_at(method_index)->is_f1_null();
}
case Bytecodes::_invokevirtual: // fall-through
case Bytecodes::_invokeinterface: // fall-through
case Bytecodes::_invokespecial: // fall-through
case Bytecodes::_invokestatic: {
if (cpool->has_preresolution()) {
return false; // might have been reached
}
assert(!invoke_bc.has_index_u4(code), "sanity");
int method_index = invoke_bc.get_index_u2_cpcache(code);
Method* resolved_method = ConstantPool::method_at_if_loaded(cpool, method_index);
return (resolved_method == NULL);
}
default: ShouldNotReachHere();
}
} else if (!Bytecodes::must_rewrite(code)) {
// might have been reached
return false;
}

View File

@ -170,6 +170,10 @@ class BytecodeStream: public BaseBytecodeStream {
// Construction
BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { }
BytecodeStream(const methodHandle& method, int bci) : BaseBytecodeStream(method) {
set_start(bci);
}
// Iteration
Bytecodes::Code next() {
Bytecodes::Code raw_code, code;

File diff suppressed because it is too large Load Diff

View File

@ -160,13 +160,14 @@ class JavaArgumentUnboxer : public SignatureIterator {
};
class JNIHandleMark : public StackObj {
JavaThread* _thread;
public:
JNIHandleMark() { push_jni_handle_block(); }
~JNIHandleMark() { pop_jni_handle_block(); }
JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); }
~JNIHandleMark() { pop_jni_handle_block(_thread); }
private:
static void push_jni_handle_block();
static void pop_jni_handle_block();
static void push_jni_handle_block(JavaThread* thread);
static void pop_jni_handle_block(JavaThread* thread);
};
#endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP

View File

@ -129,11 +129,10 @@ void JVMCIEnv::copy_saved_properties() {
}
}
JNIEnv* JVMCIEnv::attach_shared_library() {
JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) {
if (_shared_library_javavm == NULL) {
MutexLocker locker(JVMCI_lock);
if (_shared_library_javavm == NULL) {
char path[JVM_MAXPATHLEN];
char ebuf[1024];
if (JVMCILibPath != NULL) {
@ -179,85 +178,107 @@ JNIEnv* JVMCIEnv::attach_shared_library() {
}
}
}
JNIEnv* env;
if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) {
guarantee(env != NULL, "missing env");
return env;
}
fatal("Error attaching current thread to JVMCI shared library JNI interface");
return NULL;
}
void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) {
void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
assert(thread != NULL, "npe");
// By default there is only one runtime which is the compiler runtime.
_runtime = JVMCI::compiler_runtime();
_env = NULL;
_pop_frame_on_close = false;
_detach_on_close = false;
if (!UseJVMCINativeLibrary) {
// In HotSpot mode, JNI isn't used at all.
_is_hotspot = true;
_env = NULL;
return;
}
if (parent_env != NULL) {
// If the parent JNI environment is non-null then figure out whether it
// is a HotSpot or shared library JNIEnv and set the state appropriately.
JavaThread* thread = JavaThread::current();
if (thread->jni_environment() == parent_env) {
_is_hotspot = thread->jni_environment() == parent_env;
if (_is_hotspot) {
// Select the Java runtime
_runtime = JVMCI::java_runtime();
_is_hotspot = true;
_env = NULL;
return;
}
_env = parent_env;
return;
}
// Running in JVMCI shared library mode so get a shared library JNIEnv
// Running in JVMCI shared library mode so ensure the shared library
// is loaded and initialized and get a shared library JNIEnv
_is_hotspot = false;
_env = attach_shared_library();
assert(parent_env == NULL || _env == parent_env, "must be");
_env = init_shared_library(thread);
if (parent_env == NULL) {
// There is no parent shared library JNI env so push
// a JNI local frame to release all local handles in
// this JVMCIEnv scope when it's closed.
assert(_throw_to_caller == false, "must be");
JNIAccessMark jni(this);
jint result = _env->PushLocalFrame(32);
if (result != JNI_OK) {
char message[256];
jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
JVMCIRuntime::exit_on_pending_exception(this, message);
if (_env != NULL) {
// Creating the JVMCI shared library VM also attaches the current thread
_detach_on_close = true;
} else {
_shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2);
if (parent_env != NULL) {
// Even though there's a parent JNI env, there's no guarantee
// it was opened by a JVMCIEnv scope and thus may not have
// pushed a local JNI frame. As such, we use a new JNI local
// frame in this scope to ensure local JNI refs are collected
// in a timely manner after leaving this scope.
_env = parent_env;
} else {
ResourceMark rm; // Thread name is resource allocated
JavaVMAttachArgs attach_args;
attach_args.version = JNI_VERSION_1_2;
attach_args.name = thread->name();
attach_args.group = NULL;
if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) {
fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
}
_detach_on_close = true;
}
}
assert(_env != NULL, "missing env");
assert(_throw_to_caller == false, "must be");
JNIAccessMark jni(this);
jint result = _env->PushLocalFrame(32);
if (result != JNI_OK) {
char message[256];
jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
JVMCIRuntime::exit_on_pending_exception(this, message);
}
_pop_frame_on_close = true;
}
JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line):
JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
_throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
init_env_mode_runtime(NULL);
init_env_mode_runtime(thread, NULL);
}
JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
_throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
init_env_mode_runtime(NULL);
init_env_mode_runtime(thread, NULL);
}
JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line):
JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
_throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
init_env_mode_runtime(parent_env);
init_env_mode_runtime(thread, parent_env);
assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
}
void JVMCIEnv::init(bool is_hotspot, const char* file, int line) {
void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
_compile_state = NULL;
_throw_to_caller = false;
_file = file;
_line = line;
if (is_hotspot) {
_env = NULL;
_pop_frame_on_close = false;
_detach_on_close = false;
_is_hotspot = true;
_runtime = JVMCI::java_runtime();
} else {
init_env_mode_runtime(NULL);
init_env_mode_runtime(thread, NULL);
}
}
@ -324,7 +345,7 @@ JVMCIEnv::~JVMCIEnv() {
}
}
} else {
if (!is_hotspot()) {
if (_pop_frame_on_close) {
// Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
JNIAccessMark jni(this);
jni()->PopLocalFrame(NULL);
@ -335,6 +356,10 @@ JVMCIEnv::~JVMCIEnv() {
jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
JVMCIRuntime::exit_on_pending_exception(this, message);
}
if (_detach_on_close) {
get_shared_library_javavm()->DetachCurrentThread();
}
}
}
@ -463,26 +488,38 @@ void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
}
}
void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes) {
if (size_in_bytes == 0) {
void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
if (length == 0) {
return;
}
if (is_hotspot()) {
memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes);
memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
} else {
JNIAccessMark jni(this);
jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest);
jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
}
}
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) {
if (size_in_bytes == 0) {
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
if (length == 0) {
return;
}
if (is_hotspot()) {
memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes);
memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
} else {
JNIAccessMark jni(this);
jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src);
jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
}
}
void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
if (length == 0) {
return;
}
if (is_hotspot()) {
memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
} else {
JNIAccessMark jni(this);
jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
}
}
@ -612,6 +649,8 @@ DO_THROW(NullPointerException)
DO_THROW(IllegalArgumentException)
DO_THROW(InvalidInstalledCodeException)
DO_THROW(UnsatisfiedLinkError)
DO_THROW(UnsupportedOperationException)
DO_THROW(ClassNotFoundException)
#undef DO_THROW
@ -888,7 +927,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci,
return JVMCIObject();
}
jobject file_name = NULL;
if (file_name != NULL) {
if (file_name_sym != NULL) {
file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
if (jni()->ExceptionCheck()) {
return JVMCIObject();
@ -1323,14 +1362,15 @@ Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
return Handle(THREAD, obj);
} else {
assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type");
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
oop result = resolve_handle(object_handle);
if (result == NULL) {
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
}
return Handle(THREAD, result);
} else {
JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
}
}

View File

@ -36,15 +36,6 @@ class JVMCIPrimitiveArray;
class JVMCICompiler;
class JVMCIRuntime;
// Bring the JVMCI compiler thread into the VM state.
#define JVMCI_VM_ENTRY_MARK \
JavaThread* thread = JavaThread::current(); \
ThreadInVMfromNative __tiv(thread); \
ResetNoHandleMark rnhm; \
HandleMarkCleaner __hm(thread); \
Thread* THREAD = thread; \
debug_only(VMNativeEntryWrapper __vew;)
#define JVMCI_EXCEPTION_CONTEXT \
JavaThread* thread=JavaThread::current(); \
Thread* THREAD = thread;
@ -154,24 +145,25 @@ class JVMCIEnv : public ResourceObj {
static void* _shared_library_handle; // result of os::dll_load
static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
// Attaches the current thread to the JavaVM in the shared library,
// initializing the shared library VM first if necessary.
// Returns the JNI interface pointer of the current thread.
// The _shared_library_* fields are initialized by the first
// call to this method.
static JNIEnv* attach_shared_library();
// Initializes the shared library JavaVM if not already initialized.
// Returns the JNI interface pointer for the current thread
// if initialization was performed by this call, NULL if
// initialization was performed by a previous call.
static JNIEnv* init_shared_library(JavaThread* thread);
// Initializes the _env, _mode and _runtime fields.
void init_env_mode_runtime(JNIEnv* parent_env);
void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env);
void init(bool is_hotspot, const char* file, int line);
void init(JavaThread* thread, bool is_hotspot, const char* file, int line);
JNIEnv* _env; // JNI env for calling into shared library
JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
const char* _file; // The file and ...
int _line; // ... line where this JNIEnv was created
JNIEnv* _env; // JNI env for calling into shared library
bool _pop_frame_on_close; // Must pop frame on close?
bool _detach_on_close; // Must detach on close?
JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
const char* _file; // The file and ...
int _line; // ... line where this JNIEnv was created
// Translates an exception on the HotSpot heap to an exception on
// the shared library heap. The translation includes the stack and
@ -185,12 +177,12 @@ public:
// scope closes so that it will be propagated back to Java.
// The JVMCIEnv destructor translates the exception object for the
// Java runtime if necessary.
JVMCIEnv(JNIEnv* env, const char* file, int line);
JVMCIEnv(JavaThread* thread, JNIEnv* env, const char* file, int line);
// Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
// An exception occurring within the scope must not be propagated back to
// the CompileBroker.
JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line);
JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line);
// Opens a JNIEnv scope for a call from within the VM. An exception occurring
// within the scope must not be propagated back to the caller.
@ -198,20 +190,20 @@ public:
// Opens a JNIEnv scope for accessing `for_object`. An exception occurring
// within the scope must not be propagated back to the caller.
JVMCIEnv(JVMCIObject for_object, const char* file, int line) {
JVMCIEnv(JavaThread* thread, JVMCIObject for_object, const char* file, int line) {
// A JNI call to access an object in the shared library heap
// can block or take a long time so do not allow such access
// on the VM thread.
assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
"cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
init(for_object.is_hotspot(), file, line);
init(thread, for_object.is_hotspot(), file, line);
}
// Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
// otherwise for the shared library runtime. An exception occurring
// within the scope must not be propagated back to the caller.
JVMCIEnv(bool is_hotspot, const char* file, int line) {
init(is_hotspot, file, line);
JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) {
init(thread, is_hotspot, file, line);
}
~JVMCIEnv();
@ -247,8 +239,10 @@ public:
long get_long_at(JVMCIPrimitiveArray array, int index);
void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes);
void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes);
void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length);
void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length);
void copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length);
JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
@ -323,6 +317,8 @@ public:
DO_THROW(IllegalArgumentException)
DO_THROW(InvalidInstalledCodeException)
DO_THROW(UnsatisfiedLinkError)
DO_THROW(UnsupportedOperationException)
DO_THROW(ClassNotFoundException)
#undef DO_THROW

View File

@ -32,8 +32,8 @@ class JVMCIEnv;
#define JVMCIENV __jvmci_env__
#define JVMCI_TRAPS JVMCIEnv* JVMCIENV
#define JNI_JVMCIENV(env) \
JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__); \
#define JNI_JVMCIENV(thread, env) \
JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__); \
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
#define THREAD_JVMCIENV(thread) \

View File

@ -356,6 +356,43 @@ extern "C" {
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
}
// Dumps symbols for public <init>() and <init>(String) methods of
// non-abstract Throwable subtypes known by the VM. This is to
// support the use of reflection in jdk.vm.ci.hotspot.TranslatedException.create().
class ThrowableInitDumper : public SymbolClosure {
private:
fileStream* _st;
public:
ThrowableInitDumper(fileStream* st) { _st = st; }
void do_symbol(Symbol** p) {
Thread* THREAD = Thread::current();
Symbol* name = *p;
if (name == NULL) {
return;
}
Klass* k = SystemDictionary::resolve_or_null(name, CHECK_EXIT);
if (k != NULL && k->is_instance_klass()) {
InstanceKlass* iklass = InstanceKlass::cast(k);
if (iklass->is_subclass_of(SystemDictionary::Throwable_klass()) && iklass->is_public() && !iklass->is_abstract()) {
const char* class_name = NULL;
Array<Method*>* methods = iklass->methods();
for (int i = 0; i < methods->length(); i++) {
Method* m = methods->at(i);
if (m->name() == vmSymbols::object_initializer_name() &&
m->is_public() &&
(m->signature() == vmSymbols::void_method_signature() || m->signature() == vmSymbols::string_void_signature())) {
if (class_name == NULL) {
class_name = name->as_C_string();
_st->print_cr("class %s", class_name);
}
_st->print_cr("method %s %s %s", class_name, m->name()->as_C_string(), m->signature()->as_C_string());
}
}
}
}
}
};
#define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
/**
* Initializes the JNI method and field ids used in JNIJVMCI.
@ -441,6 +478,8 @@ void JNIJVMCI::initialize_ids(JNIEnv* env) {
fileStream* st = JVMCIGlobals::get_jni_config_file();
DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
ThrowableInitDumper dumper(st);
vmSymbols::symbols_do(&dumper);
st->flush();
tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);

View File

@ -381,12 +381,18 @@
start_class(InternalError, java_lang_InternalError) \
jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \
end_class \
start_class(ClassNotFoundException, java_lang_ClassNotFoundException) \
jvmci_constructor(ClassNotFoundException, "(Ljava/lang/String;)V") \
end_class \
start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException) \
jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \
end_class \
start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError) \
jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V") \
end_class \
start_class(UnsupportedOperationException, java_lang_UnsupportedOperationException) \
jvmci_constructor(UnsupportedOperationException, "(Ljava/lang/String;)V") \
end_class \
start_class(StackTraceElement, java_lang_StackTraceElement) \
object_field(StackTraceElement, declaringClass, "Ljava/lang/String;") \
object_field(StackTraceElement, methodName, "Ljava/lang/String;") \

View File

@ -655,7 +655,7 @@ JRT_END
// private static JVMCIRuntime JVMCI.initializeRuntime()
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
JNI_JVMCIENV(env);
JNI_JVMCIENV(thread, env);
if (!EnableJVMCI) {
JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
}
@ -877,7 +877,7 @@ JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
fatal("check TLAB allocation code for address space conflicts");
#endif
JNI_JVMCIENV(env);
JNI_JVMCIENV(thread, env);
if (!EnableJVMCI) {
JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
@ -1353,6 +1353,10 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c
compile_state->set_failure(true, "No OSR during boostrap");
return;
}
if (JVMCI::shutdown_called()) {
compile_state->set_failure(false, "Avoiding compilation during shutdown");
return;
}
HandleMark hm;
JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);

View File

@ -83,7 +83,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
}
FLAG_SET_DEFAULT(EnableJVMCI, true);
if (BootstrapJVMCI && UseJVMCINativeLibrary) {
jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary");
jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary\n");
return false;
}
}

View File

@ -53,7 +53,10 @@
"Prints properties used by the JVMCI compiler and exits") \
\
experimental(bool, BootstrapJVMCI, false, \
"Bootstrap JVMCI before running Java main method") \
"Bootstrap JVMCI before running Java main method. This " \
"initializes the compile queue with a small set of methods " \
"and processes the queue until it is empty. Combining this with " \
"-XX:-TieredCompilation makes JVMCI compile more of itself.") \
\
experimental(bool, EagerJVMCI, false, \
"Force eager JVMCI initialization") \

View File

@ -246,6 +246,10 @@
\
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
\
volatile_nonstatic_field(ObjectMonitor, _cxq, ObjectWaiter*) \
volatile_nonstatic_field(ObjectMonitor, _EntryList, ObjectWaiter*) \
volatile_nonstatic_field(ObjectMonitor, _succ, Thread*) \
\
volatile_nonstatic_field(oopDesc, _mark, markOop) \
volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \
\
@ -347,6 +351,7 @@
declare_toplevel_type(JVMCIEnv) \
declare_toplevel_type(LocalVariableTableElement) \
declare_toplevel_type(narrowKlass) \
declare_toplevel_type(ObjectWaiter) \
declare_toplevel_type(Symbol*) \
declare_toplevel_type(vtableEntry) \
\

View File

@ -506,7 +506,7 @@ Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpo
switch (invoke_code) {
case Bytecodes::_invokeinterface:
assert(f1->is_klass(), "");
return klassItable::method_for_itable_index((InstanceKlass*)f1, f2_as_index());
return f2_as_interface_method();
case Bytecodes::_invokestatic:
case Bytecodes::_invokespecial:
assert(!has_appendix(), "");

View File

@ -2965,6 +2965,13 @@ void InstanceKlass::adjust_default_methods(bool* trace_name_printed) {
// On-stack replacement stuff
void InstanceKlass::add_osr_nmethod(nmethod* n) {
#ifndef PRODUCT
if (TieredCompilation) {
nmethod * prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true);
assert(prev == NULL || !prev->is_in_use(),
"redundunt OSR recompilation detected. memory leak in CodeCache!");
}
#endif
// only one compilation can be active
{
// This is a short non-blocking critical region, so the no safepoint check is ok.
@ -3083,7 +3090,9 @@ nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_le
}
osr = osr->osr_link();
}
if (best != NULL && best->comp_level() >= comp_level && match_level == false) {
assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set");
if (best != NULL && best->comp_level() >= comp_level) {
return best;
}
return NULL;

View File

@ -733,8 +733,9 @@ void Klass::print_on(outputStream* st) const {
st->cr();
}
#define BULLET " - "
void Klass::oop_print_on(oop obj, outputStream* st) {
ResourceMark rm;
// print title
st->print_cr("%s ", internal_name());
obj->print_address_on(st);
@ -742,10 +743,13 @@ void Klass::oop_print_on(oop obj, outputStream* st) {
if (WizardMode) {
// print header
obj->mark()->print_on(st);
st->cr();
st->print(BULLET"prototype_header: " INTPTR_FORMAT, p2i(_prototype_header));
st->cr();
}
// print class
st->print(" - klass: ");
st->print(BULLET"klass: ");
obj->klass()->print_value_on(st);
st->cr();
}

View File

@ -25,45 +25,40 @@
#include "precompiled.hpp"
#include "oops/markOop.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/objectMonitor.inline.hpp"
#include "runtime/objectMonitor.hpp"
void markOopDesc::print_on(outputStream* st) const {
if (is_marked()) {
if (is_marked()) { // last bits = 11
st->print(" marked(" INTPTR_FORMAT ")", value());
} else if (has_monitor()) {
} else if (has_monitor()) { // last bits = 10
// have to check has_monitor() before is_locked()
st->print(" monitor(" INTPTR_FORMAT ")=", value());
ObjectMonitor* mon = monitor();
if (mon == NULL) {
st->print("NULL (this should never be seen!)");
} else {
st->print("{contentions=0x%08x,waiters=0x%08x"
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
mon->contentions(), mon->waiters(), mon->recursions(),
p2i(mon->owner()));
mon->print_on(st);
}
} else if (is_locked()) {
st->print(" locked(" INTPTR_FORMAT ")->", value());
if (is_neutral()) {
} else if (is_locked()) { // last bits != 01 => 00
// thin locked
st->print(" locked(" INTPTR_FORMAT ")", value());
} else {
st->print(" mark(");
// Biased bit is 3rd rightmost bit
if (is_neutral()) { // last bits = 001
st->print("is_neutral");
if (has_no_hash()) {
st->print(" no_hash");
} else {
st->print(" hash=" INTPTR_FORMAT, hash());
}
st->print(" age=%d", age());
} else if (has_bias_pattern()) {
} else if (has_bias_pattern()) { // last bits = 101
st->print("is_biased");
JavaThread* jt = biased_locker();
st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
st->print(" biased_locker=" INTPTR_FORMAT " epoch=%d", p2i(jt), bias_epoch());
} else {
st->print("??");
}
} else {
assert(is_unlocked() || has_bias_pattern(), "just checking");
st->print("mark(");
if (has_bias_pattern()) st->print("biased,");
st->print("hash " INTPTR_FORMAT ",", hash());
st->print("age %d)", age());
st->print(" age=%d)", age());
}
}

View File

@ -624,6 +624,10 @@ bool Method::can_be_statically_bound() const {
return can_be_statically_bound(method_holder()->access_flags());
}
bool Method::can_be_statically_bound(InstanceKlass* context) const {
return (method_holder() == context) && can_be_statically_bound();
}
bool Method::is_accessor() const {
return is_getter() || is_setter();
}

View File

@ -619,6 +619,7 @@ class Method : public Metadata {
// true if method needs no dynamic dispatch (final and/or no vtable entry)
bool can_be_statically_bound() const;
bool can_be_statically_bound(InstanceKlass* context) const;
bool can_be_statically_bound(AccessFlags class_access_flags) const;
// returns true if the method has any backward branches.

View File

@ -321,6 +321,35 @@ bool InlineTree::should_not_inline(ciMethod *callee_method,
return false;
}
bool InlineTree::is_not_reached(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile) {
if (!UseInterpreter) {
return false; // -Xcomp
}
if (profile.count() > 0) {
return false; // reachable according to profile
}
if (!callee_method->was_executed_more_than(0)) {
return true; // callee was never executed
}
if (caller_method->is_not_reached(caller_bci)) {
return true; // call site not resolved
}
if (profile.count() == -1) {
return false; // immature profile; optimistically treat as reached
}
assert(profile.count() == 0, "sanity");
// Profile info is scarce.
// Try to guess: check if the call site belongs to a start block.
// Call sites in a start block should be reachable if no exception is thrown earlier.
ciMethodBlocks* caller_blocks = caller_method->get_method_blocks();
bool is_start_block = caller_blocks->block_containing(caller_bci)->start_bci() == 0;
if (is_start_block) {
return false; // treat the call reached as part of start block
}
return true; // give up and treat the call site as not reached
}
//-----------------------------try_to_inline-----------------------------------
// return true if ok
// Relocated from "InliningClosure::try_to_inline"
@ -372,7 +401,7 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method,
// inline constructors even if they are not reached.
} else if (forced_inline()) {
// Inlining was forced by CompilerOracle, ciReplay or annotation
} else if (profile.count() == 0) {
} else if (is_not_reached(callee_method, caller_method, caller_bci, profile)) {
// don't inline unreached call sites
set_msg("call site not reached");
return false;

View File

@ -1152,14 +1152,19 @@ ciMethod* Compile::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass*
cha_monomorphic_target = NULL;
}
}
if (cha_monomorphic_target != NULL) {
// Hardwiring a virtual.
// If we inlined because CHA revealed only a single target method,
// then we are dependent on that target method not getting overridden
// by dynamic class loading. Be sure to test the "static" receiver
// dest_method here, as opposed to the actual receiver, which may
// falsely lead us to believe that the receiver is final or private.
dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
assert(!callee->can_be_statically_bound(), "should have been handled earlier");
assert(!cha_monomorphic_target->is_abstract(), "");
if (!cha_monomorphic_target->can_be_statically_bound(actual_receiver)) {
// If we inlined because CHA revealed only a single target method,
// then we are dependent on that target method not getting overridden
// by dynamic class loading. Be sure to test the "static" receiver
// dest_method here, as opposed to the actual receiver, which may
// falsely lead us to believe that the receiver is final or private.
dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
}
return cha_monomorphic_target;
}

File diff suppressed because it is too large Load Diff

View File

@ -55,27 +55,31 @@
// Return TRUE or FALSE if the loop should be unswitched
// (ie. clone loop with an invariant test that does not exit the loop)
bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
if( !LoopUnswitching ) {
if (!LoopUnswitching) {
return false;
}
if (!_head->is_Loop()) {
return false;
}
// If nodes are depleted, some transform has miscalculated its needs.
assert(!phase->exceeding_node_budget(), "sanity");
// check for vectorized loops, any unswitching was already applied
if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) {
if (_head->is_CountedLoop() && _head->as_CountedLoop()->is_unroll_only()) {
return false;
}
int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
if ((int)(2 * _body.size()) > nodes_left) {
return false; // Too speculative if running low on nodes.
}
LoopNode* head = _head->as_Loop();
if (head->unswitch_count() + 1 > head->unswitch_max()) {
return false;
}
return phase->find_unswitching_candidate(this) != NULL;
if (phase->find_unswitching_candidate(this) == NULL) {
return false;
}
// Too speculative if running low on nodes.
return phase->may_require_nodes(est_loop_clone_sz(3, _body.size()));
}
//------------------------------find_unswitching_candidate-----------------------------

View File

@ -42,17 +42,13 @@
#include "opto/superword.hpp"
//=============================================================================
//------------------------------is_loop_iv-------------------------------------
// Determine if a node is Counted loop induction variable.
// The method is declared in node.hpp.
const Node* Node::is_loop_iv() const {
if (this->is_Phi() && !this->as_Phi()->is_copy() &&
this->as_Phi()->region()->is_CountedLoop() &&
this->as_Phi()->region()->as_CountedLoop()->phi() == this) {
return this;
} else {
return NULL;
}
//--------------------------is_cloop_ind_var-----------------------------------
// Determine if a node is a counted loop induction variable.
// NOTE: The method is declared in "node.hpp".
bool Node::is_cloop_ind_var() const {
return (is_Phi() && !as_Phi()->is_copy() &&
as_Phi()->region()->is_CountedLoop() &&
as_Phi()->region()->as_CountedLoop()->phi() == this);
}
//=============================================================================
@ -2942,14 +2938,15 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
}
if (ReassociateInvariants) {
AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
// Reassociate invariants and prep for split_thru_phi
for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
IdealLoopTree* lpt = iter.current();
bool is_counted = lpt->is_counted();
if (!is_counted || !lpt->is_inner()) continue;
if (!is_counted || !lpt->is_innermost()) continue;
// check for vectorized loops, any reassociation of invariants was already done
if (is_counted && lpt->_head->as_CountedLoop()->do_unroll_only()) continue;
if (is_counted && lpt->_head->as_CountedLoop()->is_unroll_only()) continue;
lpt->reassociate_invariants(this);

View File

@ -264,7 +264,7 @@ public:
bool is_reduction_loop() const { return (_loop_flags&HasReductions) == HasReductions; }
bool was_slp_analyzed () const { return (_loop_flags&WasSlpAnalyzed) == WasSlpAnalyzed; }
bool has_passed_slp () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; }
bool do_unroll_only () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
bool is_unroll_only () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
bool is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; }
bool has_atomic_post_loop () const { return (_loop_flags & HasAtomicPostLoop) == HasAtomicPostLoop; }
void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; }
@ -370,26 +370,49 @@ public:
};
inline CountedLoopEndNode *CountedLoopNode::loopexit_or_null() const {
Node *bc = back_control();
if( bc == NULL ) return NULL;
Node *le = bc->in(0);
if( le->Opcode() != Op_CountedLoopEnd )
return NULL;
return (CountedLoopEndNode*)le;
inline CountedLoopEndNode* CountedLoopNode::loopexit_or_null() const {
Node* bctrl = back_control();
if (bctrl == NULL) return NULL;
Node* lexit = bctrl->in(0);
return (CountedLoopEndNode*)
(lexit->Opcode() == Op_CountedLoopEnd ? lexit : NULL);
}
inline CountedLoopEndNode *CountedLoopNode::loopexit() const {
inline CountedLoopEndNode* CountedLoopNode::loopexit() const {
CountedLoopEndNode* cle = loopexit_or_null();
assert(cle != NULL, "loopexit is NULL");
return cle;
}
inline Node *CountedLoopNode::init_trip() const { return loopexit_or_null() ? loopexit()->init_trip() : NULL; }
inline Node *CountedLoopNode::stride() const { return loopexit_or_null() ? loopexit()->stride() : NULL; }
inline int CountedLoopNode::stride_con() const { return loopexit_or_null() ? loopexit()->stride_con() : 0; }
inline bool CountedLoopNode::stride_is_con() const { return loopexit_or_null() && loopexit()->stride_is_con(); }
inline Node *CountedLoopNode::limit() const { return loopexit_or_null() ? loopexit()->limit() : NULL; }
inline Node *CountedLoopNode::incr() const { return loopexit_or_null() ? loopexit()->incr() : NULL; }
inline Node *CountedLoopNode::phi() const { return loopexit_or_null() ? loopexit()->phi() : NULL; }
inline Node* CountedLoopNode::init_trip() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->init_trip() : NULL;
}
inline Node* CountedLoopNode::stride() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->stride() : NULL;
}
inline int CountedLoopNode::stride_con() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->stride_con() : 0;
}
inline bool CountedLoopNode::stride_is_con() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL && cle->stride_is_con();
}
inline Node* CountedLoopNode::limit() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->limit() : NULL;
}
inline Node* CountedLoopNode::incr() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->incr() : NULL;
}
inline Node* CountedLoopNode::phi() const {
CountedLoopEndNode* cle = loopexit_or_null();
return cle != NULL ? cle->phi() : NULL;
}
//------------------------------LoopLimitNode-----------------------------
// Counted Loop limit node which represents exact final iterator value:
@ -456,9 +479,9 @@ public:
IdealLoopTree *_child; // First child in loop tree
// The head-tail backedge defines the loop.
// If tail is NULL then this loop has multiple backedges as part of the
// same loop. During cleanup I'll peel off the multiple backedges; merge
// them at the loop bottom and flow 1 real backedge into the loop.
// If a loop has multiple backedges, this is addressed during cleanup where
// we peel off the multiple backedges, merging all edges at the bottom and
// ensuring that one proper backedge flow into the loop.
Node *_head; // Head of loop
Node *_tail; // Tail of loop
inline Node *tail(); // Handle lazy update of _tail field
@ -487,7 +510,10 @@ public:
_safepts(NULL),
_required_safept(NULL),
_allow_optimizations(true)
{ }
{
precond(_head != NULL);
precond(_tail != NULL);
}
// Is 'l' a member of 'this'?
bool is_member(const IdealLoopTree *l) const; // Test for nested membership
@ -558,10 +584,10 @@ public:
bool policy_unswitching( PhaseIdealLoop *phase ) const;
// Micro-benchmark spamming. Remove empty loops.
bool policy_do_remove_empty_loop( PhaseIdealLoop *phase );
bool do_remove_empty_loop( PhaseIdealLoop *phase );
// Convert one iteration loop into normal code.
bool policy_do_one_iteration_loop( PhaseIdealLoop *phase );
bool do_one_iteration_loop( PhaseIdealLoop *phase );
// Return TRUE or FALSE if the loop should be peeled or not. Peel if we can
// make some loop-invariant test (usually a null-check) happen before the
@ -615,9 +641,11 @@ public:
// Put loop body on igvn work list
void record_for_igvn();
bool is_loop() { return !_irreducible && _tail && !_tail->is_top(); }
bool is_inner() { return is_loop() && _child == NULL; }
bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); }
bool is_root() { return _parent == NULL; }
// A proper/reducible loop w/o any (occasional) dead back-edge.
bool is_loop() { return !_irreducible && !tail()->is_top(); }
bool is_counted() { return is_loop() && _head->is_CountedLoop(); }
bool is_innermost() { return is_loop() && _child == NULL; }
void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase);
@ -630,13 +658,14 @@ public:
};
// -----------------------------PhaseIdealLoop---------------------------------
// Computes the mapping from Nodes to IdealLoopTrees. Organizes IdealLoopTrees into a
// loop tree. Drives the loop-based transformations on the ideal graph.
// Computes the mapping from Nodes to IdealLoopTrees. Organizes IdealLoopTrees
// into a loop tree. Drives the loop-based transformations on the ideal graph.
class PhaseIdealLoop : public PhaseTransform {
friend class IdealLoopTree;
friend class SuperWord;
friend class CountedLoopReserveKit;
friend class ShenandoahBarrierC2Support;
friend class AutoNodeBudget;
// Pre-computed def-use info
PhaseIterGVN &_igvn;
@ -731,8 +760,7 @@ private:
}
Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag );
// Helper function for directing control inputs away from CFG split
// points.
// Helper function for directing control inputs away from CFG split points.
Node *find_non_split_ctrl( Node *ctrl ) const {
if (ctrl != NULL) {
if (ctrl->is_MultiBranch()) {
@ -883,7 +911,8 @@ private:
_igvn(igvn),
_verify_me(NULL),
_verify_only(true),
_dom_lca_tags(arena()) { // Thread::resource_area
_dom_lca_tags(arena()), // Thread::resource_area
_nodes_required(UINT_MAX) {
build_and_optimize(LoopOptsVerify);
}
@ -899,7 +928,8 @@ private:
_igvn(igvn),
_verify_me(NULL),
_verify_only(false),
_dom_lca_tags(arena()) { // Thread::resource_area
_dom_lca_tags(arena()), // Thread::resource_area
_nodes_required(UINT_MAX) {
build_and_optimize(mode);
}
@ -909,7 +939,8 @@ private:
_igvn(igvn),
_verify_me(verify_me),
_verify_only(false),
_dom_lca_tags(arena()) { // Thread::resource_area
_dom_lca_tags(arena()), // Thread::resource_area
_nodes_required(UINT_MAX) {
build_and_optimize(LoopOptsVerify);
}
@ -1320,8 +1351,54 @@ private:
return C->live_nodes() > threshold;
}
// A simplistic node request tracking mechanism, where
// = UINT_MAX Request not valid or made final.
// < UINT_MAX Nodes currently requested (estimate).
uint _nodes_required;
bool exceeding_node_budget(uint required = 0) {
assert(C->live_nodes() < C->max_node_limit(), "sanity");
uint available = C->max_node_limit() - C->live_nodes();
return available < required + _nodes_required;
}
uint require_nodes(uint require) {
precond(require > 0);
_nodes_required += MAX2(100u, require); // Keep requests at minimum 100.
return _nodes_required;
}
bool may_require_nodes(uint require) {
return !exceeding_node_budget(require) && require_nodes(require) > 0;
}
void require_nodes_begin() {
assert(_nodes_required == UINT_MAX, "Bad state (begin).");
_nodes_required = 0;
}
// Final check that the requested nodes did not exceed the limit and that
// the request was reasonably correct with respect to the number of new
// nodes introduced by any transform since the last 'begin'.
void require_nodes_final_check(uint live_at_begin) {
uint required = _nodes_required;
require_nodes_final();
uint delta = C->live_nodes() - live_at_begin;
assert(delta <= 2 * required, "Bad node estimate (actual: %d, request: %d)",
delta, required);
}
void require_nodes_final() {
assert(_nodes_required < UINT_MAX, "Bad state (final).");
assert(!exceeding_node_budget(), "Too many NODES required!");
_nodes_required = UINT_MAX;
}
bool _created_loop_node;
public:
uint nodes_required() const { return _nodes_required; }
void set_created_loop_node() { _created_loop_node = true; }
bool created_loop_node() { return _created_loop_node; }
void register_new_node( Node *n, Node *blk );
@ -1347,6 +1424,62 @@ public:
void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const;
};
class AutoNodeBudget : public StackObj
{
public:
enum budget_check_t { BUDGET_CHECK, NO_BUDGET_CHECK };
AutoNodeBudget(PhaseIdealLoop* phase, budget_check_t chk = BUDGET_CHECK)
: _phase(phase),
_check_at_final(chk == BUDGET_CHECK),
_nodes_at_begin(0)
{
precond(_phase != NULL);
_nodes_at_begin = _phase->C->live_nodes();
_phase->require_nodes_begin();
}
~AutoNodeBudget() {
if (_check_at_final) {
#ifndef PRODUCT
if (TraceLoopOpts) {
uint request = _phase->nodes_required();
if (request > 0) {
uint delta = _phase->C->live_nodes() - _nodes_at_begin;
if (request < delta) {
tty->print_cr("Exceeding node budget: %d < %d", request, delta);
}
}
}
#endif
_phase->require_nodes_final_check(_nodes_at_begin);
} else {
_phase->require_nodes_final();
}
}
private:
PhaseIdealLoop* _phase;
bool _check_at_final;
uint _nodes_at_begin;
};
// The Estimated Loop Clone Size: CloneFactor * (BodySize + BC) + CC, where BC
// and CC are totally ad-hoc/magic "body" and "clone" constants, respectively,
// used to ensure that node usage estimates made are on the safe side, for the
// most part.
static inline uint est_loop_clone_sz(uint fact, uint size) {
uint const bc = 31;
uint const cc = 41;
uint estimate = fact * (size + bc) + cc;
return (estimate - cc) / fact == size + bc ? estimate : UINT_MAX;
}
// This kit may be used for making of a reserved copy of a loop before this loop
// goes under non-reversible changes.
//
@ -1410,14 +1543,11 @@ class CountedLoopReserveKit {
};// class CountedLoopReserveKit
inline Node* IdealLoopTree::tail() {
// Handle lazy update of _tail field
Node *n = _tail;
//while( !n->in(0) ) // Skip dead CFG nodes
//n = n->in(1);
if (n->in(0) == NULL)
n = _phase->get_ctrl(n);
_tail = n;
return n;
// Handle lazy update of _tail field.
if (_tail->in(0) == NULL) {
_tail = _phase->get_ctrl(_tail);
}
return _tail;
}

View File

@ -2662,7 +2662,7 @@ int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, No
assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
get_loop(use_c)->_body.push(n_clone);
_igvn.register_new_node_with_optimizer(n_clone);
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx);
}
@ -2700,7 +2700,7 @@ void PhaseIdealLoop::clone_for_special_use_inside_loop( IdealLoopTree *loop, Nod
set_ctrl(n_clone, get_ctrl(n));
sink_list.push(n_clone);
not_peel <<= n_clone->_idx; // add n_clone to not_peel set.
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx);
}
@ -3046,7 +3046,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
opc == Op_CatchProj ||
opc == Op_Jump ||
opc == Op_JumpProj) {
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
}
@ -3102,7 +3102,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
return false;
}
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TraceLoopOpts) {
tty->print("PartialPeel ");
loop->dump_head();
@ -3131,6 +3131,10 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
Node_List worklist(area);
Node_List sink_list(area);
if (!may_require_nodes(est_loop_clone_sz(2, loop->_body.size()))) {
return false;
}
// Set of cfg nodes to peel are those that are executable from
// the head through last_peel.
assert(worklist.size() == 0, "should be empty");
@ -3179,7 +3183,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
if (use->is_Phi()) old_phi_cnt++;
}
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("\npeeled list");
}
@ -3190,7 +3194,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
uint cloned_for_outside_use = 0;
for (i = 0; i < peel_list.size();) {
Node* n = peel_list.at(i);
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) n->dump();
#endif
bool incr = true;
@ -3212,7 +3216,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
not_peel <<= n->_idx; // add n to not_peel set.
peel_list.remove(i);
incr = false;
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("sink to not_peeled region: %d newbb: %d",
n->_idx, get_ctrl(n)->_idx);
@ -3231,7 +3235,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
}
if (new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta) {
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("\nToo many new phis: %d old %d new cmpi: %c",
new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F');
@ -3389,7 +3393,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
C->set_major_progress();
loop->record_for_igvn();
#if !defined(PRODUCT)
#ifndef PRODUCT
if (TracePartialPeeling) {
tty->print_cr("\nafter partial peel one iteration");
Node_List wl(area);
@ -3429,10 +3433,10 @@ void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) {
Node *exit = cle->proj_out(false);
Node *phi = cl->phi();
// Check for the special case of folks using the pre-incremented
// trip-counter on the fall-out path (forces the pre-incremented
// and post-incremented trip counter to be live at the same time).
// Fix this by adjusting to use the post-increment trip counter.
// Check for the special case when using the pre-incremented trip-counter on
// the fall-out path (forces the pre-incremented and post-incremented trip
// counter to be live at the same time). Fix this by adjusting to use the
// post-increment trip counter.
bool progress = true;
while (progress) {

View File

@ -1047,11 +1047,11 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
// Try harder before giving up. Unify base pointers with casts (e.g., raw/non-raw pointers).
intptr_t st_off = 0;
Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_off);
if (ld_base == NULL) return NULL;
if (st_base == NULL) return NULL;
if (ld_base->uncast() != st_base->uncast()) return NULL;
if (ld_off != st_off) return NULL;
if (ld_off == Type::OffsetBot) return NULL;
if (ld_base == NULL) return NULL;
if (st_base == NULL) return NULL;
if (!ld_base->eqv_uncast(st_base, /*keep_deps=*/true)) return NULL;
if (ld_off != st_off) return NULL;
if (ld_off == Type::OffsetBot) return NULL;
// Same base, same offset.
// Possible improvement for arrays: check index value instead of absolute offset.
@ -1062,6 +1062,7 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
// (Actually, we haven't yet proven the Q's are the same.)
// In other words, we are loading from a casted version of
// the same pointer-and-offset that we stored to.
// Casted version may carry a dependency and it is respected.
// Thus, we are able to replace L by V.
}
// Now prove that we have a LoadQ matched to a StoreQ, for some Q.

View File

@ -891,13 +891,15 @@ int Node::disconnect_inputs(Node *n, Compile* C) {
//-----------------------------uncast---------------------------------------
// %%% Temporary, until we sort out CheckCastPP vs. CastPP.
// Strip away casting. (It is depth-limited.)
Node* Node::uncast() const {
// Optionally, keep casts with dependencies.
Node* Node::uncast(bool keep_deps) const {
// Should be inline:
//return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
if (is_ConstraintCast())
return uncast_helper(this);
else
if (is_ConstraintCast()) {
return uncast_helper(this, keep_deps);
} else {
return (Node*) this;
}
}
// Find out of current node that matches opcode.
@ -929,7 +931,7 @@ bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
//---------------------------uncast_helper-------------------------------------
Node* Node::uncast_helper(const Node* p) {
Node* Node::uncast_helper(const Node* p, bool keep_deps) {
#ifdef ASSERT
uint depth_count = 0;
const Node* orig_p = p;
@ -947,6 +949,9 @@ Node* Node::uncast_helper(const Node* p) {
if (p == NULL || p->req() != 2) {
break;
} else if (p->is_ConstraintCast()) {
if (keep_deps && p->as_ConstraintCast()->carry_dependency()) {
break; // stop at casts with dependencies
}
p = p->in(1);
} else {
break;

View File

@ -456,10 +456,10 @@ protected:
void setup_is_top();
// Strip away casting. (It is depth-limited.)
Node* uncast() const;
Node* uncast(bool keep_deps = false) const;
// Return whether two Nodes are equivalent, after stripping casting.
bool eqv_uncast(const Node* n) const {
return (this->uncast() == n->uncast());
bool eqv_uncast(const Node* n, bool keep_deps = false) const {
return (this->uncast(keep_deps) == n->uncast(keep_deps));
}
// Find out of current node that matches opcode.
@ -470,7 +470,7 @@ protected:
bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
private:
static Node* uncast_helper(const Node* n);
static Node* uncast_helper(const Node* n, bool keep_deps);
// Add an output edge to the end of the list
void add_out( Node *n ) {
@ -1007,9 +1007,9 @@ public:
// value, if it appears (by local graph inspection) to be computed by a simple conditional.
bool is_iteratively_computed();
// Determine if a node is Counted loop induction variable.
// The method is defined in loopnode.cpp.
const Node* is_loop_iv() const;
// Determine if a node is a counted loop induction variable.
// NOTE: The method is defined in "loopnode.cpp".
bool is_cloop_ind_var() const;
// Return a node with opcode "opc" and same inputs as "this" if one can
// be found; Otherwise return NULL;

View File

@ -88,6 +88,10 @@ protected:
ciMethod* caller_method,
JVMState* jvms,
WarmCallInfo* wci_result);
bool is_not_reached(ciMethod* callee_method,
ciMethod* caller_method,
int caller_bci,
ciCallProfile& profile);
void print_inlining(ciMethod* callee_method, int caller_bci,
ciMethod* caller_method, bool success) const;

View File

@ -114,31 +114,37 @@ const Type* SubNode::Value(PhaseGVN* phase) const {
}
//=============================================================================
//------------------------------Helper function--------------------------------
static bool ok_to_convert(Node* inc, Node* iv) {
// Do not collapse (x+c0)-y if "+" is a loop increment, because the
// "-" is loop invariant and collapsing extends the live-range of "x"
// to overlap with the "+", forcing another register to be used in
// the loop.
// This test will be clearer with '&&' (apply DeMorgan's rule)
// but I like the early cutouts that happen here.
const PhiNode *phi;
if( ( !inc->in(1)->is_Phi() ||
!(phi=inc->in(1)->as_Phi()) ||
phi->is_copy() ||
!phi->region()->is_CountedLoop() ||
inc != phi->region()->as_CountedLoop()->incr() )
&&
// Do not collapse (x+c0)-iv if "iv" is a loop induction variable,
// because "x" maybe invariant.
( !iv->is_loop_iv() )
) {
return true;
} else {
return false;
}
static bool is_cloop_increment(Node* inc) {
precond(inc->Opcode() == Op_AddI || inc->Opcode() == Op_AddL);
if (!inc->in(1)->is_Phi()) {
return false;
}
const PhiNode* phi = inc->in(1)->as_Phi();
if (phi->is_copy() || !phi->region()->is_CountedLoop()) {
return false;
}
return inc == phi->region()->as_CountedLoop()->incr();
}
// Given the expression '(x + C) - v', or
// 'v - (x + C)', we examine nodes '+' and 'v':
//
// 1. Do not convert if '+' is a counted-loop increment, because the '-' is
// loop invariant and converting extends the live-range of 'x' to overlap
// with the '+', forcing another register to be used in the loop.
//
// 2. Do not convert if 'v' is a counted-loop induction variable, because
// 'x' might be invariant.
//
static bool ok_to_convert(Node* inc, Node* var) {
return !(is_cloop_increment(inc) || var->is_cloop_ind_var());
}
//------------------------------Ideal------------------------------------------
Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
Node *in1 = in(1);

View File

@ -145,7 +145,7 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
// Skip any loops already optimized by slp
if (cl->is_vectorized_loop()) return;
if (cl->do_unroll_only()) return;
if (cl->is_unroll_only()) return;
if (cl->is_main_loop()) {
// Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit))))

View File

@ -254,7 +254,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
return _tag_map;
}
JvmtiTagMap* acquire_tag_map() {
JvmtiTagMap* tag_map_acquire() {
return OrderAccess::load_acquire(&_tag_map);
}

View File

@ -514,7 +514,7 @@ void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
// returns the tag map for the given environments. If the tag map
// doesn't exist then it is created.
JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->acquire_tag_map();
JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map_acquire();
if (tag_map == NULL) {
MutexLocker mu(JvmtiThreadState_lock);
tag_map = ((JvmtiEnvBase*)env)->tag_map();
@ -3318,7 +3318,7 @@ void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
if (JvmtiEnv::environments_might_exist()) {
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
JvmtiTagMap* tag_map = env->acquire_tag_map();
JvmtiTagMap* tag_map = env->tag_map_acquire();
if (tag_map != NULL && !tag_map->is_empty()) {
tag_map->do_weak_oops(is_alive, f);
}

View File

@ -1080,6 +1080,24 @@ WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring
return result;
WB_END
WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION(env);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
MethodData* mdo = mh->method_data();
if (mdo == NULL) {
Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
mdo = mh->method_data();
}
mdo->init();
InvocationCounter* icnt = mdo->invocation_counter();
InvocationCounter* bcnt = mdo->backedge_counter();
// set i-counter according to TieredThresholdPolicy::is_method_profiled
icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold);
bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold);
WB_END
WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION(env);
@ -2209,6 +2227,8 @@ static JNINativeMethod methods[] = {
CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
{CC"enqueueInitializerForCompilation0",
CC"(Ljava/lang/Class;I)Z", (void*)&WB_EnqueueInitializerForCompilation},
{CC"markMethodProfiled",
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled},
{CC"clearMethodState0",
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
{CC"lockCompilation", CC"()V", (void*)&WB_LockCompilation},

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, 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
@ -499,6 +499,7 @@ protected:
JavaThread* _requesting_thread;
BiasedLocking::Condition _status_code;
traceid _biased_locker_id;
uint64_t _safepoint_id;
public:
VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
@ -506,14 +507,16 @@ public:
, _objs(NULL)
, _requesting_thread(requesting_thread)
, _status_code(BiasedLocking::NOT_BIASED)
, _biased_locker_id(0) {}
, _biased_locker_id(0)
, _safepoint_id(0) {}
VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
: _obj(NULL)
, _objs(objs)
, _requesting_thread(requesting_thread)
, _status_code(BiasedLocking::NOT_BIASED)
, _biased_locker_id(0) {}
, _biased_locker_id(0)
, _safepoint_id(0) {}
virtual VMOp_Type type() const { return VMOp_RevokeBias; }
@ -545,6 +548,7 @@ public:
if (biased_locker != NULL) {
_biased_locker_id = JFR_THREAD_ID(biased_locker);
}
_safepoint_id = SafepointSynchronize::safepoint_counter();
clean_up_cached_monitor_info();
return;
} else {
@ -560,6 +564,10 @@ public:
traceid biased_locker() const {
return _biased_locker_id;
}
uint64_t safepoint_id() const {
return _safepoint_id;
}
};
@ -581,16 +589,14 @@ public:
virtual void doit() {
_status_code = bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
_safepoint_id = SafepointSynchronize::safepoint_counter();
clean_up_cached_monitor_info();
}
};
template <typename E>
static void set_safepoint_id(E* event) {
assert(event != NULL, "invariant");
// Subtract 1 to match the id of events committed inside the safepoint
event->set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
}
bool is_bulk_rebias() const {
return _bulk_rebias;
}
};
static void post_self_revocation_event(EventBiasedLockSelfRevocation* event, Klass* k) {
assert(event != NULL, "invariant");
@ -600,24 +606,25 @@ static void post_self_revocation_event(EventBiasedLockSelfRevocation* event, Kla
event->commit();
}
static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* revoke) {
static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* op) {
assert(event != NULL, "invariant");
assert(k != NULL, "invariant");
assert(revoke != NULL, "invariant");
assert(op != NULL, "invariant");
assert(event->should_commit(), "invariant");
event->set_lockClass(k);
set_safepoint_id(event);
event->set_previousOwner(revoke->biased_locker());
event->set_safepointId(op->safepoint_id());
event->set_previousOwner(op->biased_locker());
event->commit();
}
static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, bool disabled_bias) {
static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, VM_BulkRevokeBias* op) {
assert(event != NULL, "invariant");
assert(k != NULL, "invariant");
assert(op != NULL, "invariant");
assert(event->should_commit(), "invariant");
event->set_revokedClass(k);
event->set_disableBiasing(disabled_bias);
set_safepoint_id(event);
event->set_disableBiasing(!op->is_bulk_rebias());
event->set_safepointId(op->safepoint_id());
event->commit();
}
@ -729,7 +736,7 @@ BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attem
attempt_rebias);
VMThread::execute(&bulk_revoke);
if (event.should_commit()) {
post_class_revocation_event(&event, obj->klass(), heuristics != HR_BULK_REBIAS);
post_class_revocation_event(&event, obj->klass(), &bulk_revoke);
}
return bulk_revoke.status_code();
}

View File

@ -674,8 +674,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
int top_frame_expression_stack_adjustment = 0;
methodHandle mh(thread, iframe->interpreter_frame_method());
OopMapCache::compute_one_oop_map(mh, iframe->interpreter_frame_bci(), &mask);
BytecodeStream str(mh);
str.set_start(iframe->interpreter_frame_bci());
BytecodeStream str(mh, iframe->interpreter_frame_bci());
int max_bci = mh->code_size();
// Get to the next bytecode if possible
assert(str.bci() < max_bci, "bci in interpreter frame out of bounds");

View File

@ -526,11 +526,31 @@ void vm_exit(int code) {
vm_direct_exit(code);
}
// We'd like to add an entry to the XML log to show that the VM is
// terminating, but we can't safely do that here. The logic to make
// XML termination logging safe is tied to the termination of the
// VMThread, and it doesn't terminate on this exit path. See 8222534.
if (VMThread::vm_thread() != NULL) {
if (thread->is_Java_thread()) {
// We must be "in_vm" for the code below to work correctly.
// Historically there must have been some exit path for which
// that was not the case and so we set it explicitly - even
// though we no longer know what that path may be.
((JavaThread*)thread)->set_thread_state(_thread_in_vm);
}
// Fire off a VM_Exit operation to bring VM to a safepoint and exit
VM_Exit op(code);
if (thread->is_Java_thread())
((JavaThread*)thread)->set_thread_state(_thread_in_vm);
// 4945125 The vm thread comes to a safepoint during exit.
// GC vm_operations can get caught at the safepoint, and the
// heap is unparseable if they are caught. Grab the Heap_lock
// to prevent this. The GC vm_operations will not be able to
// queue until after we release it, but we never do that as we
// are terminating the VM process.
MutexLocker ml(Heap_lock);
VMThread::execute(&op);
// should never reach here; but in case something wrong with VM Thread.
vm_direct_exit(code);

View File

@ -1926,3 +1926,11 @@ void ObjectMonitor::Initialize() {
DEBUG_ONLY(InitDone = true;)
}
void ObjectMonitor::print_on(outputStream* st) const {
// The minimal things to print for markOop printing, more can be added for debugging and logging.
st->print("{contentions=0x%08x,waiters=0x%08x"
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
contentions(), waiters(), recursions(),
p2i(owner()));
}

View File

@ -139,6 +139,7 @@ class ObjectMonitor {
friend class ObjectSynchronizer;
friend class ObjectWaiter;
friend class VMStructs;
JVMCI_ONLY(friend class JVMCIVMStructs;)
volatile markOop _header; // displaced object header word - mark
void* volatile _object; // backward object pointer - strong root
@ -291,6 +292,9 @@ class ObjectMonitor {
void notify(TRAPS);
void notifyAll(TRAPS);
void print() const { print_on(tty); }
void print_on(outputStream* st) const;
// Use the following at your own risk
intptr_t complete_exit(TRAPS);
void reenter(intptr_t recursions, TRAPS);

View File

@ -1575,18 +1575,15 @@ bool jvmci_counters_include(JavaThread* thread) {
return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
}
void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
if (JVMCICounterSize > 0) {
JavaThreadIteratorWithHandle jtiwh;
int len = jvmci_env->get_length(array);
for (int i = 0; i < len; i++) {
jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
}
for (; JavaThread *tp = jtiwh.next(); ) {
if (jvmci_counters_include(tp)) {
for (int i = 0; i < len; i++) {
jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
}
void JavaThread::collect_counters(jlong* array, int length) {
assert(length == JVMCICounterSize, "wrong value");
for (int i = 0; i < length; i++) {
array[i] = _jvmci_old_thread_counters[i];
}
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
if (jvmci_counters_include(tp)) {
for (int i = 0; i < length; i++) {
array[i] += tp->_jvmci_counters[i];
}
}
}

View File

@ -1152,7 +1152,7 @@ class JavaThread: public Thread {
public:
static jlong* _jvmci_old_thread_counters;
static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
static void collect_counters(jlong* array, int length);
private:
#endif // INCLUDE_JVMCI

View File

@ -353,6 +353,16 @@ CompileTask* TieredThresholdPolicy::select_task(CompileQueue* compile_queue) {
TieredStopAtLevel > CompLevel_full_profile &&
max_method != NULL && is_method_profiled(max_method)) {
max_task->set_comp_level(CompLevel_limited_profile);
if (CompileBroker::compilation_is_complete(max_method, max_task->osr_bci(), CompLevel_limited_profile)) {
if (PrintTieredEvents) {
print_event(REMOVE_FROM_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
}
compile_queue->remove_and_mark_stale(max_task);
max_method->clear_queued_for_compilation();
return NULL;
}
if (PrintTieredEvents) {
print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
}

View File

@ -30,6 +30,7 @@
#include "gc/shared/isGCActiveMark.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "logging/logConfiguration.hpp"
#include "memory/heapInspection.hpp"
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
@ -437,14 +438,14 @@ int VM_Exit::wait_for_threads_in_native_to_block() {
if (thr->is_Compiler_thread()) {
#if INCLUDE_JVMCI
CompilerThread* ct = (CompilerThread*) thr;
if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) {
if (ct->compiler() == NULL || !ct->compiler()->is_jvmci()) {
num_active_compiler_thread++;
} else {
// When using a compiler in a JVMCI shared library, it's possible
// for one compiler thread to grab a lock in the shared library,
// enter HotSpot and go to sleep on the shutdown safepoint. Another
// JVMCI shared library compiler thread can then attempt to grab the
// lock and thus never make progress.
// A JVMCI compiler thread never accesses VM data structures
// while in _thread_in_native state so there's no need to wait
// for it and potentially add a 300 millisecond delay to VM
// shutdown.
num_active--;
}
#else
num_active_compiler_thread++;
@ -469,6 +470,16 @@ int VM_Exit::wait_for_threads_in_native_to_block() {
}
void VM_Exit::doit() {
if (VerifyBeforeExit) {
HandleMark hm(VMThread::vm_thread());
// Among other things, this ensures that Eden top is correct.
Universe::heap()->prepare_for_verify();
// Silent verification so as not to pollute normal output,
// unless we really asked for it.
Universe::verify();
}
CompileBroker::set_should_block();
// Wait for a short period for threads in native to block. Any thread
@ -480,10 +491,17 @@ void VM_Exit::doit() {
set_vm_exited();
// We'd like to call IdealGraphPrinter::clean_up() to finalize the
// XML logging, but we can't safely do that here. The logic to make
// XML termination logging safe is tied to the termination of the
// VMThread, and it doesn't terminate on this exit path. See 8222534.
// cleanup globals resources before exiting. exit_globals() currently
// cleans up outputStream resources and PerfMemory resources.
exit_globals();
LogConfiguration::finalize();
// Check for exit hook
exit_hook_t exit_hook = Arguments::exit_hook();
if (exit_hook != NULL) {

View File

@ -63,6 +63,9 @@ do { \
// For backward compatibility.
#define assert(p, ...) vmassert(p, __VA_ARGS__)
#define precond(p) assert(p, "precond")
#define postcond(p) assert(p, "postcond")
#ifndef ASSERT
#define vmassert_status(p, status, msg)
#else

View File

@ -75,7 +75,7 @@ import static java.util.function.Predicate.not;
* System.out.println("abc");
* String cde = "cde";
* System.out.println("abc" + cde);
* String c = "abc".substring(2,3);
* String c = "abc".substring(2, 3);
* String d = cde.substring(1, 2);
* </pre></blockquote>
* <p>
@ -2160,27 +2160,48 @@ public final class String
* @since 1.5
*/
public String replace(CharSequence target, CharSequence replacement) {
String tgtStr = target.toString();
String trgtStr = target.toString();
String replStr = replacement.toString();
int j = indexOf(tgtStr);
if (j < 0) {
return this;
}
int tgtLen = tgtStr.length();
int tgtLen1 = Math.max(tgtLen, 1);
int thisLen = length();
int trgtLen = trgtStr.length();
int replLen = replStr.length();
int newLenHint = thisLen - tgtLen + replStr.length();
if (newLenHint < 0) {
throw new OutOfMemoryError();
if (trgtLen > 0) {
if (trgtLen == 1 && replLen == 1) {
return replace(trgtStr.charAt(0), replStr.charAt(0));
}
boolean thisIsLatin1 = this.isLatin1();
boolean trgtIsLatin1 = trgtStr.isLatin1();
boolean replIsLatin1 = replStr.isLatin1();
String ret = (thisIsLatin1 && trgtIsLatin1 && replIsLatin1)
? StringLatin1.replace(value, thisLen,
trgtStr.value, trgtLen,
replStr.value, replLen)
: StringUTF16.replace(value, thisLen, thisIsLatin1,
trgtStr.value, trgtLen, trgtIsLatin1,
replStr.value, replLen, replIsLatin1);
if (ret != null) {
return ret;
}
return this;
} else { // trgtLen == 0
int resultLen;
try {
resultLen = Math.addExact(thisLen, Math.multiplyExact(
Math.addExact(thisLen, 1), replLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
}
StringBuilder sb = new StringBuilder(resultLen);
sb.append(replStr);
for (int i = 0; i < thisLen; ++i) {
sb.append(charAt(i)).append(replStr);
}
return sb.toString();
}
StringBuilder sb = new StringBuilder(newLenHint);
int i = 0;
do {
sb.append(this, i, j).append(replStr);
i = j + tgtLen;
} while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
return sb.append(this, i, thisLen).toString();
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019, 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,6 +42,14 @@ import static java.lang.String.checkOffset;
final class StringLatin1 {
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public static char charAt(byte[] value, int index) {
if (index < 0 || index >= value.length) {
throw new StringIndexOutOfBoundsException(index);
@ -304,7 +312,7 @@ final class StringLatin1 {
}
if (i < len) {
if (canEncode(newChar)) {
byte buf[] = new byte[len];
byte[] buf = StringConcatHelper.newArray(len);
for (int j = 0; j < i; j++) { // TBD arraycopy?
buf[j] = value[j];
}
@ -330,6 +338,64 @@ final class StringLatin1 {
return null; // for string to return this;
}
public static String replace(byte[] value, int valLen, byte[] targ,
int targLen, byte[] repl, int replLen)
{
assert targLen > 0;
int i, j, p = 0;
if (valLen == 0 || (i = indexOf(value, valLen, targ, targLen, 0)) < 0) {
return null; // for string to return this;
}
// find and store indices of substrings to replace
int[] pos = new int[16];
pos[0] = i;
i += targLen;
while ((j = indexOf(value, valLen, targ, targLen, i)) > 0) {
if (++p == pos.length) {
int cap = p + (p >> 1);
// overflow-conscious code
if (cap - MAX_ARRAY_SIZE > 0) {
if (p == MAX_ARRAY_SIZE) {
throw new OutOfMemoryError();
}
cap = MAX_ARRAY_SIZE;
}
pos = Arrays.copyOf(pos, cap);
}
pos[p] = j;
i = j + targLen;
}
int resultLen;
try {
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
}
if (resultLen == 0) {
return "";
}
byte[] result = StringConcatHelper.newArray(resultLen);
int posFrom = 0, posTo = 0;
for (int q = 0; q < p; ++q) {
int nextPos = pos[q];
while (posFrom < nextPos) {
result[posTo++] = value[posFrom++];
}
posFrom += targLen;
for (int k = 0; k < replLen; ++k) {
result[posTo++] = repl[k];
}
}
while (posFrom < valLen) {
result[posTo++] = value[posFrom++];
}
return new String(result, LATIN1);
}
// case insensitive
public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) {

View File

@ -574,7 +574,7 @@ final class StringUTF16 {
}
}
if (i < len) {
byte buf[] = new byte[value.length];
byte[] buf = new byte[value.length];
for (int j = 0; j < i; j++) {
putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
}
@ -582,21 +582,145 @@ final class StringUTF16 {
char c = getChar(value, i);
putChar(buf, i, c == oldChar ? newChar : c);
i++;
}
// Check if we should try to compress to latin1
if (String.COMPACT_STRINGS &&
!StringLatin1.canEncode(oldChar) &&
StringLatin1.canEncode(newChar)) {
byte[] val = compress(buf, 0, len);
if (val != null) {
return new String(val, LATIN1);
}
}
return new String(buf, UTF16);
}
// Check if we should try to compress to latin1
if (String.COMPACT_STRINGS &&
!StringLatin1.canEncode(oldChar) &&
StringLatin1.canEncode(newChar)) {
byte[] val = compress(buf, 0, len);
if (val != null) {
return new String(val, LATIN1);
}
}
return new String(buf, UTF16);
}
return null;
}
public static String replace(byte[] value, int valLen, boolean valLat1,
byte[] targ, int targLen, boolean targLat1,
byte[] repl, int replLen, boolean replLat1)
{
assert targLen > 0;
assert !valLat1 || !targLat1 || !replLat1;
// Possible combinations of the arguments/result encodings:
// +---+--------+--------+--------+-----------------------+
// | # | VALUE | TARGET | REPL | RESULT |
// +===+========+========+========+=======================+
// | 1 | Latin1 | Latin1 | UTF16 | null or UTF16 |
// +---+--------+--------+--------+-----------------------+
// | 2 | Latin1 | UTF16 | Latin1 | null |
// +---+--------+--------+--------+-----------------------+
// | 3 | Latin1 | UTF16 | UTF16 | null |
// +---+--------+--------+--------+-----------------------+
// | 4 | UTF16 | Latin1 | Latin1 | null or UTF16 |
// +---+--------+--------+--------+-----------------------+
// | 5 | UTF16 | Latin1 | UTF16 | null or UTF16 |
// +---+--------+--------+--------+-----------------------+
// | 6 | UTF16 | UTF16 | Latin1 | null, Latin1 or UTF16 |
// +---+--------+--------+--------+-----------------------+
// | 7 | UTF16 | UTF16 | UTF16 | null or UTF16 |
// +---+--------+--------+--------+-----------------------+
if (String.COMPACT_STRINGS && valLat1 && !targLat1) {
// combinations 2 or 3
return null; // for string to return this;
}
int i = (String.COMPACT_STRINGS && valLat1)
? StringLatin1.indexOf(value, targ) :
(String.COMPACT_STRINGS && targLat1)
? indexOfLatin1(value, targ)
: indexOf(value, targ);
if (i < 0) {
return null; // for string to return this;
}
// find and store indices of substrings to replace
int j, p = 0;
int[] pos = new int[16];
pos[0] = i;
i += targLen;
while ((j = ((String.COMPACT_STRINGS && valLat1)
? StringLatin1.indexOf(value, valLen, targ, targLen, i) :
(String.COMPACT_STRINGS && targLat1)
? indexOfLatin1(value, valLen, targ, targLen, i)
: indexOf(value, valLen, targ, targLen, i))) > 0)
{
if (++p == pos.length) {
int cap = p + (p >> 1);
// overflow-conscious code
if (cap - MAX_ARRAY_SIZE > 0) {
if (p == MAX_ARRAY_SIZE) {
throw new OutOfMemoryError();
}
cap = MAX_ARRAY_SIZE;
}
pos = Arrays.copyOf(pos, cap);
}
pos[p] = j;
i = j + targLen;
}
int resultLen;
try {
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
}
if (resultLen == 0) {
return "";
}
byte[] result = newBytesFor(resultLen);
int posFrom = 0, posTo = 0;
for (int q = 0; q < p; ++q) {
int nextPos = pos[q];
if (String.COMPACT_STRINGS && valLat1) {
while (posFrom < nextPos) {
char c = (char)(value[posFrom++] & 0xff);
putChar(result, posTo++, c);
}
} else {
while (posFrom < nextPos) {
putChar(result, posTo++, getChar(value, posFrom++));
}
}
posFrom += targLen;
if (String.COMPACT_STRINGS && replLat1) {
for (int k = 0; k < replLen; ++k) {
char c = (char)(repl[k] & 0xff);
putChar(result, posTo++, c);
}
} else {
for (int k = 0; k < replLen; ++k) {
putChar(result, posTo++, getChar(repl, k));
}
}
}
if (String.COMPACT_STRINGS && valLat1) {
while (posFrom < valLen) {
char c = (char)(value[posFrom++] & 0xff);
putChar(result, posTo++, c);
}
} else {
while (posFrom < valLen) {
putChar(result, posTo++, getChar(value, posFrom++));
}
}
if (String.COMPACT_STRINGS && replLat1 && !targLat1) {
// combination 6
byte[] lat1Result = compress(result, 0, resultLen);
if (lat1Result != null) {
return new String(lat1Result, LATIN1);
}
}
return new String(result, UTF16);
}
public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) {
int last = toffset + len;
@ -1430,6 +1554,15 @@ final class StringUTF16 {
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// Used by trusted callers. Assumes all necessary bounds checks have
// been done by the caller.

View File

@ -213,7 +213,7 @@ public interface ClassDesc
* @param moreNestedNames the unqualified name(s) of the remaining levels of
* nested class
* @return a {@linkplain ClassDesc} describing the nested class
* @throws NullPointerException if any argument is {@code null}
* @throws NullPointerException if any argument or its contents is {@code null}
* @throws IllegalStateException if this {@linkplain ClassDesc} does not
* describe a class or interface type
* @throws IllegalArgumentException if the nested class name is invalid
@ -221,6 +221,11 @@ public interface ClassDesc
default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
if (!isClassOrInterface())
throw new IllegalStateException("Outer class is not a class or interface type");
validateMemberName(firstNestedName, false);
requireNonNull(moreNestedNames);
for (String addNestedNames : moreNestedNames) {
validateMemberName(addNestedNames, false);
}
return moreNestedNames.length == 0
? nested(firstNestedName)
: nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", "")));

View File

@ -32,6 +32,7 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.channels.ServerSocketChannel;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import java.util.Set;
import java.util.Collections;
@ -81,6 +82,7 @@ class ServerSocket implements java.io.Closeable {
* @since 12
*/
protected ServerSocket(SocketImpl impl) {
Objects.requireNonNull(impl);
this.impl = impl;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2019, 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
@ -1403,8 +1403,9 @@ public final class URL implements java.io.Serializable {
URLStreamHandlerFactory fac;
boolean checkedWithFactory = false;
boolean overrideableProtocol = isOverrideable(protocol);
if (isOverrideable(protocol) && jdk.internal.misc.VM.isBooted()) {
if (overrideableProtocol && jdk.internal.misc.VM.isBooted()) {
// Use the factory (if any). Volatile read makes
// URLStreamHandlerFactory appear fully initialized to current thread.
fac = factory;
@ -1440,7 +1441,8 @@ public final class URL implements java.io.Serializable {
// Check with factory if another thread set a
// factory since our last check
if (!checkedWithFactory && (fac = factory) != null) {
if (overrideableProtocol && !checkedWithFactory &&
(fac = factory) != null) {
handler2 = fac.createURLStreamHandler(protocol);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2019, 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,10 +252,8 @@ public final class FileSystems {
* Suppose there is a provider identified by the scheme {@code "memory"}
* installed:
* <pre>
* Map&lt;String,String&gt; env = new HashMap&lt;&gt;();
* env.put("capacity", "16G");
* env.put("blockSize", "4k");
* FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
* FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"),
* Map.of("capacity", "16G", "blockSize", "4k"));
* </pre>
*
* @param uri
@ -365,14 +363,13 @@ public final class FileSystems {
* systems where the contents of one or more files is treated as a file
* system.
*
* <p> This method iterates over the {@link FileSystemProvider#installedProviders()
* installed} providers. It invokes, in turn, each provider's {@link
* FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method
* with an empty map. If a provider returns a file system then the iteration
* terminates and the file system is returned. If none of the installed
* providers return a {@code FileSystem} then an attempt is made to locate
* the provider using the given class loader. If a provider returns a file
* system then the lookup terminates and the file system is returned.
* <p> This method first attempts to locate an installed provider in exactly
* the same manner as the {@link #newFileSystem(Path, Map, ClassLoader)
* newFileSystem(Path, Map, ClassLoader)} method with an empty map. If none
* of the installed providers return a {@code FileSystem} then an attempt is
* made to locate the provider using the given class loader. If a provider
* returns a file system then the lookup terminates and the file system is
* returned.
*
* @param path
* the path to the file
@ -395,11 +392,132 @@ public final class FileSystems {
public static FileSystem newFileSystem(Path path,
ClassLoader loader)
throws IOException
{
return newFileSystem(path, Map.of(), loader);
}
/**
* Constructs a new {@code FileSystem} to access the contents of a file as a
* file system.
*
* <p> This method makes use of specialized providers that create pseudo file
* systems where the contents of one or more files is treated as a file
* system.
*
* <p> This method first attempts to locate an installed provider in exactly
* the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
* newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
* {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
* method is invoked to construct the new file system.
*
* @param path
* the path to the file
* @param env
* a map of provider specific properties to configure the file system;
* may be empty
*
* @return a new file system
*
* @throws ProviderNotFoundException
* if a provider supporting this file type cannot be located
* @throws ServiceConfigurationError
* when an error occurs while loading a service provider
* @throws IOException
* if an I/O error occurs
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission
*
* @since 13
*/
public static FileSystem newFileSystem(Path path, Map<String,?> env)
throws IOException
{
return newFileSystem(path, env, null);
}
/**
* Constructs a new {@code FileSystem} to access the contents of a file as a
* file system.
*
* <p> This method makes use of specialized providers that create pseudo file
* systems where the contents of one or more files is treated as a file
* system.
*
* <p> This method first attempts to locate an installed provider in exactly
* the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
* newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
* {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
* method is invoked with an empty map to construct the new file system.
*
* @param path
* the path to the file
*
* @return a new file system
*
* @throws ProviderNotFoundException
* if a provider supporting this file type cannot be located
* @throws ServiceConfigurationError
* when an error occurs while loading a service provider
* @throws IOException
* if an I/O error occurs
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission
*
* @since 13
*/
public static FileSystem newFileSystem(Path path) throws IOException {
return newFileSystem(path, Map.of(), null);
}
/**
* Constructs a new {@code FileSystem} to access the contents of a file as a
* file system.
*
* <p> This method makes use of specialized providers that create pseudo file
* systems where the contents of one or more files is treated as a file
* system.
*
* <p> This method iterates over the {@link FileSystemProvider#installedProviders()
* installed} providers. It invokes, in turn, each provider's {@link
* FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)}
* method. If a provider returns a file system then the iteration
* terminates and the file system is returned.
* If none of the installed providers return a {@code FileSystem} then
* an attempt is made to locate the provider using the given class loader.
* If a provider returns a file
* system, then the lookup terminates and the file system is returned.
*
* @param path
* the path to the file
* @param env
* a map of provider specific properties to configure the file system;
* may be empty
* @param loader
* the class loader to locate the provider or {@code null} to only
* attempt to locate an installed provider
*
* @return a new file system
*
* @throws ProviderNotFoundException
* if a provider supporting this file type cannot be located
* @throws ServiceConfigurationError
* when an error occurs while loading a service provider
* @throws IOException
* if an I/O error occurs
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission
*
* @since 13
*/
public static FileSystem newFileSystem(Path path, Map<String,?> env,
ClassLoader loader)
throws IOException
{
if (path == null)
throw new NullPointerException();
Map<String,?> env = Collections.emptyMap();
// check installed providers
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
try {

View File

@ -62,10 +62,11 @@ public final class Objects {
* Returns {@code true} if the arguments are equal to each other
* and {@code false} otherwise.
* Consequently, if both arguments are {@code null}, {@code true}
* is returned and if exactly one argument is {@code null}, {@code
* false} is returned. Otherwise, equality is determined by using
* the {@link Object#equals equals} method of the first
* argument.
* is returned. Otherwise, if the first argument is not {@code
* null}, equality is determined by calling the {@link
* Object#equals equals} method of the first argument with the
* second argument of this method. Otherwise, {@code false} is
* returned.
*
* @param a an object
* @param b an object to be compared with {@code a} for equality

View File

@ -1678,7 +1678,13 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
return;
int j = i;
i += 2;
int[] newtemp = new int[j + 3*(pLen-i) + 2];
int newTempLen;
try {
newTempLen = Math.addExact(j + 2, Math.multiplyExact(3, pLen - i));
} catch (ArithmeticException ae) {
throw new OutOfMemoryError();
}
int[] newtemp = new int[newTempLen];
System.arraycopy(temp, 0, newtemp, 0, j);
boolean inQuote = true;

View File

@ -826,6 +826,10 @@ public final class SSLSocketImpl
// reading lock
private final ReentrantLock readLock = new ReentrantLock();
// closing status
private volatile boolean isClosing;
private volatile boolean hasDepleted;
AppInputStream() {
this.appDataIsAvailable = false;
this.buffer = ByteBuffer.allocate(4096);
@ -871,8 +875,7 @@ public final class SSLSocketImpl
* and returning "-1" on non-fault EOF status.
*/
@Override
public int read(byte[] b, int off, int len)
throws IOException {
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException("the target buffer is null");
} else if (off < 0 || len < 0 || len > b.length - off) {
@ -900,12 +903,40 @@ public final class SSLSocketImpl
throw new SocketException("Connection or inbound has closed");
}
// Check if the input stream has been depleted.
//
// Note that the "hasDepleted" rather than the isClosing
// filed is checked here, in case the closing process is
// still in progress.
if (hasDepleted) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.fine("The input stream has been depleted");
}
return -1;
}
// Read the available bytes at first.
//
// Note that the receiving and processing of post-handshake message
// are also synchronized with the read lock.
readLock.lock();
try {
// Double check if the Socket is invalid (error or closed).
if (conContext.isBroken || conContext.isInboundClosed()) {
throw new SocketException(
"Connection or inbound has closed");
}
// Double check if the input stream has been depleted.
if (hasDepleted) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.fine("The input stream is closing");
}
return -1;
}
int remains = available();
if (remains > 0) {
int howmany = Math.min(remains, len);
@ -938,7 +969,17 @@ public final class SSLSocketImpl
return -1;
}
} finally {
readLock.unlock();
// Check if the input stream is closing.
//
// If the deplete() did not hold the lock, clean up the
// input stream here.
try {
if (isClosing) {
readLockedDeplete();
}
} finally {
readLock.unlock();
}
}
}
@ -1016,34 +1057,48 @@ public final class SSLSocketImpl
* socket gracefully, without impact the performance too much.
*/
private void deplete() {
if (conContext.isInboundClosed()) {
if (conContext.isInboundClosed() || isClosing) {
return;
}
readLock.lock();
try {
// double check
if (conContext.isInboundClosed()) {
return;
}
if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
return;
}
SSLSocketInputRecord socketInputRecord =
(SSLSocketInputRecord)conContext.inputRecord;
isClosing = true;
if (readLock.tryLock()) {
try {
socketInputRecord.deplete(
conContext.isNegotiated && (getSoTimeout() > 0));
} catch (IOException ioe) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning(
"input stream close depletion failed", ioe);
}
readLockedDeplete();
} finally {
readLock.unlock();
}
}
}
/**
* Try to use up the input records.
*
* Please don't call this method unless the readLock is held by
* the current thread.
*/
private void readLockedDeplete() {
// double check
if (hasDepleted || conContext.isInboundClosed()) {
return;
}
if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
return;
}
SSLSocketInputRecord socketInputRecord =
(SSLSocketInputRecord)conContext.inputRecord;
try {
socketInputRecord.deplete(
conContext.isNegotiated && (getSoTimeout() > 0));
} catch (Exception ex) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning(
"input stream close depletion failed", ex);
}
} finally {
readLock.unlock();
hasDepleted = true;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2019, 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
@ -73,15 +73,23 @@ class UnixFileAttributeViews {
boolean haveFd = false;
boolean useFutimes = false;
boolean useLutimes = false;
int fd = -1;
try {
fd = file.openForAttributeAccess(followLinks);
if (fd != -1) {
haveFd = true;
useFutimes = futimesSupported();
if (!followLinks) {
useLutimes = lutimesSupported() &&
UnixFileAttributes.get(file, false).isSymbolicLink();
}
if (!useLutimes) {
fd = file.openForAttributeAccess(followLinks);
if (fd != -1) {
haveFd = true;
useFutimes = futimesSupported();
}
}
} catch (UnixException x) {
if (x.errno() != UnixConstants.ENXIO) {
if (!(x.errno() == UnixConstants.ENXIO ||
(x.errno() == UnixConstants.ELOOP && useLutimes))) {
x.rethrowAsIOException(file);
}
}
@ -112,6 +120,8 @@ class UnixFileAttributeViews {
try {
if (useFutimes) {
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
} else {
utimes(file, accessValue, modValue);
}
@ -131,6 +141,8 @@ class UnixFileAttributeViews {
try {
if (useFutimes) {
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
} else {
utimes(file, accessValue, modValue);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2019, 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
@ -401,7 +401,7 @@ class UnixNativeDispatcher {
static native void fchmod(int fd, int mode) throws UnixException;
/**
* utimes(conar char* path, const struct timeval times[2])
* utimes(const char* path, const struct timeval times[2])
*/
static void utimes(UnixPath path, long times0, long times1)
throws UnixException
@ -417,10 +417,26 @@ class UnixNativeDispatcher {
throws UnixException;
/**
* futimes(int fildes,, const struct timeval times[2])
* futimes(int fildes, const struct timeval times[2])
*/
static native void futimes(int fd, long times0, long times1) throws UnixException;
/**
* lutimes(const char* path, const struct timeval times[2])
*/
static void lutimes(UnixPath path, long times0, long times1)
throws UnixException
{
NativeBuffer buffer = copyToNativeBuffer(path);
try {
lutimes0(buffer.address(), times0, times1);
} finally {
buffer.release();
}
}
private static native void lutimes0(long pathAddress, long times0, long times1)
throws UnixException;
/**
* DIR *opendir(const char* dirname)
*/
@ -578,9 +594,10 @@ class UnixNativeDispatcher {
/**
* Capabilities
*/
private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls
private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls
private static final int SUPPORTS_FUTIMES = 1 << 2;
private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features
private static final int SUPPORTS_LUTIMES = 1 << 4;
private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features
private static final int capabilities;
/**
@ -597,6 +614,13 @@ class UnixNativeDispatcher {
return (capabilities & SUPPORTS_FUTIMES) != 0;
}
/**
* Supports lutimes
*/
static boolean lutimesSupported() {
return (capabilities & SUPPORTS_LUTIMES) != 0;
}
/**
* Supports file birth (creation) time attribute
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2019, 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
@ -143,6 +143,7 @@ typedef int fstatat64_func(int, const char *, struct stat64 *, int);
typedef int unlinkat_func(int, const char*, int);
typedef int renameat_func(int, const char*, int, const char*);
typedef int futimesat_func(int, const char *, const struct timeval *);
typedef int lutimes_func(const char *, const struct timeval *);
typedef DIR* fdopendir_func(int);
static openat64_func* my_openat64_func = NULL;
@ -150,6 +151,7 @@ static fstatat64_func* my_fstatat64_func = NULL;
static unlinkat_func* my_unlinkat_func = NULL;
static renameat_func* my_renameat_func = NULL;
static futimesat_func* my_futimesat_func = NULL;
static lutimes_func* my_lutimes_func = NULL;
static fdopendir_func* my_fdopendir_func = NULL;
/**
@ -269,7 +271,10 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
#endif
my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
#ifndef _ALLBSD_SOURCE
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes");
#endif
#if defined(_AIX)
my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64");
#else
@ -282,13 +287,16 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
#endif
/* supports futimes or futimesat */
/* supports futimes or futimesat and/or lutimes */
#ifdef _ALLBSD_SOURCE
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
#else
if (my_futimesat_func != NULL)
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
if (my_lutimes_func != NULL)
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
#endif
/* supports openat, etc. */
@ -675,7 +683,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint file
RESTARTABLE(futimes(filedes, &times[0]), err);
#else
if (my_futimesat_func == NULL) {
JNU_ThrowInternalError(env, "my_ftimesat_func is NULL");
JNU_ThrowInternalError(env, "my_futimesat_func is NULL");
return;
}
RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
@ -685,6 +693,34 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint file
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this,
jlong pathAddress, jlong accessTime, jlong modificationTime)
{
int err;
struct timeval times[2];
const char* path = (const char*)jlong_to_ptr(pathAddress);
times[0].tv_sec = accessTime / 1000000;
times[0].tv_usec = accessTime % 1000000;
times[1].tv_sec = modificationTime / 1000000;
times[1].tv_usec = modificationTime % 1000000;
#ifdef _ALLBSD_SOURCE
RESTARTABLE(lutimes(path, &times[0]), err);
#else
if (my_lutimes_func == NULL) {
JNU_ThrowInternalError(env, "my_lutimes_func is NULL");
return;
}
RESTARTABLE((*my_lutimes_func)(path, &times[0]), err);
#endif
if (err == -1) {
throwUnixException(env, errno);
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
jlong pathAddress)

View File

@ -40,6 +40,7 @@ import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
@ -325,12 +326,13 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
throw new IllegalArgumentException("element null");
}
Text hmaclength =
XMLUtils.selectDsNodeText(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0);
if (hmaclength != null) {
this.HMACOutputLength = Integer.parseInt(hmaclength.getData());
this.HMACOutputLengthSet = true;
Node n = XMLUtils.selectDsNode(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0);
if (n != null) {
String hmacLength = XMLUtils.getFullTextChildrenFromNode(n);
if (hmacLength != null && !"".equals(hmacLength)) {
this.HMACOutputLength = Integer.parseInt(hmacLength);
this.HMACOutputLengthSet = true;
}
}
}

View File

@ -33,7 +33,6 @@ import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.DSAKey;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
@ -41,6 +40,7 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
public class SignatureDSA extends SignatureAlgorithmSpi {
@ -109,7 +109,7 @@ public class SignatureDSA extends SignatureAlgorithmSpi {
throws XMLSignatureException {
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Called DSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature));
LOG.debug("Called DSA.verify() on " + XMLUtils.encodeToString(signature));
}
byte[] jcebytes = JavaUtils.convertDsaXMLDSIGtoASN1(signature,

View File

@ -33,12 +33,12 @@ import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
/**
*
@ -132,7 +132,7 @@ public abstract class SignatureECDSA extends SignatureAlgorithmSpi {
byte[] jcebytes = SignatureECDSA.convertXMLDSIGtoASN1(signature);
if (LOG.isDebugEnabled()) {
LOG.debug("Called ECDSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature));
LOG.debug("Called ECDSA.verify() on " + XMLUtils.encodeToString(signature));
}
return this.signatureAlgorithm.verify(jcebytes);

View File

@ -331,7 +331,7 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
ns.addMapping(NName, NValue, attribute);
}
} else if (XML_LANG_URI.equals(attribute.getNamespaceURI())
&& (!c14n11 || c14n11 && !"id".equals(NName))) {
&& (!c14n11 || !"id".equals(NName))) {
xmlattrStack.addXmlnsAttr(attribute);
}
}

View File

@ -342,7 +342,7 @@ public abstract class Canonicalizer20010315Excl extends CanonicalizerBase {
protected void circumventBugIfNeeded(XMLSignatureInput input)
throws CanonicalizationException, ParserConfigurationException,
IOException, SAXException {
if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty() || inclusiveNSSet.isEmpty()) {
if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty()) {
return;
}
Document doc = null;

View File

@ -50,7 +50,6 @@ import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
import com.sun.org.apache.xml.internal.security.transforms.Transforms;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.ElementProxy;
import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Attr;

View File

@ -26,6 +26,7 @@ import java.security.PublicKey;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue;
import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue;
import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
@ -107,9 +108,14 @@ public class KeyValue extends SignatureElementProxy implements KeyInfoContent {
appendSelf(rsa);
addReturnToSelf();
} else if (pk instanceof java.security.interfaces.ECPublicKey) {
ECKeyValue ec = new ECKeyValue(getDocument(), pk);
appendSelf(ec);
addReturnToSelf();
} else {
String error = "The given PublicKey type " + pk + " is not supported. Only DSAPublicKey and "
+ "RSAPublicKey types are currently supported";
+ "RSAPublicKey and ECPublicKey types are currently supported";
throw new IllegalArgumentException(error);
}
}

View File

@ -0,0 +1,366 @@
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.sun.org.apache.xml.internal.security.keys.content.keyvalues;
import java.io.IOException;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECField;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.xml.crypto.MarshalException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.I18n;
import com.sun.org.apache.xml.internal.security.utils.Signature11ElementProxy;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
public class ECKeyValue extends Signature11ElementProxy implements KeyValueContent {
/* Supported curve, secp256r1 */
private static final Curve SECP256R1 = initializeCurve(
"secp256r1 [NIST P-256, X9.62 prime256v1]",
"1.2.840.10045.3.1.7",
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
1
);
/* Supported curve secp384r1 */
private static final Curve SECP384R1 = initializeCurve(
"secp384r1 [NIST P-384]",
"1.3.132.0.34",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
1
);
/* Supported curve secp521r1 */
private static final Curve SECP521R1 = initializeCurve(
"secp521r1 [NIST P-521]",
"1.3.132.0.35",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
1
);
private static Curve initializeCurve(String name, String oid,
String sfield, String a, String b,
String x, String y, String n, int h) {
BigInteger p = bigInt(sfield);
ECField field = new ECFieldFp(p);
EllipticCurve curve = new EllipticCurve(field, bigInt(a),
bigInt(b));
ECPoint g = new ECPoint(bigInt(x), bigInt(y));
return new Curve(name, oid, curve, g, bigInt(n), h);
}
/**
* Constructor DSAKeyValue
*
* @param element
* @param baseURI
* @throws XMLSecurityException
*/
public ECKeyValue(Element element, String baseURI) throws XMLSecurityException {
super(element, baseURI);
}
/**
* Constructor DSAKeyValue
*
* @param doc
* @param key
* @throws IllegalArgumentException
*/
public ECKeyValue(Document doc, Key key) throws IllegalArgumentException {
super(doc);
addReturnToSelf();
if (key instanceof ECPublicKey) {
ECParameterSpec ecParams = ((ECPublicKey)key).getParams();
// NamedCurve
String oid = getCurveOid(ecParams);
if (oid == null) {
throw new IllegalArgumentException("Invalid ECParameterSpec");
}
Element namedCurveElement = XMLUtils.createElementInSignature11Space(getDocument(), "NamedCurve");
namedCurveElement.setAttributeNS(null, "URI", "urn:oid:" + oid);
appendSelf(namedCurveElement);
addReturnToSelf();
// PublicKey
ECPoint ecPoint = ((ECPublicKey)key).getW();
byte[] secPublicKey = encodePoint(ecPoint, ecParams.getCurve());
String encoded = XMLUtils.encodeToString(secPublicKey);
Element publicKeyElement = XMLUtils.createElementInSignature11Space(getDocument(), "PublicKey");
Text text = getDocument().createTextNode(encoded);
publicKeyElement.appendChild(text);
appendSelf(publicKeyElement);
addReturnToSelf();
} else {
Object[] exArgs = { Constants._TAG_ECKEYVALUE, key.getClass().getName() };
throw new IllegalArgumentException(I18n.translate("KeyValue.IllegalArgument", exArgs));
}
}
/** {@inheritDoc} */
public PublicKey getPublicKey() throws XMLSecurityException {
try {
ECParameterSpec ecParams = null;
Element curElem = getFirstChildElement(getElement());
if (curElem == null) {
throw new MarshalException("KeyValue must contain at least one type");
}
if ("ECParameters".equals(curElem.getLocalName())
&& Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
throw new UnsupportedOperationException
("ECParameters not supported");
} else if ("NamedCurve".equals(curElem.getLocalName())
&& Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
String uri = null;
if (curElem.hasAttributeNS(null, "URI")) {
uri = curElem.getAttributeNS(null, "URI");
}
// strip off "urn:oid"
if (uri.startsWith("urn:oid:")) {
String oid = uri.substring("urn:oid:".length());
ecParams = getECParameterSpec(oid);
if (ecParams == null) {
throw new MarshalException("Invalid curve OID");
}
} else {
throw new MarshalException("Invalid NamedCurve URI");
}
} else {
throw new MarshalException("Invalid ECKeyValue");
}
curElem = getNextSiblingElement(curElem, "PublicKey", Constants.SignatureSpec11NS);
ECPoint ecPoint = null;
try {
String content = XMLUtils.getFullTextChildrenFromNode(curElem);
ecPoint = decodePoint(XMLUtils.decode(content), ecParams.getCurve());
} catch (IOException ioe) {
throw new MarshalException("Invalid EC Point", ioe);
}
ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams);
return KeyFactory.getInstance("EC").generatePublic(spec);
} catch (NoSuchAlgorithmException ex) {
throw new XMLSecurityException(ex);
} catch (InvalidKeySpecException ex) {
throw new XMLSecurityException(ex);
} catch (MarshalException ex) {
throw new XMLSecurityException(ex);
}
}
/** {@inheritDoc} */
public String getBaseLocalName() {
return Constants._TAG_ECKEYVALUE;
}
private static Element getFirstChildElement(Node node) {
Node child = node.getFirstChild();
while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
child = child.getNextSibling();
}
return (Element)child;
}
private static Element getNextSiblingElement(Node node, String localName, String namespaceURI)
throws MarshalException
{
return verifyElement(getNextSiblingElement(node), localName, namespaceURI);
}
private static Element getNextSiblingElement(Node node) {
Node sibling = node.getNextSibling();
while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE) {
sibling = sibling.getNextSibling();
}
return (Element)sibling;
}
private static Element verifyElement(Element elem, String localName, String namespaceURI)
throws MarshalException
{
if (elem == null) {
throw new MarshalException("Missing " + localName + " element");
}
String name = elem.getLocalName();
String namespace = elem.getNamespaceURI();
if (!name.equals(localName) || namespace == null && namespaceURI != null
|| namespace != null && !namespace.equals(namespaceURI)) {
throw new MarshalException("Invalid element name: " +
namespace + ":" + name + ", expected " + namespaceURI + ":" + localName);
}
return elem;
}
private static String getCurveOid(ECParameterSpec params) {
// Check that the params represent one of the supported
// curves. If there is a match, return the object identifier
// of the curve.
Curve match;
if (matchCurve(params, SECP256R1)) {
match = SECP256R1;
} else if (matchCurve(params, SECP384R1)) {
match = SECP384R1;
} else if (matchCurve(params, SECP521R1)) {
match = SECP521R1;
} else {
return null;
}
return match.getObjectId();
}
private static boolean matchCurve(ECParameterSpec params, Curve curve) {
int fieldSize = params.getCurve().getField().getFieldSize();
return curve.getCurve().getField().getFieldSize() == fieldSize
&& curve.getCurve().equals(params.getCurve())
&& curve.getGenerator().equals(params.getGenerator())
&& curve.getOrder().equals(params.getOrder())
&& curve.getCofactor() == params.getCofactor();
}
private static ECPoint decodePoint(byte[] data, EllipticCurve curve)
throws IOException {
if (data.length == 0 || data[0] != 4) {
throw new IOException("Only uncompressed point format " +
"supported");
}
// Per ANSI X9.62, an encoded point is a 1 byte type followed by
// ceiling(LOG base 2 field-size / 8) bytes of x and the same of y.
int n = (data.length - 1) / 2;
if (n != (curve.getField().getFieldSize() + 7) >> 3) {
throw new IOException("Point does not match field size");
}
byte[] xb = Arrays.copyOfRange(data, 1, 1 + n);
byte[] yb = Arrays.copyOfRange(data, n + 1, n + 1 + n);
return new ECPoint(new BigInteger(1, xb), new BigInteger(1, yb));
}
private static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
// get field size in bytes (rounding up)
int n = (curve.getField().getFieldSize() + 7) >> 3;
byte[] xb = trimZeroes(point.getAffineX().toByteArray());
byte[] yb = trimZeroes(point.getAffineY().toByteArray());
if (xb.length > n || yb.length > n) {
throw new RuntimeException("Point coordinates do not " +
"match field size");
}
byte[] b = new byte[1 + (n << 1)];
b[0] = 4; // uncompressed
System.arraycopy(xb, 0, b, n - xb.length + 1, xb.length);
System.arraycopy(yb, 0, b, b.length - yb.length, yb.length);
return b;
}
private static byte[] trimZeroes(byte[] b) {
int i = 0;
while (i < b.length - 1 && b[i] == 0) {
i++;
}
if (i == 0) {
return b;
}
return Arrays.copyOfRange(b, i, b.length);
}
private static ECParameterSpec getECParameterSpec(String oid) {
if (oid.equals(SECP256R1.getObjectId())) {
return SECP256R1;
} else if (oid.equals(SECP384R1.getObjectId())) {
return SECP384R1;
} else if (oid.equals(SECP521R1.getObjectId())) {
return SECP521R1;
} else {
return null;
}
}
static final class Curve extends ECParameterSpec {
private final String name;
private final String oid;
Curve(String name, String oid, EllipticCurve curve,
ECPoint g, BigInteger n, int h) {
super(curve, g, n, h);
this.name = name;
this.oid = oid;
}
private String getName() {
return name;
}
private String getObjectId() {
return oid;
}
}
private static BigInteger bigInt(String s) {
return new BigInteger(s, 16);
}
}

View File

@ -24,18 +24,18 @@ package com.sun.org.apache.xml.internal.security.keys.content.x509;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Base64;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Handles SubjectKeyIdentifier (SKI) for X.509v3.
*
* @see <A HREF="http://docs.oracle.com/javase/1.5.0/docs/api/java/security/cert/X509Extension.html">
* @see <A HREF="http://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Extension.html">
* Interface X509Extension</A>
*/
public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataContent {
@ -138,7 +138,7 @@ public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataCont
System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length);
if (LOG.isDebugEnabled()) {
LOG.debug("Base64 of SKI is " + Base64.getMimeEncoder().encodeToString(skidValue));
LOG.debug("Base64 of SKI is " + XMLUtils.encodeToString(skidValue));
}
return skidValue;

View File

@ -33,6 +33,7 @@ import javax.crypto.SecretKey;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DEREncodedKeyValueResolver;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DSAKeyValueResolver;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.ECKeyValueResolver;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.KeyInfoReferenceResolver;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RSAKeyValueResolver;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RetrievalMethodResolver;
@ -295,6 +296,7 @@ public class KeyResolver {
keyResolverList.add(new KeyResolver(new DEREncodedKeyValueResolver()));
keyResolverList.add(new KeyResolver(new KeyInfoReferenceResolver()));
keyResolverList.add(new KeyResolver(new X509DigestResolver()));
keyResolverList.add(new KeyResolver(new ECKeyValueResolver()));
resolverVector.addAll(keyResolverList);
}

View File

@ -0,0 +1,97 @@
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue;
import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi;
import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Element;
public class ECKeyValueResolver extends KeyResolverSpi {
private static final com.sun.org.slf4j.internal.Logger LOG =
com.sun.org.slf4j.internal.LoggerFactory.getLogger(ECKeyValueResolver.class);
/**
* Method engineResolvePublicKey
*
* @param element
* @param baseURI
* @param storage
* @return null if no {@link PublicKey} could be obtained
*/
public PublicKey engineLookupAndResolvePublicKey(
Element element, String baseURI, StorageResolver storage
) {
if (element == null) {
return null;
}
Element ecKeyElement = null;
boolean isKeyValue =
XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE);
if (isKeyValue) {
ecKeyElement =
XMLUtils.selectDs11Node(element.getFirstChild(), Constants._TAG_ECKEYVALUE, 0);
} else if (XMLUtils.elementIsInSignature11Space(element, Constants._TAG_ECKEYVALUE)) {
// this trick is needed to allow the RetrievalMethodResolver to eat a
// ds:ECKeyValue directly (without KeyValue)
ecKeyElement = element;
}
if (ecKeyElement == null) {
return null;
}
try {
ECKeyValue ecKeyValue = new ECKeyValue(ecKeyElement, baseURI);
return ecKeyValue.getPublicKey();
} catch (XMLSecurityException ex) {
LOG.debug(ex.getMessage(), ex);
//do nothing
}
return null;
}
/** {@inheritDoc} */
public X509Certificate engineLookupResolveX509Certificate(
Element element, String baseURI, StorageResolver storage
) {
return null;
}
/** {@inheritDoc} */
public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String baseURI, StorageResolver storage
) {
return null;
}
}

View File

@ -44,11 +44,12 @@ public class RSAKeyValueResolver extends KeyResolverSpi {
public PublicKey engineLookupAndResolvePublicKey(
Element element, String baseURI, StorageResolver storage
) {
LOG.debug("Can I resolve {}", element.getTagName());
if (element == null) {
return null;
}
LOG.debug("Can I resolve {}", element.getTagName());
boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE);
Element rsaKeyElement = null;
if (isKeyValue) {

View File

@ -35,12 +35,12 @@ import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;
import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverException;
import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverSpi;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
/**
* This {@link StorageResolverSpi} makes all raw (binary) {@link X509Certificate}s
@ -207,7 +207,7 @@ public class CertsInFilesystemDirectoryResolver extends StorageResolverSpi {
System.out.println();
System.out.println("Base64(SKI())= \""
+ Base64.getMimeEncoder().encodeToString(ski) + "\"");
+ XMLUtils.encodeToString(ski) + "\"");
System.out.println("cert.getSerialNumber()= \""
+ cert.getSerialNumber().toString() + "\"");
System.out.println("cert.getSubjectX500Principal().getName()= \""

Some files were not shown because too many files have changed in this diff Show More