From 5a2d8cb81908c08a695363b4f8be77350030cc97 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 1 Feb 2017 17:56:22 -0500 Subject: [PATCH 01/86] 8140685: Fix backtrace building to not rely on constant pool merging Store Symbol* for the name in the backtrace Reviewed-by: gtriantafill, dholmes, kbarrett, lfoltan --- .../src/share/vm/classfile/javaClasses.cpp | 80 +++++++++---------- .../src/share/vm/classfile/javaClasses.hpp | 6 +- hotspot/src/share/vm/memory/oopFactory.cpp | 16 ++-- hotspot/src/share/vm/memory/oopFactory.hpp | 4 +- hotspot/src/share/vm/oops/typeArrayOop.hpp | 16 ++-- 5 files changed, 59 insertions(+), 63 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 91b51404489..0bd1aa5c836 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1578,7 +1578,7 @@ class BacktraceBuilder: public StackObj { typeArrayOop _methods; typeArrayOop _bcis; objArrayOop _mirrors; - typeArrayOop _cprefs; // needed to insulate method name against redefinition + typeArrayOop _names; // needed to insulate method name against redefinition int _index; NoSafepointVerifier _nsv; @@ -1586,7 +1586,7 @@ class BacktraceBuilder: public StackObj { trace_methods_offset = java_lang_Throwable::trace_methods_offset, trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, - trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset, + trace_names_offset = java_lang_Throwable::trace_names_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size @@ -1608,16 +1608,16 @@ class BacktraceBuilder: public StackObj { assert(mirrors != NULL, "mirror array should be initialized in backtrace"); return mirrors; } - static typeArrayOop get_cprefs(objArrayHandle chunk) { - typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset)); - assert(cprefs != NULL, "cprefs array should be initialized in backtrace"); - return cprefs; + static typeArrayOop get_names(objArrayHandle chunk) { + typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset)); + assert(names != NULL, "names array should be initialized in backtrace"); + return names; } public: // constructor for new backtrace - BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { + BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) { expand(CHECK); _backtrace = _head; _index = 0; @@ -1627,9 +1627,10 @@ class BacktraceBuilder: public StackObj { _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); - _cprefs = get_cprefs(backtrace); + _names = get_names(backtrace); assert(_methods->length() == _bcis->length() && - _methods->length() == _mirrors->length(), + _methods->length() == _mirrors->length() && + _mirrors->length() == _names->length(), "method and source information arrays should match"); // head is the preallocated backtrace @@ -1653,8 +1654,8 @@ class BacktraceBuilder: public StackObj { objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); objArrayHandle new_mirrors(THREAD, mirrors); - typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle new_cprefs(THREAD, cprefs); + typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK); + typeArrayHandle new_names(THREAD, names); if (!old_head.is_null()) { old_head->obj_at_put(trace_next_offset, new_head()); @@ -1662,13 +1663,13 @@ class BacktraceBuilder: public StackObj { new_head->obj_at_put(trace_methods_offset, new_methods()); new_head->obj_at_put(trace_bcis_offset, new_bcis()); new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); - new_head->obj_at_put(trace_cprefs_offset, new_cprefs()); + new_head->obj_at_put(trace_names_offset, new_names()); _head = new_head(); _methods = new_methods(); _bcis = new_bcis(); _mirrors = new_mirrors(); - _cprefs = new_cprefs(); + _names = new_names(); _index = 0; } @@ -1690,7 +1691,11 @@ class BacktraceBuilder: public StackObj { _methods->short_at_put(_index, method->orig_method_idnum()); _bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version())); - _cprefs->short_at_put(_index, method->name_index()); + + // Note:this doesn't leak symbols because the mirror in the backtrace keeps the + // klass owning the symbols alive so their refcounts aren't decremented. + Symbol* name = method->name(); + _names->symbol_at_put(_index, name); // We need to save the mirrors in the backtrace to keep the class // from being unloaded while we still have this stack trace. @@ -1705,10 +1710,10 @@ struct BacktraceElement : public StackObj { int _method_id; int _bci; int _version; - int _cpref; + Symbol* _name; Handle _mirror; - BacktraceElement(Handle mirror, int mid, int version, int bci, int cpref) : - _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _cpref(cpref) {} + BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name) : + _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _name(name) {} }; class BacktraceIterator : public StackObj { @@ -1717,7 +1722,7 @@ class BacktraceIterator : public StackObj { objArrayHandle _mirrors; typeArrayHandle _methods; typeArrayHandle _bcis; - typeArrayHandle _cprefs; + typeArrayHandle _names; void init(objArrayHandle result, Thread* thread) { // Get method id, bci, version and mirror from chunk @@ -1726,7 +1731,7 @@ class BacktraceIterator : public StackObj { _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); - _cprefs = typeArrayHandle(thread, BacktraceBuilder::get_cprefs(_result)); + _names = typeArrayHandle(thread, BacktraceBuilder::get_names(_result)); _index = 0; } } @@ -1741,7 +1746,7 @@ class BacktraceIterator : public StackObj { _methods->short_at(_index), Backtrace::version_at(_bcis->int_at(_index)), Backtrace::bci_at(_bcis->int_at(_index)), - _cprefs->short_at(_index)); + _names->symbol_at(_index)); _index++; if (_index >= java_lang_Throwable::trace_chunk_size) { @@ -1761,7 +1766,7 @@ class BacktraceIterator : public StackObj { // Print stack trace element to resource allocated buffer static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, - int version, int bci, int cpref) { + int version, int bci, Symbol* name) { ResourceMark rm; // Get strings and string lengths @@ -1769,11 +1774,7 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m const char* klass_name = holder->external_name(); int buf_len = (int)strlen(klass_name); - Method* method = holder->method_with_orig_idnum(method_id, version); - - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); - char* method_name = sym->as_C_string(); + char* method_name = name->as_C_string(); buf_len += (int)strlen(method_name); char* source_file_name = NULL; @@ -1809,6 +1810,8 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } } + // The method can be NULL if the requested class version is gone + Method* method = holder->method_with_orig_idnum(method_id, version); if (!version_matches(method, version)) { strcat(buf, "Redefined)"); } else { @@ -1840,8 +1843,7 @@ void java_lang_Throwable::print_stack_element(outputStream *st, const methodHand Handle mirror = method->method_holder()->java_mirror(); int method_id = method->orig_method_idnum(); int version = method->constants()->version(); - int cpref = method->name_index(); - print_stack_element_to_stream(st, mirror, method_id, version, bci, cpref); + print_stack_element_to_stream(st, mirror, method_id, version, bci, method->name()); } /** @@ -1865,7 +1867,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) while (iter.repeat()) { BacktraceElement bte = iter.next(THREAD); - print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._cpref); + print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name); } { // Call getCause() which doesn't necessarily return the _cause field. @@ -2144,7 +2146,7 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable, method, bte._version, bte._bci, - bte._cpref, CHECK); + bte._name, CHECK); } } @@ -2159,15 +2161,14 @@ oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRA Handle element = ik->allocate_instance_handle(CHECK_0); - int cpref = method->name_index(); int version = method->constants()->version(); - fill_in(element, method->method_holder(), method, version, bci, cpref, CHECK_0); + fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0); return element(); } void java_lang_StackTraceElement::fill_in(Handle element, InstanceKlass* holder, const methodHandle& method, - int version, int bci, int cpref, TRAPS) { + int version, int bci, Symbol* name, TRAPS) { assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check"); // Fill in class name @@ -2184,11 +2185,8 @@ void java_lang_StackTraceElement::fill_in(Handle element, java_lang_StackTraceElement::set_classLoaderName(element(), loader_name); } - // The method can be NULL if the requested class version is gone - Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref); - // Fill in method name - oop methodname = StringTable::intern(sym, CHECK); + oop methodname = StringTable::intern(name, CHECK); java_lang_StackTraceElement::set_methodName(element(), methodname); // Fill in module name and version @@ -2205,7 +2203,7 @@ void java_lang_StackTraceElement::fill_in(Handle element, java_lang_StackTraceElement::set_moduleVersion(element(), module_version); } - if (!version_matches(method(), version)) { + if (method() == NULL || !version_matches(method(), version)) { // The method was redefined, accurate line number information isn't available java_lang_StackTraceElement::set_fileName(element(), NULL); java_lang_StackTraceElement::set_lineNumber(element(), -1); @@ -2252,8 +2250,8 @@ void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle short version = stackFrame->short_field(_version_offset); short bci = stackFrame->short_field(_bci_offset); - int cpref = method->name_index(); - java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK); + Symbol* name = method->name(); + java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK); } void java_lang_StackFrameInfo::compute_offsets() { diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 0cf0090e851..67b4a2e8ac0 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -466,7 +466,7 @@ class java_lang_Throwable: AllStatic { trace_methods_offset = 0, trace_bcis_offset = 1, trace_mirrors_offset = 2, - trace_cprefs_offset = 3, + trace_names_offset = 3, trace_next_offset = 4, trace_size = 5, trace_chunk_size = 32 @@ -1331,7 +1331,7 @@ class java_lang_StackTraceElement: AllStatic { static oop create(const methodHandle& method, int bci, TRAPS); static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method, - int version, int bci, int cpref, TRAPS); + int version, int bci, Symbol* name, TRAPS); // Debugging friend class JavaClasses; diff --git a/hotspot/src/share/vm/memory/oopFactory.cpp b/hotspot/src/share/vm/memory/oopFactory.cpp index 3693deb5007..f8d14feff4e 100644 --- a/hotspot/src/share/vm/memory/oopFactory.cpp +++ b/hotspot/src/share/vm/memory/oopFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -57,17 +57,15 @@ typeArrayOop oopFactory::new_typeArray(BasicType type, int length, TRAPS) { return result; } -// Create a Java array that points to metadata. -// As far as Java code is concerned, a metaData array is either an array of -// int or long depending on pointer size. Only a few things use this, like -// stack trace elements in Throwable. They cast Method* into this type. -// Note:can't point to symbols because there's no way to unreference count -// them when this object goes away. -typeArrayOop oopFactory::new_metaDataArray(int length, TRAPS) { +// Create a Java array that points to Symbol. +// As far as Java code is concerned, a Symbol array is either an array of +// int or long depending on pointer size. Only stack trace elements in Throwable use +// this. They cast Symbol* into this type. +typeArrayOop oopFactory::new_symbolArray(int length, TRAPS) { BasicType type = LP64_ONLY(T_LONG) NOT_LP64(T_INT); Klass* type_asKlassOop = Universe::typeArrayKlassObj(type); TypeArrayKlass* type_asArrayKlass = TypeArrayKlass::cast(type_asKlassOop); - typeArrayOop result = type_asArrayKlass->allocate_common(length, true, THREAD); + typeArrayOop result = type_asArrayKlass->allocate(length, THREAD); return result; } diff --git a/hotspot/src/share/vm/memory/oopFactory.hpp b/hotspot/src/share/vm/memory/oopFactory.hpp index c8dd27f2df8..d44e6907568 100644 --- a/hotspot/src/share/vm/memory/oopFactory.hpp +++ b/hotspot/src/share/vm/memory/oopFactory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -62,7 +62,7 @@ class oopFactory: AllStatic { static typeArrayOop new_typeArray(BasicType type, int length, TRAPS); static typeArrayOop new_typeArray_nozero(BasicType type, int length, TRAPS); - static typeArrayOop new_metaDataArray(int length, TRAPS); + static typeArrayOop new_symbolArray(int length, TRAPS); // Regular object arrays static objArrayOop new_objArray(Klass* klass, int length, TRAPS); diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index adf99a30fe4..df3884da816 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -122,19 +122,19 @@ class typeArrayOopDesc : public arrayOopDesc { jbyte byte_at_acquire(int which) const { return OrderAccess::load_acquire(byte_at_addr(which)); } void release_byte_at_put(int which, jbyte contents) { OrderAccess::release_store(byte_at_addr(which), contents); } - // Java thinks metadata arrays are just arrays of either long or int, since + // Java thinks Symbol arrays are just arrays of either long or int, since // there doesn't seem to be T_ADDRESS, so this is a bit of unfortunate // casting #ifdef _LP64 - Metadata* metadata_at(int which) const { - return (Metadata*)*long_at_addr(which); } - void metadata_at_put(int which, Metadata* contents) { + Symbol* symbol_at(int which) const { + return (Symbol*)*long_at_addr(which); } + void symbol_at_put(int which, Symbol* contents) { *long_at_addr(which) = (jlong)contents; } #else - Metadata* metadata_at(int which) const { - return (Metadata*)*int_at_addr(which); } - void metadata_at_put(int which, Metadata* contents) { + Symbol* symbol_at(int which) const { + return (Symbol*)*int_at_addr(which); } + void symbol_at_put(int which, Symbol* contents) { *int_at_addr(which) = (int)contents; } #endif // _LP64 From 9d95a1541bf8ce798c75172c74ff3ebfd2400d5a Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 30 May 2016 14:42:50 +0300 Subject: [PATCH 02/86] 8142749: HeapRegion::_predicted_bytes_to_copy is unused and can be removed Reviewed-by: tschatzl, drwhite --- hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp | 10 ++++------ hotspot/src/share/vm/gc/g1/heapRegion.cpp | 15 +++++---------- hotspot/src/share/vm/gc/g1/heapRegion.hpp | 13 +------------ 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index 7ff07bc5a72..deaf1cbc65f 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -216,14 +216,14 @@ public: } bool doHeapRegion(HeapRegion *hr) { - bool during_initial_mark = _g1h->collector_state()->during_initial_mark_pause(); - bool during_conc_mark = _g1h->collector_state()->mark_in_progress(); - assert(!hr->is_pinned(), "Unexpected pinned region at index %u", hr->hrm_index()); assert(hr->in_collection_set(), "bad CS"); if (_hrclaimer->claim_region(hr->hrm_index())) { if (hr->evacuation_failed()) { + bool during_initial_mark = _g1h->collector_state()->during_initial_mark_pause(); + bool during_conc_mark = _g1h->collector_state()->mark_in_progress(); + hr->note_self_forwarding_removal_start(during_initial_mark, during_conc_mark); _g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr); @@ -234,9 +234,7 @@ public: hr->rem_set()->clean_strong_code_roots(hr); - hr->note_self_forwarding_removal_end(during_initial_mark, - during_conc_mark, - live_bytes); + hr->note_self_forwarding_removal_end(live_bytes); } } return false; diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index e62dbab436f..2bd451fc700 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -290,8 +290,7 @@ HeapRegion::HeapRegion(uint hrm_index, _containing_set(NULL), #endif // ASSERT _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1), - _rem_set(NULL), _recorded_rs_length(0), _predicted_elapsed_time_ms(0), - _predicted_bytes_to_copy(0) + _rem_set(NULL), _recorded_rs_length(0), _predicted_elapsed_time_ms(0) { _rem_set = new HeapRegionRemSet(bot, this); @@ -343,9 +342,7 @@ void HeapRegion::note_self_forwarding_removal_start(bool during_initial_mark, } } -void HeapRegion::note_self_forwarding_removal_end(bool during_initial_mark, - bool during_conc_mark, - size_t marked_bytes) { +void HeapRegion::note_self_forwarding_removal_end(size_t marked_bytes) { assert(marked_bytes <= used(), "marked: " SIZE_FORMAT " used: " SIZE_FORMAT, marked_bytes, used()); _prev_top_at_mark_start = top(); @@ -483,7 +480,6 @@ void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const { class VerifyStrongCodeRootOopClosure: public OopClosure { const HeapRegion* _hr; - nmethod* _nm; bool _failures; bool _has_oops_in_region; @@ -510,7 +506,7 @@ class VerifyStrongCodeRootOopClosure: public OopClosure { } public: - VerifyStrongCodeRootOopClosure(const HeapRegion* hr, nmethod* nm): + VerifyStrongCodeRootOopClosure(const HeapRegion* hr): _hr(hr), _failures(false), _has_oops_in_region(false) {} void do_oop(narrowOop* p) { do_oop_work(p); } @@ -536,7 +532,7 @@ public: p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } else { - VerifyStrongCodeRootOopClosure oop_cl(_hr, nm); + VerifyStrongCodeRootOopClosure oop_cl(_hr); nm->oops_do(&oop_cl); if (!oop_cl.has_oops_in_region()) { log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " PTR_FORMAT " in its strong code roots with no pointers into region", @@ -728,7 +724,6 @@ public: Log(gc, verify) log; if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - bool failed = false; HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); HeapRegion* to = _g1h->heap_region_containing(obj); if (from != NULL && to != NULL && @@ -763,7 +758,7 @@ public: log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); log.error("----------"); _failures = true; - if (!failed) _n_failures++; + _n_failures++; } } } diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.hpp index 10e45c1c1ba..195ebea6c74 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp @@ -311,10 +311,6 @@ class HeapRegion: public G1ContiguousSpace { // for the collection set. double _predicted_elapsed_time_ms; - // The predicted number of bytes to copy that was added to - // the total value for the collection set. - size_t _predicted_bytes_to_copy; - public: HeapRegion(uint hrm_index, G1BlockOffsetTable* bot, @@ -554,9 +550,7 @@ class HeapRegion: public G1ContiguousSpace { // Notify the region that we have finished processing self-forwarded // objects during evac failure handling. - void note_self_forwarding_removal_end(bool during_initial_mark, - bool during_conc_mark, - size_t marked_bytes); + void note_self_forwarding_removal_end(size_t marked_bytes); // Returns "false" iff no object in the region was allocated when the // last mark phase ended. @@ -671,7 +665,6 @@ class HeapRegion: public G1ContiguousSpace { size_t recorded_rs_length() const { return _recorded_rs_length; } double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; } - size_t predicted_bytes_to_copy() const { return _predicted_bytes_to_copy; } void set_recorded_rs_length(size_t rs_length) { _recorded_rs_length = rs_length; @@ -681,10 +674,6 @@ class HeapRegion: public G1ContiguousSpace { _predicted_elapsed_time_ms = ms; } - void set_predicted_bytes_to_copy(size_t bytes) { - _predicted_bytes_to_copy = bytes; - } - virtual CompactibleSpace* next_compaction_space() const; virtual void reset_after_compaction(); From d93ba6ef1dffada47acae6d8a4ea0bda70ddaba0 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 24 Oct 2016 14:51:16 +0200 Subject: [PATCH 03/86] 8168542: os::realloc should return a valid pointer for input size=0 Reviewed-by: dholmes, cjplummer, dsamersoff, rehn --- hotspot/src/share/vm/runtime/os.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 47a7b5672a4..b48edb441fb 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -649,6 +649,12 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa return NULL; } + if (size == 0) { + // return a valid pointer if size is zero + // if NULL is returned the calling functions assume out of memory. + size = 1; + } + #ifndef ASSERT NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); @@ -669,9 +675,6 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa // NMT support void* membase = MemTracker::malloc_base(memblock); verify_memory(membase); - if (size == 0) { - return NULL; - } // always move the block void* ptr = os::malloc(size, memflags, stack); if (PrintMalloc && tty != NULL) { From 5ff4b1bb78fec394290c47dc3f12d035622f8c84 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Wed, 7 Dec 2016 13:51:20 +0100 Subject: [PATCH 04/86] 8171235: Move archive object code from G1MarkSweep into G1ArchiveAllocator Reviewed-by: tschatzl, kbarrett --- hotspot/src/share/vm/gc/g1/g1Allocator.cpp | 10 +++--- hotspot/src/share/vm/gc/g1/g1Allocator.hpp | 29 +++++++++++++-- .../src/share/vm/gc/g1/g1Allocator.inline.hpp | 35 ++++++++++++++++++- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 8 ++--- hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp | 6 ++-- hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp | 25 +------------ hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp | 28 ++------------- .../share/vm/gc/serial/markSweep.inline.hpp | 7 ++-- 8 files changed, 80 insertions(+), 68 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp index 92c00936dff..3f3aaeb9045 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "gc/g1/g1AllocRegion.inline.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1MarkSweep.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" @@ -333,11 +332,14 @@ void G1DefaultPLABAllocator::waste(size_t& wasted, size_t& undo_wasted) { } } +bool G1ArchiveAllocator::_archive_check_enabled = false; +G1ArchiveRegionMap G1ArchiveAllocator::_archive_region_map; + G1ArchiveAllocator* G1ArchiveAllocator::create_allocator(G1CollectedHeap* g1h) { // Create the archive allocator, and also enable archive object checking // in mark-sweep, since we will be creating archive regions. G1ArchiveAllocator* result = new G1ArchiveAllocator(g1h); - G1MarkSweep::enable_archive_object_check(); + enable_archive_object_check(); return result; } @@ -362,7 +364,7 @@ bool G1ArchiveAllocator::alloc_new_region() { _max = _bottom + HeapRegion::min_region_size_in_words(); // Tell mark-sweep that objects in this region are not to be marked. - G1MarkSweep::set_range_archive(MemRegion(_bottom, HeapRegion::GrainWords), true); + set_range_archive(MemRegion(_bottom, HeapRegion::GrainWords), true); // Since we've modified the old set, call update_sizes. _g1h->g1mm()->update_sizes(); diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp index e2db5c8dd0c..98942303287 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -312,12 +312,19 @@ public: virtual void waste(size_t& wasted, size_t& undo_wasted); }; +// G1ArchiveRegionMap is a boolean array used to mark G1 regions as +// archive regions. This allows a quick check for whether an object +// should not be marked because it is in an archive region. +class G1ArchiveRegionMap : public G1BiasedMappedArray { +protected: + bool default_value() const { return false; } +}; + // G1ArchiveAllocator is used to allocate memory in archive // regions. Such regions are not modifiable by GC, being neither // scavenged nor compacted, or even marked in the object header. // They can contain no pointers to non-archive heap regions, class G1ArchiveAllocator : public CHeapObj { - protected: G1CollectedHeap* _g1h; @@ -378,6 +385,24 @@ public: _summary_bytes_used = 0; } + // Create the _archive_region_map which is used to identify archive objects. + static inline void enable_archive_object_check(); + + // Set the regions containing the specified address range as archive/non-archive. + static inline void set_range_archive(MemRegion range, bool is_archive); + + static inline bool is_archive_object(oop object); + +private: + static bool _archive_check_enabled; + static G1ArchiveRegionMap _archive_region_map; + + // Check if an object is in an archive region using the _archive_region_map. + static inline bool in_archive_range(oop object); + + // Check if archive object checking is enabled, to avoid calling in_archive_range + // unnecessarily. + static inline bool archive_check_enabled(); }; #endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp index 3ca9451132a..6d27b007824 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -55,4 +55,37 @@ inline HeapWord* G1PLABAllocator::plab_allocate(InCSetState dest, } } +// Create the _archive_region_map which is used to identify archive objects. +inline void G1ArchiveAllocator::enable_archive_object_check() { + assert(!_archive_check_enabled, "archive range check already enabled"); + _archive_check_enabled = true; + size_t length = Universe::heap()->max_capacity(); + _archive_region_map.initialize((HeapWord*)Universe::heap()->base(), + (HeapWord*)Universe::heap()->base() + length, + HeapRegion::GrainBytes); +} + +// Set the regions containing the specified address range as archive/non-archive. +inline void G1ArchiveAllocator::set_range_archive(MemRegion range, bool is_archive) { + assert(_archive_check_enabled, "archive range check not enabled"); + _archive_region_map.set_by_address(range, is_archive); +} + +// Check if an object is in an archive region using the _archive_region_map. +inline bool G1ArchiveAllocator::in_archive_range(oop object) { + // This is the out-of-line part of is_archive_object test, done separately + // to avoid additional performance impact when the check is not enabled. + return _archive_region_map.get_by_address((HeapWord*)object); +} + +// Check if archive object checking is enabled, to avoid calling in_archive_range +// unnecessarily. +inline bool G1ArchiveAllocator::archive_check_enabled() { + return _archive_check_enabled; +} + +inline bool G1ArchiveAllocator::is_archive_object(oop object) { + return (archive_check_enabled() && in_archive_range(object)); +} + #endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index ba6b9fc0867..b30f9a512eb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -699,9 +699,9 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) { // when mmap'ing archived heap data in, so pre-touching is wasted. FlagSetting fs(AlwaysPreTouch, false); - // Enable archive object checking in G1MarkSweep. We have to let it know + // Enable archive object checking used by G1MarkSweep. We have to let it know // about each archive range, so that objects in those ranges aren't marked. - G1MarkSweep::enable_archive_object_check(); + G1ArchiveAllocator::enable_archive_object_check(); // For each specified MemRegion range, allocate the corresponding G1 // regions and mark them as archive regions. We expect the ranges in @@ -773,7 +773,7 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) { } // Notify mark-sweep of the archive range. - G1MarkSweep::set_range_archive(curr_range, true); + G1ArchiveAllocator::set_range_archive(curr_range, true); } return true; } @@ -924,7 +924,7 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) { } // Notify mark-sweep that this is no longer an archive range. - G1MarkSweep::set_range_archive(ranges[i], false); + G1ArchiveAllocator::set_range_archive(ranges[i], false); } if (uncommitted_regions != 0) { diff --git a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp index c3970d71991..e76a62ccab7 100644 --- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp +++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,10 @@ #include "precompiled.hpp" #include "logging/log.hpp" #include "gc/g1/concurrentMarkThread.hpp" +#include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" -#include "gc/g1/g1MarkSweep.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RemSet.hpp" #include "gc/g1/g1RootProcessor.hpp" @@ -239,7 +239,7 @@ public: template void do_oop_work(T *p) { oop obj = oopDesc::load_decode_heap_oop(p); - guarantee(obj == NULL || G1MarkSweep::in_archive_range(obj), + guarantee(obj == NULL || G1ArchiveAllocator::is_archive_object(obj), "Archive object at " PTR_FORMAT " references a non-archive object at " PTR_FORMAT, p2i(p), p2i(obj)); } diff --git a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp index 9834fbd8c7f..fc80f8803e4 100644 --- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -56,9 +56,6 @@ class HeapRegion; -bool G1MarkSweep::_archive_check_enabled = false; -G1ArchiveRegionMap G1MarkSweep::_archive_region_map; - void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); @@ -314,26 +311,6 @@ void G1MarkSweep::mark_sweep_phase4() { } -void G1MarkSweep::enable_archive_object_check() { - assert(!_archive_check_enabled, "archive range check already enabled"); - _archive_check_enabled = true; - size_t length = Universe::heap()->max_capacity(); - _archive_region_map.initialize((HeapWord*)Universe::heap()->base(), - (HeapWord*)Universe::heap()->base() + length, - HeapRegion::GrainBytes); -} - -void G1MarkSweep::set_range_archive(MemRegion range, bool is_archive) { - assert(_archive_check_enabled, "archive range check not enabled"); - _archive_region_map.set_by_address(range, is_archive); -} - -bool G1MarkSweep::in_archive_range(oop object) { - // This is the out-of-line part of is_archive_object test, done separately - // to avoid additional performance impact when the check is not enabled. - return _archive_region_map.get_by_address((HeapWord*)object); -} - void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); g1h->heap_region_iterate(blk); diff --git a/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp b/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp index a6dab8a4324..d7fae1aeee2 100644 --- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp +++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -55,23 +55,7 @@ class G1MarkSweep : AllStatic { static STWGCTimer* gc_timer() { return GenMarkSweep::_gc_timer; } static SerialOldTracer* gc_tracer() { return GenMarkSweep::_gc_tracer; } - // Create the _archive_region_map which is used to identify archive objects. - static void enable_archive_object_check(); - - // Set the regions containing the specified address range as archive/non-archive. - static void set_range_archive(MemRegion range, bool is_archive); - - // Check if an object is in an archive region using the _archive_region_map. - static bool in_archive_range(oop object); - - // Check if archive object checking is enabled, to avoid calling in_archive_range - // unnecessarily. - static bool archive_check_enabled() { return G1MarkSweep::_archive_check_enabled; } - - private: - static bool _archive_check_enabled; - static G1ArchiveRegionMap _archive_region_map; - +private: // Mark live objects static void mark_sweep_phase1(bool& marked_for_deopt, bool clear_all_softrefs); @@ -109,12 +93,4 @@ class G1PrepareCompactClosure : public HeapRegionClosure { bool doHeapRegion(HeapRegion* hr); }; -// G1ArchiveRegionMap is a boolean array used to mark G1 regions as -// archive regions. This allows a quick check for whether an object -// should not be marked because it is in an archive region. -class G1ArchiveRegionMap : public G1BiasedMappedArray { -protected: - bool default_value() const { return false; } -}; - #endif // SHARE_VM_GC_G1_G1MARKSWEEP_HPP diff --git a/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp b/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp index 8b968a0caff..0ae30ff2647 100644 --- a/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp +++ b/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,12 @@ #include "oops/markOop.inline.hpp" #include "oops/oop.inline.hpp" #if INCLUDE_ALL_GCS -#include "gc/g1/g1MarkSweep.hpp" +#include "gc/g1/g1Allocator.inline.hpp" #endif // INCLUDE_ALL_GCS inline bool MarkSweep::is_archive_object(oop object) { #if INCLUDE_ALL_GCS - return (G1MarkSweep::archive_check_enabled() && - G1MarkSweep::in_archive_range(object)); + return G1ArchiveAllocator::is_archive_object(object); #else return false; #endif From 5c5e21df9ff7201ed47d7e2a2a064410a2f3fa7d Mon Sep 17 00:00:00 2001 From: Lutz Schmidt Date: Fri, 20 Jan 2017 15:17:46 +0100 Subject: [PATCH 05/86] 8175267: [s390] cleanup stub code "handler_for_unsafe_access" Reviewed-by: dholmes, goetz, mdoerr --- .../src/cpu/s390/vm/stubGenerator_s390.cpp | 22 ------------------- hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp | 2 -- hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp | 4 ---- 3 files changed, 28 deletions(-) diff --git a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp index 8b872c5c922..63cc18c6801 100644 --- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp @@ -623,26 +623,6 @@ class StubGenerator: public StubCodeGenerator { #define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)-> #endif - //---------------------------------------------------------------------- - // The following routine generates a subroutine to throw an asynchronous - // UnknownError when an unsafe access gets a fault that could not be - // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.) - // - // Arguments: - // trapping PC: ?? - // - // Results: - // Posts an asynchronous exception, skips the trapping instruction. - // - address generate_handler_for_unsafe_access() { - StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access"); - { - address start = __ pc(); - __ unimplemented("StubRoutines::handler_for_unsafe_access", 86); - return start; - } - } - // Support for uint StubRoutine::zarch::partial_subtype_check(Klass // sub, Klass super); // @@ -2462,8 +2442,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::zarch::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); - // Support for verify_oop (must happen after universe_init). StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine(); diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp index 8c60ae04350..e99eb48035a 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp @@ -33,8 +33,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::zarch::_handler_for_unsafe_access_entry = NULL; - address StubRoutines::zarch::_partial_subtype_check = NULL; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp index 5bb64303b6b..d33cf9cfc7a 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp @@ -68,8 +68,6 @@ class zarch { }; private: - static address _handler_for_unsafe_access_entry; - static int _atomic_memory_operation_lock; static address _partial_subtype_check; @@ -91,8 +89,6 @@ class zarch { static int atomic_memory_operation_lock() { return _atomic_memory_operation_lock; } static void set_atomic_memory_operation_lock(int value) { _atomic_memory_operation_lock = value; } - static address handler_for_unsafe_access_entry() { return _handler_for_unsafe_access_entry; } - static address partial_subtype_check() { return _partial_subtype_check; } static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); From fd7b59965683bbc78af54c34815bfbddd61d4c6a Mon Sep 17 00:00:00 2001 From: Lutz Schmidt Date: Fri, 20 Jan 2017 16:53:50 +0100 Subject: [PATCH 06/86] 8175269: [s390] cleanup calls to vtable_start_offset() and vtable_length_offset() Reviewed-by: dholmes, mdoerr --- hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp | 4 ++-- hotspot/src/cpu/s390/vm/templateTable_s390.cpp | 2 +- hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp index 015bccc2aa3..71926a36b45 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -2726,11 +2726,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, BLOCK_COMMENT("lookup_interface_method {"); // Load start of itable entries into itable_entry_addr. - z_llgf(vtable_len, Address(recv_klass, InstanceKlass::vtable_length_offset())); + z_llgf(vtable_len, Address(recv_klass, Klass::vtable_length_offset())); z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), diff --git a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp index 83d707dbd60..c5a6a6fe796 100644 --- a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp @@ -3466,7 +3466,7 @@ void TemplateTable::invokevirtual_helper(Register index, __ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes())); __ mem2reg_opt(method, Address(Z_tmp_2, index, - InstanceKlass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); + Klass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); __ profile_arguments_type(Z_ARG4, method, Z_ARG5, true); __ jump_from_interpreted(method, Z_ARG4); BLOCK_COMMENT("} invokevirtual_helper"); diff --git a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp index c2c3ab246b8..de0a351ea04 100644 --- a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp @@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Set method (in case of interpreted method), and destination address. - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index * vtableEntry::size_in_bytes(); #ifndef PRODUCT @@ -96,8 +96,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // worst case actual size padding_bytes += __ load_const_size() - __ load_const_optimized_rtn_len(vtable_idx, vtable_index*vtableEntry::size_in_bytes(), true); - assert(Immediate::is_uimm12(in_bytes(InstanceKlass::vtable_length_offset())), "disp to large"); - __ z_cl(vtable_idx, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + assert(Immediate::is_uimm12(in_bytes(Klass::vtable_length_offset())), "disp to large"); + __ z_cl(vtable_idx, in_bytes(Klass::vtable_length_offset()), rcvr_klass); __ z_brl(L); __ z_lghi(Z_ARG3, vtable_index); // Debug code, don't optimize. __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), Z_ARG1, Z_ARG3, false); @@ -187,11 +187,11 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Load start of itable entries into itable_entry. - __ z_llgf(vtable_len, Address(rcvr_klass, InstanceKlass::vtable_length_offset())); + __ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset())); __ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); // Count unused bytes. start_pc = __ pc(); __ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len); From 5a06c219785cb07b8c870ff6358e34f7d70b1410 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 14 Feb 2017 19:16:46 -0800 Subject: [PATCH 07/86] 8172286: CodeCacheFlushing message should be shown in UL Reviewed-by: kvn --- hotspot/src/share/vm/code/codeCache.cpp | 27 ++++++++++++++++++++---- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/sweeper.cpp | 7 ++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 80ce54f847e..eabd87598c9 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -1309,6 +1309,8 @@ void CodeCache::verify() { } // A CodeHeap is full. Print out warning and report event. +PRAGMA_DIAG_PUSH +PRAGMA_FORMAT_NONLITERAL_IGNORED void CodeCache::report_codemem_full(int code_blob_type, bool print) { // Get nmethod heap for the given CodeBlobType and build CodeCacheFull event CodeHeap* heap = get_code_heap(code_blob_type); @@ -1317,11 +1319,27 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { if ((heap->full_count() == 0) || print) { // Not yet reported for this heap, report if (SegmentedCodeCache) { - warning("%s is full. Compiler has been disabled.", get_code_heap_name(code_blob_type)); - warning("Try increasing the code heap size using -XX:%s=", get_code_heap_flag_name(code_blob_type)); + ResourceMark rm; + stringStream msg1_stream, msg2_stream; + msg1_stream.print("%s is full. Compiler has been disabled.", + get_code_heap_name(code_blob_type)); + msg2_stream.print("Try increasing the code heap size using -XX:%s=", + get_code_heap_flag_name(code_blob_type)); + const char *msg1 = msg1_stream.as_string(); + const char *msg2 = msg2_stream.as_string(); + + log_warning(codecache)(msg1); + log_warning(codecache)(msg2); + warning(msg1); + warning(msg2); } else { - warning("CodeCache is full. Compiler has been disabled."); - warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); + const char *msg1 = "CodeCache is full. Compiler has been disabled."; + const char *msg2 = "Try increasing the code cache size using -XX:ReservedCodeCacheSize="; + + log_warning(codecache)(msg1); + log_warning(codecache)(msg2); + warning(msg1); + warning(msg2); } ResourceMark rm; stringStream s; @@ -1350,6 +1368,7 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { event.commit(); } } +PRAGMA_DIAG_POP void CodeCache::print_memory_overhead() { size_t wasted_bytes = 0; diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index e262d074cfa..e424a231534 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -48,6 +48,7 @@ LOG_TAG(class) \ LOG_TAG(classhisto) \ LOG_TAG(cleanup) \ + LOG_TAG(codecache) \ LOG_TAG(compaction) \ LOG_TAG(constraints) \ LOG_TAG(constantpool) \ diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index 8dad9129aa0..212f23e245f 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -403,6 +403,8 @@ void NMethodSweeper::sweep_code_cache() { ResourceMark rm; Ticks sweep_start_counter = Ticks::now(); + log_debug(codecache, sweep, start)("CodeCache flushing"); + int flushed_count = 0; int zombified_count = 0; int flushed_c2_count = 0; @@ -500,6 +502,10 @@ void NMethodSweeper::sweep_code_cache() { } #endif + Log(codecache, sweep) log; + if (log.is_debug()) { + CodeCache::print_summary(log.debug_stream(), false); + } log_sweep("finished"); // Sweeper is the only case where memory is released, check here if it @@ -513,6 +519,7 @@ void NMethodSweeper::sweep_code_cache() { // cache. As a result, 'freed_memory' > 0 to restart the compiler. if (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0)) { CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation); + log.debug("restart compiler"); log_sweep("restart_compiler"); } } From b1171ce431da385d64834e6b853c665bb49957d8 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 14 Feb 2017 20:00:28 -0800 Subject: [PATCH 08/86] 8172285: UL support for PrintCompilation Reviewed-by: kvn --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 2 + hotspot/src/share/vm/code/nmethod.cpp | 5 +- .../src/share/vm/compiler/compileBroker.cpp | 1 + hotspot/src/share/vm/compiler/compileTask.hpp | 22 ++++++ hotspot/src/share/vm/logging/logTag.hpp | 3 + hotspot/src/share/vm/opto/bytecodeInfo.cpp | 2 + hotspot/src/share/vm/opto/library_call.cpp | 74 ++++++++++++------- .../src/share/vm/runtime/sharedRuntime.cpp | 4 +- 8 files changed, 85 insertions(+), 28 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 75a4f8aa3de..84a1f98d42d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -4289,6 +4289,8 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes } #endif // INCLUDE_TRACE + CompileTask::print_inlining_ul(callee, scope()->level(), bci(), msg); + if (!compilation()->directive()->PrintInliningOption) { return; } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 71420040970..94ba6ae803f 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1134,8 +1134,11 @@ void nmethod::log_state_change() const { xtty->end_elem(); } } + + const char *state_msg = _state == zombie ? "made zombie" : "made not entrant"; + CompileTask::print_ul(this, state_msg); if (PrintCompilation && _state != unloaded) { - print_on(tty, _state == zombie ? "made zombie" : "made not entrant"); + print_on(tty, state_msg); } } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 62433c1c088..6ebb3362726 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1765,6 +1765,7 @@ CompilerDirectives* DirectivesStack::_bottom = NULL; // Compile a method. // void CompileBroker::invoke_compiler_on_method(CompileTask* task) { + task->print_ul(); if (PrintCompilation) { ResourceMark rm; task->print_tty(); diff --git a/hotspot/src/share/vm/compiler/compileTask.hpp b/hotspot/src/share/vm/compiler/compileTask.hpp index 2a5da508b8a..6b0a81205cc 100644 --- a/hotspot/src/share/vm/compiler/compileTask.hpp +++ b/hotspot/src/share/vm/compiler/compileTask.hpp @@ -180,11 +180,27 @@ private: public: void print(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true); + void print_ul(const char* msg = NULL){ + Log(jit, compilation) log; + if (log.is_debug()) { + print(log.debug_stream(), msg, /* short form */ true, /* cr */ true); + } + } static void print(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) { print_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, msg, short_form, cr); } + static void print_ul(const nmethod* nm, const char* msg = NULL) { + Log(jit, compilation) log; + if (log.is_debug()) { + print_impl(log.debug_stream(), nm->method(), nm->compile_id(), + nm->comp_level(), nm->is_osr_method(), + nm->is_osr_method() ? nm->osr_entry_bci() : -1, + /*is_blocking*/ false, + msg, /* short form */ true, /* cr */ true); + } + } static void print_inline_indent(int inline_level, outputStream* st = tty); @@ -206,6 +222,12 @@ public: static void print_inlining_tty(ciMethod* method, int inline_level, int bci, const char* msg = NULL) { print_inlining_inner(tty, method, inline_level, bci, msg); } + static void print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg = NULL) { + Log(jit, inlining) log; + if (log.is_debug()) { + print_inlining_inner(log.debug_stream(), method, inline_level, bci, msg); + } + } }; #endif // SHARE_VM_COMPILER_COMPILETASK_HPP diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index e424a231534..bcedd8457d1 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -50,6 +50,7 @@ LOG_TAG(cleanup) \ LOG_TAG(codecache) \ LOG_TAG(compaction) \ + LOG_TAG(compilation) \ LOG_TAG(constraints) \ LOG_TAG(constantpool) \ LOG_TAG(coops) \ @@ -70,7 +71,9 @@ LOG_TAG(ihop) \ LOG_TAG(iklass) \ LOG_TAG(init) \ + LOG_TAG(inlining) \ LOG_TAG(itables) \ + LOG_TAG(jit) \ LOG_TAG(jni) \ LOG_TAG(jvmti) \ LOG_TAG(liveness) \ diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 4c5ee040585..8071d76b95c 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -496,6 +496,8 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, C->log()->inline_fail(inline_msg); } } + CompileTask::print_inlining_ul(callee_method, inline_level(), + caller_bci, inline_msg); if (C->print_inlining()) { C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg); if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index c298e318ab5..de2bdb465b7 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -387,8 +387,11 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { // Try to inline the intrinsic. if ((CheckIntrinsics ? callee->intrinsic_candidate() : true) && kit.try_to_inline(_last_predicate)) { + const char *inline_msg = is_virtual() ? "(intrinsic, virtual)" + : "(intrinsic)"; + CompileTask::print_inlining_ul(callee, jvms->depth() - 1, bci, inline_msg); if (C->print_intrinsics() || C->print_inlining()) { - C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); + C->print_inlining(callee, jvms->depth() - 1, bci, inline_msg); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); if (C->log()) { @@ -404,22 +407,30 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { } // The intrinsic bailed out - if (C->print_intrinsics() || C->print_inlining()) { - if (jvms->has_method()) { - // Not a root compile. - const char* msg; - if (callee->intrinsic_candidate()) { - msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; - } else { - msg = is_virtual() ? "failed to inline (intrinsic, virtual), method not annotated" - : "failed to inline (intrinsic), method not annotated"; - } - C->print_inlining(callee, jvms->depth() - 1, bci, msg); + if (jvms->has_method()) { + // Not a root compile. + const char* msg; + if (callee->intrinsic_candidate()) { + msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; } else { - // Root compile - tty->print("Did not generate intrinsic %s%s at bci:%d in", - vmIntrinsics::name_at(intrinsic_id()), - (is_virtual() ? " (virtual)" : ""), bci); + msg = is_virtual() ? "failed to inline (intrinsic, virtual), method not annotated" + : "failed to inline (intrinsic), method not annotated"; + } + CompileTask::print_inlining_ul(callee, jvms->depth() - 1, bci, msg); + if (C->print_intrinsics() || C->print_inlining()) { + C->print_inlining(callee, jvms->depth() - 1, bci, msg); + } + } else { + // Root compile + ResourceMark rm; + stringStream msg_stream; + msg_stream.print("Did not generate intrinsic %s%s at bci:%d in", + vmIntrinsics::name_at(intrinsic_id()), + is_virtual() ? " (virtual)" : "", bci); + const char *msg = msg_stream.as_string(); + log_debug(jit, inlining)("%s", msg); + if (C->print_intrinsics() || C->print_inlining()) { + tty->print("%s", msg); } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); @@ -445,8 +456,11 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) { Node* slow_ctl = kit.try_to_predicate(predicate); if (!kit.failing()) { + const char *inline_msg = is_virtual() ? "(intrinsic, virtual, predicate)" + : "(intrinsic, predicate)"; + CompileTask::print_inlining_ul(callee, jvms->depth() - 1, bci, inline_msg); if (C->print_intrinsics() || C->print_inlining()) { - C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual, predicate)" : "(intrinsic, predicate)"); + C->print_inlining(callee, jvms->depth() - 1, bci, inline_msg); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); if (C->log()) { @@ -459,16 +473,24 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) { } // The intrinsic bailed out - if (C->print_intrinsics() || C->print_inlining()) { - if (jvms->has_method()) { - // Not a root compile. - const char* msg = "failed to generate predicate for intrinsic"; + if (jvms->has_method()) { + // Not a root compile. + const char* msg = "failed to generate predicate for intrinsic"; + CompileTask::print_inlining_ul(kit.callee(), jvms->depth() - 1, bci, msg); + if (C->print_intrinsics() || C->print_inlining()) { C->print_inlining(kit.callee(), jvms->depth() - 1, bci, msg); - } else { - // Root compile - C->print_inlining_stream()->print("Did not generate predicate for intrinsic %s%s at bci:%d in", - vmIntrinsics::name_at(intrinsic_id()), - (is_virtual() ? " (virtual)" : ""), bci); + } + } else { + // Root compile + ResourceMark rm; + stringStream msg_stream; + msg_stream.print("Did not generate intrinsic %s%s at bci:%d in", + vmIntrinsics::name_at(intrinsic_id()), + is_virtual() ? " (virtual)" : "", bci); + const char *msg = msg_stream.as_string(); + log_debug(jit, inlining)("%s", msg); + if (C->print_intrinsics() || C->print_inlining()) { + C->print_inlining_stream()->print("%s", msg); } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index c854e4ad84f..afd8c1d5d32 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -2891,9 +2891,11 @@ void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) { // Install the generated code. if (nm != NULL) { + const char *msg = method->is_static() ? "(static)" : ""; + CompileTask::print_ul(nm, msg); if (PrintCompilation) { ttyLocker ttyl; - CompileTask::print(tty, nm, method->is_static() ? "(static)" : ""); + CompileTask::print(tty, nm, msg); } nm->post_compiled_method_load_event(); } From 0b3bc5c4f0cb470b00e297718e86debbc3ba0912 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 15 Feb 2017 22:59:57 -0500 Subject: [PATCH 09/86] 8169881: Remove implicit Handle conversions oop->Handle Pass THREAD to Handle as argument instead of implicit Thread::current() call. Reviewed-by: dholmes, sspitsyn --- .../aarch64/vm/jvmciCodeInstaller_aarch64.cpp | 4 +- .../cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp | 4 +- .../src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp | 4 +- hotspot/src/share/vm/aot/aotCodeHeap.cpp | 4 +- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 6 +- hotspot/src/share/vm/ci/ciEnv.cpp | 2 +- hotspot/src/share/vm/ci/ciInstance.cpp | 6 +- hotspot/src/share/vm/ci/ciObject.cpp | 5 +- hotspot/src/share/vm/ci/ciObjectFactory.cpp | 4 +- .../share/vm/classfile/classFileParser.cpp | 11 +- .../src/share/vm/classfile/classLoader.cpp | 4 +- .../share/vm/classfile/classLoaderData.cpp | 12 +- .../share/vm/classfile/classLoaderData.hpp | 4 +- hotspot/src/share/vm/classfile/dictionary.cpp | 4 +- .../src/share/vm/classfile/javaClasses.cpp | 44 ++--- .../src/share/vm/classfile/javaClasses.hpp | 6 +- .../src/share/vm/classfile/moduleEntry.cpp | 8 +- hotspot/src/share/vm/classfile/modules.cpp | 8 +- .../src/share/vm/classfile/stringTable.cpp | 3 +- .../share/vm/classfile/systemDictionary.cpp | 60 ++++--- .../share/vm/classfile/systemDictionary.hpp | 6 +- .../share/vm/classfile/verificationType.cpp | 3 +- hotspot/src/share/vm/classfile/verifier.cpp | 5 +- hotspot/src/share/vm/code/codeBlob.cpp | 3 +- hotspot/src/share/vm/code/debugInfo.cpp | 4 +- hotspot/src/share/vm/code/debugInfo.hpp | 5 +- hotspot/src/share/vm/code/dependencies.cpp | 9 +- hotspot/src/share/vm/compiler/compileTask.cpp | 7 +- .../src/share/vm/jvmci/jvmciCodeInstaller.cpp | 160 ++++++++++-------- .../src/share/vm/jvmci/jvmciCodeInstaller.hpp | 14 +- hotspot/src/share/vm/jvmci/jvmciCompiler.cpp | 9 +- hotspot/src/share/vm/jvmci/jvmciCompiler.hpp | 4 +- .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 92 +++++----- .../src/share/vm/jvmci/jvmciCompilerToVM.hpp | 6 +- hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 12 +- hotspot/src/share/vm/jvmci/jvmciRuntime.hpp | 4 +- hotspot/src/share/vm/memory/oopFactory.cpp | 10 ++ hotspot/src/share/vm/memory/oopFactory.hpp | 4 + hotspot/src/share/vm/memory/universe.cpp | 14 +- hotspot/src/share/vm/oops/arrayKlass.cpp | 4 +- hotspot/src/share/vm/oops/cpCache.cpp | 4 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 36 ++-- hotspot/src/share/vm/oops/klass.cpp | 4 +- hotspot/src/share/vm/oops/oop.cpp | 7 +- hotspot/src/share/vm/prims/jvm.cpp | 8 +- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 24 +-- .../share/vm/prims/jvmtiGetLoadedClasses.cpp | 17 +- hotspot/src/share/vm/prims/jvmtiImpl.cpp | 6 +- .../src/share/vm/prims/jvmtiThreadState.hpp | 4 +- hotspot/src/share/vm/prims/methodHandles.cpp | 16 +- hotspot/src/share/vm/prims/stackwalk.cpp | 4 +- hotspot/src/share/vm/prims/whitebox.cpp | 8 +- .../src/share/vm/runtime/deoptimization.cpp | 10 +- hotspot/src/share/vm/runtime/handles.cpp | 11 +- hotspot/src/share/vm/runtime/handles.hpp | 18 +- .../src/share/vm/runtime/handles.inline.hpp | 13 +- hotspot/src/share/vm/runtime/java.cpp | 5 +- hotspot/src/share/vm/runtime/stackValue.cpp | 6 +- hotspot/src/share/vm/runtime/synchronizer.cpp | 4 +- hotspot/src/share/vm/runtime/vframe.cpp | 13 +- hotspot/src/share/vm/runtime/vframe_hp.cpp | 6 +- hotspot/src/share/vm/services/gcNotifier.cpp | 4 +- hotspot/src/share/vm/services/management.cpp | 5 +- .../src/share/vm/services/threadService.cpp | 4 +- hotspot/src/share/vm/utilities/exceptions.cpp | 6 +- 65 files changed, 424 insertions(+), 397 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index f9cc50fe4d0..bebd5ae8ca9 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -55,7 +55,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) } } #endif // ASSERT - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); MacroAssembler::patch_oop(pc, (address)obj()); int oop_index = _oop_recorder->find_index(value); diff --git a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp index 4976e1686b2..5fb5b1cc8b9 100644 --- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -44,7 +44,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { #ifdef _LP64 diff --git a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp index e2ddb71aa9d..acb7034684e 100644 --- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp +++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -65,7 +65,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { #ifdef _LP64 diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.cpp b/hotspot/src/share/vm/aot/aotCodeHeap.cpp index 97f5c960f68..8d38edc686c 100644 --- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp +++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp @@ -595,9 +595,9 @@ Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char* memcpy(&meta_name[klass_len + 1 + method_name_len], signature_name, signature_name_len); meta_name[klass_len + 1 + method_name_len + signature_name_len] = '\0'; Handle exception = Exceptions::new_exception(thread, vmSymbols::java_lang_NoSuchMethodError(), meta_name); - java_lang_Throwable::print(exception, tty); + java_lang_Throwable::print(exception(), tty); tty->cr(); - java_lang_Throwable::print_stack_trace(exception(), tty); + java_lang_Throwable::print_stack_trace(exception, tty); tty->cr(); fatal("Failed to find method '%s'", meta_name); } diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 3cb9aaf0d94..e353b2f7544 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -961,13 +961,13 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i assert(cache_index >= 0 && cache_index < pool->cache()->length(), "unexpected cache index"); ConstantPoolCacheEntry* cpce = pool->cache()->entry_at(cache_index); cpce->set_method_handle(pool, info); - appendix = cpce->appendix_if_resolved(pool); // just in case somebody already resolved the entry + appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry break; } case Bytecodes::_invokedynamic: { ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index); cpce->set_dynamic_call(pool, info); - appendix = cpce->appendix_if_resolved(pool); // just in case somebody already resolved the entry + appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry break; } default: fatal("unexpected bytecode for load_appendix_patching_id"); diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index fce88ba51c4..aaac0a1e96f 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -276,7 +276,7 @@ ciInstance* ciEnv::get_or_create_exception(jobject& handle, Symbol* name) { if (!HAS_PENDING_EXCEPTION && k != NULL) { oop obj = InstanceKlass::cast(k)->allocate_instance(THREAD); if (!HAS_PENDING_EXCEPTION) - objh = JNIHandles::make_global(obj); + objh = JNIHandles::make_global(Handle(THREAD, obj)); } if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; diff --git a/hotspot/src/share/vm/ci/ciInstance.cpp b/hotspot/src/share/vm/ci/ciInstance.cpp index d2073abdbf1..08d631b8d1c 100644 --- a/hotspot/src/share/vm/ci/ciInstance.cpp +++ b/hotspot/src/share/vm/ci/ciInstance.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -58,8 +58,8 @@ ciType* ciInstance::java_mirror_type() { // ------------------------------------------------------------------ // ciInstance::field_value_impl ciConstant ciInstance::field_value_impl(BasicType field_btype, int offset) { - Handle obj = get_oop(); - assert(!obj.is_null(), "bad oop"); + oop obj = get_oop(); + assert(obj != NULL, "bad oop"); switch(field_btype) { case T_BYTE: return ciConstant(field_btype, obj->byte_field(offset)); case T_CHAR: return ciConstant(field_btype, obj->char_field(offset)); diff --git a/hotspot/src/share/vm/ci/ciObject.cpp b/hotspot/src/share/vm/ci/ciObject.cpp index 2b09567cfca..23f4b0f2fdf 100644 --- a/hotspot/src/share/vm/ci/ciObject.cpp +++ b/hotspot/src/share/vm/ci/ciObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -54,7 +54,8 @@ ciObject::ciObject(oop o) { if (ciObjectFactory::is_initialized()) { _handle = JNIHandles::make_local(o); } else { - _handle = JNIHandles::make_global(o); + Handle obj(Thread::current(), o); + _handle = JNIHandles::make_global(obj); } _klass = NULL; init_flags_from(o); diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index bcb7540a3e9..50ab44ebb0d 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -249,7 +249,7 @@ ciObject* ciObjectFactory::get(oop key) { // The ciObject does not yet exist. Create it and insert it // into the cache. - Handle keyHandle(key); + Handle keyHandle(Thread::current(), key); ciObject* new_object = create_new_object(keyHandle()); assert(keyHandle() == new_object->get_oop(), "must be properly recorded"); init_ident_of(new_object); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 87b593eb690..57f4c863126 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -834,7 +834,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, const Klass* const k = SystemDictionary::resolve_super_or_fail(_class_name, unresolved_klass, - _loader_data->class_loader(), + Handle(THREAD, _loader_data->class_loader()), _protection_domain, false, CHECK); @@ -2851,7 +2851,6 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs, NULL, CHECK); - HandleMark hm(THREAD); for (int index = 0; index < length; index++) { Method* method = parse_method(cfs, is_interface, @@ -5357,7 +5356,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa // Allocate mirror and initialize static fields // The create_mirror() call will also call compute_modifiers() java_lang_Class::create_mirror(ik, - _loader_data->class_loader(), + Handle(THREAD, _loader_data->class_loader()), module_handle, _protection_domain, CHECK); @@ -5915,10 +5914,11 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st "Interfaces must have java.lang.Object as superclass in class file %s", CHECK); } + Handle loader(THREAD, _loader_data->class_loader()); _super_klass = (const InstanceKlass*) SystemDictionary::resolve_super_or_fail(_class_name, super_class_name, - _loader_data->class_loader(), + loader, _protection_domain, true, CHECK); @@ -5960,6 +5960,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st _all_mirandas = new GrowableArray(20); + Handle loader(THREAD, _loader_data->class_loader()); klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size, &_num_miranda_methods, _all_mirandas, @@ -5967,7 +5968,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st _methods, _access_flags, _major_version, - _loader_data->class_loader(), + loader, _class_name, _local_interfaces, CHECK); diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index e0b7c84e45b..2b5a1036402 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1715,7 +1715,7 @@ void ClassLoader::create_javabase() { { MutexLocker ml(Module_lock, THREAD); - ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(NULL), vmSymbols::java_base(), NULL, NULL, null_cld); + ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(), vmSymbols::java_base(), NULL, NULL, null_cld); if (jb_module == NULL) { vm_exit_during_initialization("Unable to create ModuleEntry for " JAVA_BASE_NAME); } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index fbafa936950..9f11cf5c965 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -522,10 +522,9 @@ bool ClassLoaderData::is_platform_class_loader_data() const { // (boot, application/system or platform) class loaders. Note, the // builtin loaders are not freed by a GC. bool ClassLoaderData::is_builtin_class_loader_data() const { - Handle classLoaderHandle = class_loader(); return (is_the_null_class_loader_data() || - SystemDictionary::is_system_class_loader(classLoaderHandle) || - SystemDictionary::is_platform_class_loader(classLoaderHandle)); + SystemDictionary::is_system_class_loader(class_loader()) || + SystemDictionary::is_platform_class_loader(class_loader())); } Metaspace* ClassLoaderData::metaspace_non_null() { @@ -627,7 +626,8 @@ void ClassLoaderData::free_deallocate_list() { // These anonymous class loaders are to contain classes used for JSR292 ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) { // Add a new class loader data to the graph. - return ClassLoaderDataGraph::add(loader, true, THREAD); + Handle lh(THREAD, loader); + return ClassLoaderDataGraph::add(lh, true, THREAD); } const char* ClassLoaderData::loader_name() { @@ -768,7 +768,7 @@ void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRA vmSymbols::void_string_signature(), CHECK); assert(result.get_type() == T_OBJECT, "just checking"); - string = (oop)result.get_jobject(); + string = Handle(THREAD, (oop)result.get_jobject()); } ResourceMark rm; diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index b69c4e681d4..94272e8055f 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -263,7 +263,7 @@ class ClassLoaderData : public CHeapObj { assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice"); // We explicitly initialize the Dependencies object at a later phase in the initialization - _the_null_class_loader_data = new ClassLoaderData((oop)NULL, false, Dependencies()); + _the_null_class_loader_data = new ClassLoaderData(Handle(), false, Dependencies()); ClassLoaderDataGraph::_head = _the_null_class_loader_data; assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be"); if (DumpSharedSpaces) { diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 5bb666d730c..eda1531ee74 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -731,7 +731,6 @@ void SymbolPropertyTable::methods_do(void f(Method*)) { void Dictionary::print(bool details) { ResourceMark rm; - HandleMark hm; if (details) { tty->print_cr("Java system dictionary (table_size=%d, classes=%d)", @@ -777,7 +776,6 @@ void Dictionary::print(bool details) { void Dictionary::printPerformanceInfoDetails() { if (log_is_enabled(Info, hashtables)) { ResourceMark rm; - HandleMark hm; log_info(hashtables)(" "); log_info(hashtables)("Java system dictionary (table_size=%d, classes=%d)", diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 0bd1aa5c836..6f6a54be81c 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -514,11 +514,10 @@ char* java_lang_String::as_quoted_ascii(oop java_string) { return result; } -Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) { - oop obj = java_string(); - typeArrayOop value = java_lang_String::value(obj); - int length = java_lang_String::length(obj); - bool is_latin1 = java_lang_String::is_latin1(obj); +Symbol* java_lang_String::as_symbol(oop java_string, TRAPS) { + typeArrayOop value = java_lang_String::value(java_string); + int length = java_lang_String::length(java_string); + bool is_latin1 = java_lang_String::is_latin1(java_string); if (!is_latin1) { jchar* base = (length == 0) ? NULL : value->char_at_addr(0); Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD); @@ -753,7 +752,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { } } } - create_mirror(k, Handle(NULL), Handle(NULL), Handle(NULL), CHECK); + create_mirror(k, Handle(), Handle(), Handle(), CHECK); } void java_lang_Class::initialize_mirror_fields(KlassHandle k, @@ -828,7 +827,8 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, // the mirror. if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) - Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK); + oop mirror_oop = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK); + Handle mirror(THREAD, mirror_oop); // Setup indirection from mirror->klass if (!k.is_null()) { @@ -842,7 +842,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, // It might also have a component mirror. This mirror must already exist. if (k->is_array_klass()) { - Handle comp_mirror; + oop comp_mirror; if (k->is_typeArray_klass()) { BasicType type = TypeArrayKlass::cast(k())->element_type(); comp_mirror = Universe::java_mirror(type); @@ -852,12 +852,12 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, assert(element_klass != NULL, "Must have an element klass"); comp_mirror = element_klass->java_mirror(); } - assert(comp_mirror.not_null(), "must have a mirror"); + assert(comp_mirror != NULL, "must have a mirror"); // Two-way link between the array klass and its component mirror: // (array_klass) k -> mirror -> component_mirror -> array_klass -> k - set_component_mirror(mirror(), comp_mirror()); - set_array_klass(comp_mirror(), k()); + set_component_mirror(mirror(), comp_mirror); + set_array_klass(comp_mirror, k()); } else { assert(k->is_instance_klass(), "Must be"); @@ -1518,7 +1518,7 @@ void java_lang_Throwable::set_depth(oop throwable, int value) { throwable->int_field_put(depth_offset, value); } -oop java_lang_Throwable::message(Handle throwable) { +oop java_lang_Throwable::message(oop throwable) { return throwable->obj_field(detailMessage_offset); } @@ -1547,7 +1547,7 @@ void java_lang_Throwable::clear_stacktrace(oop throwable) { } -void java_lang_Throwable::print(Handle throwable, outputStream* st) { +void java_lang_Throwable::print(oop throwable, outputStream* st) { ResourceMark rm; Klass* k = throwable->klass(); assert(k != NULL, "just checking"); @@ -1619,11 +1619,11 @@ class BacktraceBuilder: public StackObj { // constructor for new backtrace BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) { expand(CHECK); - _backtrace = _head; + _backtrace = Handle(THREAD, _head); _index = 0; } - BacktraceBuilder(objArrayHandle backtrace) { + BacktraceBuilder(Thread* thread, objArrayHandle backtrace) { _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); @@ -1634,7 +1634,8 @@ class BacktraceBuilder: public StackObj { "method and source information arrays should match"); // head is the preallocated backtrace - _backtrace = _head = backtrace(); + _head = backtrace(); + _backtrace = Handle(thread, _head); _index = 0; } @@ -1840,7 +1841,7 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { - Handle mirror = method->method_holder()->java_mirror(); + Handle mirror (Thread::current(), method->method_holder()->java_mirror()); int method_id = method->orig_method_idnum(); int version = method->constants()->version(); print_stack_element_to_stream(st, mirror, method_id, version, bci, method->name()); @@ -1852,7 +1853,7 @@ void java_lang_Throwable::print_stack_element(outputStream *st, const methodHand */ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) { // First, print the message. - print(throwable, st); + print(throwable(), st); st->cr(); // Now print the stack trace. @@ -1887,7 +1888,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) throwable = Handle(THREAD, (oop) cause.get_jobject()); if (throwable.not_null()) { st->print("Caused by: "); - print(throwable, st); + print(throwable(), st); st->cr(); } } @@ -2091,7 +2092,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t ResourceMark rm(THREAD); vframeStream st(THREAD); - BacktraceBuilder bt(backtrace); + BacktraceBuilder bt(THREAD, backtrace); // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init // methods as preallocated errors aren't created by "java" code. @@ -2230,7 +2231,7 @@ Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* h void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) { // set Method* or mid/cpref - oop mname = stackFrame->obj_field(_memberName_offset); + Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset)); InstanceKlass* ik = method->method_holder(); CallInfo info(method(), ik); MethodHandles::init_method_MemberName(mname, info); @@ -3958,7 +3959,6 @@ bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, void JavaClasses::check_offsets() { bool valid = true; - HandleMark hm; #define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig) diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 67b4a2e8ac0..10c1db85d81 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -164,7 +164,7 @@ class java_lang_String : AllStatic { static Handle internalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '.', '/', THREAD); } // Conversion - static Symbol* as_symbol(Handle java_string, TRAPS); + static Symbol* as_symbol(oop java_string, TRAPS); static Symbol* as_symbol_or_null(oop java_string); // Testers @@ -494,7 +494,7 @@ class java_lang_Throwable: AllStatic { static int get_backtrace_offset() { return backtrace_offset;} static int get_detailMessage_offset() { return detailMessage_offset;} // Message - static oop message(Handle throwable); + static oop message(oop throwable); static void set_message(oop throwable, oop value); static Symbol* detail_message(oop throwable); static void print_stack_element(outputStream *st, const methodHandle& method, int bci); @@ -512,7 +512,7 @@ class java_lang_Throwable: AllStatic { // Programmatic access to stack trace static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS); // Printing - static void print(Handle throwable, outputStream* st); + static void print(oop throwable, outputStream* st); static void print_stack_trace(Handle throwable, outputStream* st); static void java_printStackTrace(Handle throwable, TRAPS); // Debugging diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index 9402f5d91e1..8ebb8bdef16 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -81,7 +81,7 @@ void ModuleEntry::set_version(Symbol* version) { // Returns the shared ProtectionDomain Handle ModuleEntry::shared_protection_domain() { - return Handle(JNIHandles::resolve(_pd)); + return Handle(Thread::current(), JNIHandles::resolve(_pd)); } // Set the shared ProtectionDomain atomically @@ -269,12 +269,12 @@ void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) { // For the boot loader, the java.lang.reflect.Module for the unnamed module // is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At // this point initially create the ModuleEntry for the unnamed module. - _unnamed_module = new_entry(0, Handle(NULL), NULL, NULL, NULL, loader_data); + _unnamed_module = new_entry(0, Handle(), NULL, NULL, NULL, loader_data); } else { // For all other class loaders the java.lang.reflect.Module for their // corresponding unnamed module can be found in the java.lang.ClassLoader object. oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader()); - _unnamed_module = new_entry(0, Handle(module), NULL, NULL, NULL, loader_data); + _unnamed_module = new_entry(0, Handle(Thread::current(), module), NULL, NULL, NULL, loader_data); // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module // object. diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp index becda5363a6..f6327d80399 100644 --- a/hotspot/src/share/vm/classfile/modules.cpp +++ b/hotspot/src/share/vm/classfile/modules.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2017, 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 @@ -198,7 +198,7 @@ static void define_javabase_module(jobject module, jstring version, THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Class loader must be the boot class loader"); } - Handle h_loader = Handle(THREAD, loader); + Handle h_loader(THREAD, loader); // Ensure the boot loader's PackageEntryTable has been created PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK); @@ -320,7 +320,7 @@ void Modules::define_module(jobject module, jstring version, // Only modules defined to either the boot or platform class loader, can define a "java/" package. if (!h_loader.is_null() && - !SystemDictionary::is_platform_class_loader(h_loader) && + !SystemDictionary::is_platform_class_loader(h_loader()) && strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) { const char* class_loader_name = SystemDictionary::loader_name(h_loader()); StringUtils::replace_no_expand(package_name, "/", "."); @@ -482,7 +482,7 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Class loader must be the boot class loader"); } - Handle h_loader = Handle(THREAD, loader); + Handle h_loader(THREAD, loader); log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader"); diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp index 24c72b7ccf1..525eddc53bd 100644 --- a/hotspot/src/share/vm/classfile/stringTable.cpp +++ b/hotspot/src/share/vm/classfile/stringTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -236,6 +236,7 @@ oop StringTable::intern(Handle string_or_null, jchar* name, assert(!Universe::heap()->is_in_reserved(name), "proposed name of symbol must be stable"); + HandleMark hm(THREAD); // cleanup strings created Handle string; // try to reuse the string if possible if (!string_or_null.is_null()) { diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index e29fd131432..27624d50472 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -160,17 +160,17 @@ bool SystemDictionary::is_parallelDefine(Handle class_loader) { // Returns true if the passed class loader is the builtin application class loader // or a custom system class loader. A customer system class loader can be // specified via -Djava.system.class.loader. -bool SystemDictionary::is_system_class_loader(Handle class_loader) { - if (class_loader.is_null()) { +bool SystemDictionary::is_system_class_loader(oop class_loader) { + if (class_loader == NULL) { return false; } return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() || - class_loader() == _java_system_loader); + class_loader == _java_system_loader); } // Returns true if the passed class loader is the platform class loader. -bool SystemDictionary::is_platform_class_loader(Handle class_loader) { - if (class_loader.is_null()) { +bool SystemDictionary::is_platform_class_loader(oop class_loader) { + if (class_loader == NULL) { return false; } return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass()); @@ -662,6 +662,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Ticks class_load_start_time = Ticks::now(); + HandleMark hm(THREAD); + // Fix for 4474172; see evaluation for more details class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL); @@ -1103,6 +1105,8 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, ClassFileStream* st, TRAPS) { + HandleMark hm(THREAD); + // Classloaders that support parallelism, e.g. bootstrap classloader, // or all classloaders with UnsyncloadClass do not acquire lock here bool DoObjectLock = true; @@ -1381,6 +1385,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); { + HandleMark hm(THREAD); Handle lockObject = compute_loader_lock_object(class_loader, THREAD); check_loader_lock_contention(lockObject, THREAD); ObjectLocker ol(lockObject, THREAD, true); @@ -1601,6 +1606,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { + HandleMark hm(THREAD); ClassLoaderData* loader_data = k->class_loader_data(); Handle class_loader_h(THREAD, loader_data->class_loader()); @@ -2608,8 +2614,9 @@ methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass, SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty)); int ref_kind = JVM_REF_invokeVirtual; - Handle name_str = StringTable::intern(name, CHECK_(empty)); - objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty)); + oop name_oop = StringTable::intern(name, CHECK_(empty)); + Handle name_str (THREAD, name_oop); + objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty)); assert(appendix_box->obj_at(0) == NULL, ""); // This should not happen. JDK code should take care of that. @@ -2619,12 +2626,12 @@ methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass, // call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName JavaCallArguments args; - args.push_oop(accessing_klass()->java_mirror()); + args.push_oop(Handle(THREAD, accessing_klass()->java_mirror())); args.push_int(ref_kind); - args.push_oop(klass()->java_mirror()); - args.push_oop(name_str()); - args.push_oop(method_type()); - args.push_oop(appendix_box()); + args.push_oop(Handle(THREAD, klass()->java_mirror())); + args.push_oop(name_str); + args.push_oop(method_type); + args.push_oop(appendix_box); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), @@ -2682,7 +2689,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, } bool can_be_cached = true; int npts = ArgumentCount(signature).size(); - objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); + objArrayHandle pts = oopFactory::new_objArray_handle(SystemDictionary::Class_klass(), npts, CHECK_(empty)); int arg = 0; Handle rt; // the return type from the signature ResourceMark rm(THREAD); @@ -2725,7 +2732,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, // call java.lang.invoke.MethodHandleNatives::findMethodHandleType(Class rt, Class[] pts) -> MethodType JavaCallArguments args(Handle(THREAD, rt())); - args.push_oop(pts()); + args.push_oop(pts); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), @@ -2768,7 +2775,8 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, ResourceMark rm(THREAD); SignatureStream ss(signature, false); if (!ss.is_done()) { - oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(), + oop mirror = ss.as_java_mirror(Handle(THREAD, caller->class_loader()), + Handle(THREAD, caller->protection_domain()), SignatureStream::NCDFError, CHECK_(empty)); type = Handle(THREAD, mirror); ss.next(); @@ -2781,11 +2789,11 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, // call java.lang.invoke.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle JavaCallArguments args; - args.push_oop(caller->java_mirror()); // the referring class + args.push_oop(Handle(THREAD, caller->java_mirror())); // the referring class args.push_int(ref_kind); - args.push_oop(callee->java_mirror()); // the target class - args.push_oop(name()); - args.push_oop(type()); + args.push_oop(Handle(THREAD, callee->java_mirror())); // the target class + args.push_oop(name); + args.push_oop(type); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), @@ -2832,16 +2840,16 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty); } - objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty)); + objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty)); assert(appendix_box->obj_at(0) == NULL, ""); // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, bsm, name, mtype, info, &appendix) JavaCallArguments args; - args.push_oop(caller->java_mirror()); - args.push_oop(bsm()); - args.push_oop(method_name()); - args.push_oop(method_type()); - args.push_oop(info()); + args.push_oop(Handle(THREAD, caller->java_mirror())); + args.push_oop(bsm); + args.push_oop(method_name); + args.push_oop(method_type); + args.push_oop(info); args.push_oop(appendix_box); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 4cd5e40ffa8..612a83aac7e 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -657,8 +657,8 @@ public: static instanceKlassHandle load_shared_class(Symbol* class_name, Handle class_loader, TRAPS); - static bool is_system_class_loader(Handle class_loader); - static bool is_platform_class_loader(Handle class_loader); + static bool is_system_class_loader(oop class_loader); + static bool is_platform_class_loader(oop class_loader); protected: static Klass* find_shared_class(Symbol* class_name); diff --git a/hotspot/src/share/vm/classfile/verificationType.cpp b/hotspot/src/share/vm/classfile/verificationType.cpp index 1f0f9549013..fec279f7411 100644 --- a/hotspot/src/share/vm/classfile/verificationType.cpp +++ b/hotspot/src/share/vm/classfile/verificationType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -44,6 +44,7 @@ VerificationType VerificationType::from_tag(u1 tag) { bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) { + HandleMark hm(THREAD); Klass* obj = SystemDictionary::resolve_or_fail( name, Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 93392009cc9..aa6f093de1d 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -126,7 +126,7 @@ void Verifier::log_end_verification(outputStream* st, const char* klassName, Sym } bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) { - HandleMark hm; + HandleMark hm(THREAD); ResourceMark rm(THREAD); // Eagerly allocate the identity hash code for a klass. This is a fallout @@ -1997,6 +1997,7 @@ void ClassVerifier::class_format_error(const char* msg, ...) { } Klass* ClassVerifier::load_class(Symbol* name, TRAPS) { + HandleMark hm(THREAD); // Get current loader and protection domain first. oop loader = current_class()->class_loader(); oop protection_domain = current_class()->protection_domain(); diff --git a/hotspot/src/share/vm/code/codeBlob.cpp b/hotspot/src/share/vm/code/codeBlob.cpp index 1d0634a2da6..7dd159c757b 100644 --- a/hotspot/src/share/vm/code/codeBlob.cpp +++ b/hotspot/src/share/vm/code/codeBlob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -209,7 +209,6 @@ const ImmutableOopMap* CodeBlob::oop_map_for_return_address(address return_addre } void CodeBlob::print_code() { - HandleMark hm; ResourceMark m; Disassembler::decode(this, tty); } diff --git a/hotspot/src/share/vm/code/debugInfo.cpp b/hotspot/src/share/vm/code/debugInfo.cpp index 1cb13d7491c..287d7e1ad4e 100644 --- a/hotspot/src/share/vm/code/debugInfo.cpp +++ b/hotspot/src/share/vm/code/debugInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -224,7 +224,7 @@ void ConstantOopWriteValue::print_on(outputStream* st) const { // ConstantOopReadValue ConstantOopReadValue::ConstantOopReadValue(DebugInfoReadStream* stream) { - _value = Handle(stream->read_oop()); + _value = Handle(Thread::current(), stream->read_oop()); assert(_value() == NULL || Universe::heap()->is_in_reserved(_value()), "Should be in heap"); } diff --git a/hotspot/src/share/vm/code/debugInfo.hpp b/hotspot/src/share/vm/code/debugInfo.hpp index ad59edeb546..58a618acfc2 100644 --- a/hotspot/src/share/vm/code/debugInfo.hpp +++ b/hotspot/src/share/vm/code/debugInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "code/nmethod.hpp" #include "code/oopRecorder.hpp" #include "runtime/stackValue.hpp" +#include "runtime/thread.hpp" #include "utilities/growableArray.hpp" // Classes used for serializing debugging information. @@ -127,7 +128,7 @@ class ObjectValue: public ScopeValue { Handle value() const { return _value; } bool is_visited() const { return _visited; } - void set_value(oop value) { _value = Handle(value); } + void set_value(oop value) { _value = Handle(Thread::current(), value); } void set_visited(bool visited) { _visited = false; } // Serialization of debugging information diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp index d33df4eda1b..845f1320243 100644 --- a/hotspot/src/share/vm/code/dependencies.cpp +++ b/hotspot/src/share/vm/code/dependencies.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -714,7 +714,8 @@ void Dependencies::write_dependency_to(xmlStream* xtty, if (xtty == NULL) { return; } - ResourceMark rm; + Thread* thread = Thread::current(); + HandleMark rm(thread); ttyLocker ttyl; int ctxkj = dep_context_arg(dept); // -1 if no context arg if (witness != NULL) { @@ -732,14 +733,14 @@ void Dependencies::write_dependency_to(xmlStream* xtty, DepArgument arg = args->at(j); if (j == 1) { if (arg.is_oop()) { - xtty->object("x", arg.oop_value()); + xtty->object("x", Handle(thread, arg.oop_value())); } else { xtty->object("x", arg.metadata_value()); } } else { char xn[10]; sprintf(xn, "x%d", j); if (arg.is_oop()) { - xtty->object(xn, arg.oop_value()); + xtty->object(xn, Handle(thread, arg.oop_value())); } else { xtty->object(xn, arg.metadata_value()); } diff --git a/hotspot/src/share/vm/compiler/compileTask.cpp b/hotspot/src/share/vm/compiler/compileTask.cpp index c5dcd8ca28e..d9887353fa5 100644 --- a/hotspot/src/share/vm/compiler/compileTask.cpp +++ b/hotspot/src/share/vm/compiler/compileTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -86,9 +86,10 @@ void CompileTask::initialize(int compile_id, bool is_blocking) { assert(!_lock->is_locked(), "bad locking"); + Thread* thread = Thread::current(); _compile_id = compile_id; _method = method(); - _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder()); + _method_holder = JNIHandles::make_global(Handle(thread, method->method_holder()->klass_holder())); _osr_bci = osr_bci; _is_blocking = is_blocking; JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) @@ -115,7 +116,7 @@ void CompileTask::initialize(int compile_id, } else { _hot_method = hot_method(); // only add loader or mirror if different from _method_holder - _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder()); + _hot_method_holder = JNIHandles::make_global(Handle(thread, hot_method->method_holder()->klass_holder())); } } } diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index 745fb5199ec..32001919582 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -59,7 +59,7 @@ VMReg getVMRegFromLocation(Handle location, int total_frame_size, TRAPS) { THROW_NULL(vmSymbols::java_lang_NullPointerException()); } - Handle reg = code_Location::reg(location); + Handle reg(THREAD, code_Location::reg(location)); jint offset = code_Location::offset(location); if (reg.not_null()) { @@ -95,7 +95,7 @@ VMReg getVMRegFromLocation(Handle location, int total_frame_size, TRAPS) { // creates a HotSpot oop map out of the byte arrays provided by DebugInfo OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) { - Handle reference_map = DebugInfo::referenceMap(debug_info); + Handle reference_map(THREAD, DebugInfo::referenceMap(debug_info)); if (reference_map.is_null()) { THROW_NULL(vmSymbols::java_lang_NullPointerException()); } @@ -106,9 +106,9 @@ OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) { _has_wide_vector = true; } OopMap* map = new OopMap(_total_frame_size, _parameter_count); - objArrayHandle objects = HotSpotReferenceMap::objects(reference_map); - objArrayHandle derivedBase = HotSpotReferenceMap::derivedBase(reference_map); - typeArrayHandle sizeInBytes = HotSpotReferenceMap::sizeInBytes(reference_map); + objArrayHandle objects(THREAD, HotSpotReferenceMap::objects(reference_map)); + objArrayHandle derivedBase(THREAD, HotSpotReferenceMap::derivedBase(reference_map)); + typeArrayHandle sizeInBytes(THREAD, HotSpotReferenceMap::sizeInBytes(reference_map)); if (objects.is_null() || derivedBase.is_null() || sizeInBytes.is_null()) { THROW_NULL(vmSymbols::java_lang_NullPointerException()); } @@ -116,8 +116,8 @@ OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) { JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", objects->length(), derivedBase->length(), sizeInBytes->length()); } for (int i = 0; i < objects->length(); i++) { - Handle location = objects->obj_at(i); - Handle baseLocation = derivedBase->obj_at(i); + Handle location(THREAD, objects->obj_at(i)); + Handle baseLocation(THREAD, derivedBase->obj_at(i)); int bytes = sizeInBytes->int_at(i); VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, CHECK_NULL); @@ -149,12 +149,12 @@ OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) { } } - Handle callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info); + Handle callee_save_info(THREAD, (oop) DebugInfo::calleeSaveInfo(debug_info)); if (callee_save_info.not_null()) { - objArrayHandle registers = RegisterSaveLayout::registers(callee_save_info); - typeArrayHandle slots = RegisterSaveLayout::slots(callee_save_info); + objArrayHandle registers(THREAD, RegisterSaveLayout::registers(callee_save_info)); + typeArrayHandle slots(THREAD, RegisterSaveLayout::slots(callee_save_info)); for (jint i = 0; i < slots->length(); i++) { - Handle jvmci_reg = registers->obj_at(i); + Handle jvmci_reg (THREAD, registers->obj_at(i)); jint jvmci_reg_number = code_Register::number(jvmci_reg); VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, CHECK_NULL); // HotSpot stack slots are 4 bytes @@ -279,9 +279,9 @@ narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section } #endif -Location::Type CodeInstaller::get_oop_type(Handle value) { - Handle valueKind = Value::valueKind(value); - Handle platformKind = ValueKind::platformKind(valueKind); +Location::Type CodeInstaller::get_oop_type(Thread* thread, Handle value) { + Handle valueKind(thread, Value::valueKind(value)); + Handle platformKind(thread, ValueKind::platformKind(valueKind)); if (platformKind == word_kind()) { return Location::oop; @@ -300,13 +300,13 @@ ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, Growabl } return _illegal_value; } else if (value->is_a(RegisterValue::klass())) { - Handle reg = RegisterValue::reg(value); + Handle reg(THREAD, RegisterValue::reg(value)); jint number = code_Register::number(reg); VMReg hotspotRegister = get_hotspot_reg(number, CHECK_NULL); if (is_general_purpose_reg(hotspotRegister)) { Location::Type locationType; if (type == T_OBJECT) { - locationType = get_oop_type(value); + locationType = get_oop_type(THREAD, value); } else if (type == T_LONG) { locationType = Location::lng; } else if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) { @@ -343,7 +343,7 @@ ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, Growabl Location::Type locationType; if (type == T_OBJECT) { - locationType = get_oop_type(value); + locationType = get_oop_type(THREAD, value); } else if (type == T_LONG) { locationType = Location::lng; } else if (type == T_DOUBLE) { @@ -364,7 +364,8 @@ ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, Growabl jlong prim = PrimitiveConstant::primitive(value); return new ConstantLongValue(prim); } else { - BasicType constantType = JVMCIRuntime::kindToBasicType(PrimitiveConstant::kind(value), CHECK_NULL); + Handle primitive_constant_kind(THREAD, PrimitiveConstant::kind(value)); + BasicType constantType = JVMCIRuntime::kindToBasicType(primitive_constant_kind, CHECK_NULL); if (type != constantType) { JVMCI_ERROR_NULL("primitive constant type doesn't match, expected %s but got %s", basictype_to_str(type), basictype_to_str(constantType)); } @@ -421,18 +422,21 @@ ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, Growabl } void CodeInstaller::record_object_value(ObjectValue* sv, Handle value, GrowableArray* objects, TRAPS) { - Handle type = VirtualObject::type(value); + // Might want a HandleMark here. + Handle type(THREAD, VirtualObject::type(value)); int id = VirtualObject::id(value); oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); Klass* klass = java_lang_Class::as_Klass(javaMirror); bool isLongArray = klass == Universe::longArrayKlassObj(); - objArrayHandle values = VirtualObject::values(value); - objArrayHandle slotKinds = VirtualObject::slotKinds(value); + objArrayHandle values(THREAD, VirtualObject::values(value)); + objArrayHandle slotKinds(THREAD, VirtualObject::slotKinds(value)); for (jint i = 0; i < values->length(); i++) { + HandleMark hm(THREAD); ScopeValue* cur_second = NULL; - Handle object = values->obj_at(i); - BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK); + Handle object(THREAD, values->obj_at(i)); + Handle slot_kind (THREAD, slotKinds->obj_at(i)); + BasicType type = JVMCIRuntime::kindToBasicType(slot_kind, CHECK); ScopeValue* value = get_scope_value(object, type, objects, cur_second, CHECK); if (isLongArray && cur_second == NULL) { @@ -458,10 +462,12 @@ MonitorValue* CodeInstaller::get_monitor_value(Handle value, GrowableArrayis_location(), "invalid monitor location"); Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); @@ -476,25 +482,26 @@ MonitorValue* CodeInstaller::get_monitor_value(Handle value, GrowableArrayis_Compiler_thread() ? thread->as_CompilerThread() : NULL; _oop_recorder = recorder; _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL); - objArrayHandle assumptions = HotSpotCompiledCode::assumptions(compiled_code); + objArrayHandle assumptions(THREAD, HotSpotCompiledCode::assumptions(compiled_code)); if (!assumptions.is_null()) { int length = assumptions->length(); for (int i = 0; i < length; ++i) { - Handle assumption = assumptions->obj_at(i); + Handle assumption(THREAD, assumptions->obj_at(i)); if (!assumption.is_null()) { if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { - assumption_NoFinalizableSubclass(assumption); + assumption_NoFinalizableSubclass(THREAD, assumption); } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) { - assumption_ConcreteSubtype(assumption); + assumption_ConcreteSubtype(THREAD, assumption); } else if (assumption->klass() == Assumptions_LeafType::klass()) { - assumption_LeafType(assumption); + assumption_LeafType(THREAD, assumption); } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) { - assumption_ConcreteMethod(assumption); + assumption_ConcreteMethod(THREAD, assumption); } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) { - assumption_CallSiteTargetValue(assumption); + assumption_CallSiteTargetValue(THREAD, assumption); } else { JVMCI_ERROR("unexpected Assumption subclass %s", assumption->klass()->signature_name()); } @@ -502,11 +509,11 @@ void CodeInstaller::initialize_dependencies(oop compiled_code, OopRecorder* reco } } if (JvmtiExport::can_hotswap_or_post_breakpoint()) { - objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code); + objArrayHandle methods(THREAD, HotSpotCompiledCode::methods(compiled_code)); if (!methods.is_null()) { int length = methods->length(); for (int i = 0; i < length; ++i) { - Handle method_handle = methods->obj_at(i); + Handle method_handle(THREAD, methods->obj_at(i)); methodHandle method = getMethodFromHotSpotMethod(method_handle()); _dependencies->assert_evol_method(method()); } @@ -639,7 +646,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand void CodeInstaller::initialize_fields(oop target, oop compiled_code, TRAPS) { if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) { - Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code); + Handle hotspotJavaMethod(THREAD, HotSpotCompiledNmethod::method(compiled_code)); methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod()); _parameter_count = method->size_of_parameters(); TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string()); @@ -728,7 +735,7 @@ int CodeInstaller::estimate_stubs_size(TRAPS) { // perform data and call relocation on the CodeBuffer JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRAPS) { HandleMark hm; - objArrayHandle sites = this->sites(); + objArrayHandle sites(THREAD, this->sites()); int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo)); // Allocate enough space in the stub section for the static call @@ -766,18 +773,19 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, _instructions->set_end(end_pc); for (int i = 0; i < data_section_patches()->length(); i++) { - Handle patch = data_section_patches()->obj_at(i); + HandleMark hm(THREAD); + Handle patch(THREAD, data_section_patches()->obj_at(i)); if (patch.is_null()) { THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok); } - Handle reference = site_DataPatch::reference(patch); + Handle reference(THREAD, site_DataPatch::reference(patch)); if (reference.is_null()) { THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok); } if (!reference->is_a(site_ConstantReference::klass())) { JVMCI_ERROR_OK("invalid patch in data section: %s", reference->klass()->signature_name()); } - Handle constant = site_ConstantReference::constant(reference); + Handle constant(THREAD, site_ConstantReference::constant(reference)); if (constant.is_null()) { THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok); } @@ -793,7 +801,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, *((void**) dest) = record_metadata_reference(_constants, dest, constant, CHECK_OK); } } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) { - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); int oop_index = _oop_recorder->find_index(value); @@ -812,7 +820,8 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, } jint last_pc_offset = -1; for (int i = 0; i < sites->length(); i++) { - Handle site = sites->obj_at(i); + HandleMark hm(THREAD); + Handle site(THREAD, sites->obj_at(i)); if (site.is_null()) { THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok); } @@ -869,15 +878,15 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, return JVMCIEnv::ok; } -void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) { - Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption()); +void CodeInstaller::assumption_NoFinalizableSubclass(Thread* thread, Handle assumption) { + Handle receiverType_handle (thread, Assumptions_NoFinalizableSubclass::receiverType(assumption())); Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle)); _dependencies->assert_has_no_finalizable_subclasses(receiverType); } -void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { - Handle context_handle = Assumptions_ConcreteSubtype::context(assumption()); - Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption()); +void CodeInstaller::assumption_ConcreteSubtype(Thread* thread, Handle assumption) { + Handle context_handle (thread, Assumptions_ConcreteSubtype::context(assumption())); + Handle subtype_handle (thread, Assumptions_ConcreteSubtype::subtype(assumption())); Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle)); @@ -885,16 +894,16 @@ void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype); } -void CodeInstaller::assumption_LeafType(Handle assumption) { - Handle context_handle = Assumptions_LeafType::context(assumption()); +void CodeInstaller::assumption_LeafType(Thread* thread, Handle assumption) { + Handle context_handle (thread, Assumptions_LeafType::context(assumption())); Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); _dependencies->assert_leaf_type(context); } -void CodeInstaller::assumption_ConcreteMethod(Handle assumption) { - Handle impl_handle = Assumptions_ConcreteMethod::impl(assumption()); - Handle context_handle = Assumptions_ConcreteMethod::context(assumption()); +void CodeInstaller::assumption_ConcreteMethod(Thread* thread, Handle assumption) { + Handle impl_handle (thread, Assumptions_ConcreteMethod::impl(assumption())); + Handle context_handle (thread, Assumptions_ConcreteMethod::context(assumption())); methodHandle impl = getMethodFromHotSpotMethod(impl_handle()); Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); @@ -902,9 +911,9 @@ void CodeInstaller::assumption_ConcreteMethod(Handle assumption) { _dependencies->assert_unique_concrete_method(context, impl()); } -void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) { - Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption()); - Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption()); +void CodeInstaller::assumption_CallSiteTargetValue(Thread* thread, Handle assumption) { + Handle callSite(thread, Assumptions_CallSiteTargetValue::callSite(assumption())); + Handle methodHandle(thread, Assumptions_CallSiteTargetValue::methodHandle(assumption())); _dependencies->assert_call_site_target_value(callSite(), methodHandle()); } @@ -936,16 +945,17 @@ static bool bytecode_should_reexecute(Bytecodes::Code code) { } GrowableArray* CodeInstaller::record_virtual_objects(Handle debug_info, TRAPS) { - objArrayHandle virtualObjects = DebugInfo::virtualObjectMapping(debug_info); + objArrayHandle virtualObjects(THREAD, DebugInfo::virtualObjectMapping(debug_info)); if (virtualObjects.is_null()) { return NULL; } GrowableArray* objects = new GrowableArray(virtualObjects->length(), virtualObjects->length(), NULL); // Create the unique ObjectValues for (int i = 0; i < virtualObjects->length(); i++) { - Handle value = virtualObjects->obj_at(i); + HandleMark hm(THREAD); + Handle value(THREAD, virtualObjects->obj_at(i)); int id = VirtualObject::id(value); - Handle type = VirtualObject::type(value); + Handle type(THREAD, VirtualObject::type(value)); oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); if (id < 0 || id >= objects->length()) { @@ -959,7 +969,8 @@ GrowableArray* CodeInstaller::record_virtual_objects(Handle debug_i // All the values which could be referenced by the VirtualObjects // exist, so now describe all the VirtualObjects themselves. for (int i = 0; i < virtualObjects->length(); i++) { - Handle value = virtualObjects->obj_at(i); + HandleMark hm(THREAD); + Handle value(THREAD, virtualObjects->obj_at(i)); int id = VirtualObject::id(value); record_object_value(objects->at(id)->as_ObjectValue(), value, objects, CHECK_NULL); } @@ -968,7 +979,7 @@ GrowableArray* CodeInstaller::record_virtual_objects(Handle debug_i } void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS) { - Handle position = DebugInfo::bytecodePosition(debug_info); + Handle position(THREAD, DebugInfo::bytecodePosition(debug_info)); if (position.is_null()) { // Stubs do not record scope info, just oop maps return; @@ -991,12 +1002,12 @@ void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scop } frame = position; } - Handle caller_frame = BytecodePosition::caller(position); + Handle caller_frame (THREAD, BytecodePosition::caller(position)); if (caller_frame.not_null()) { record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, CHECK); } - Handle hotspot_method = BytecodePosition::method(position); + Handle hotspot_method (THREAD, BytecodePosition::method(position)); Method* method = getMethodFromHotSpotMethod(hotspot_method()); jint bci = BytecodePosition::bci(position); if (bci == BytecodeFrame::BEFORE_BCI()) { @@ -1027,8 +1038,8 @@ void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scop jint local_count = BytecodeFrame::numLocals(frame); jint expression_count = BytecodeFrame::numStack(frame); jint monitor_count = BytecodeFrame::numLocks(frame); - objArrayHandle values = BytecodeFrame::values(frame); - objArrayHandle slotKinds = BytecodeFrame::slotKinds(frame); + objArrayHandle values(THREAD, BytecodeFrame::values(frame)); + objArrayHandle slotKinds(THREAD, BytecodeFrame::slotKinds(frame)); if (values.is_null() || slotKinds.is_null()) { THROW(vmSymbols::java_lang_NullPointerException()); @@ -1048,17 +1059,18 @@ void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scop TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); for (jint i = 0; i < values->length(); i++) { + HandleMark hm(THREAD); ScopeValue* second = NULL; - Handle value = values->obj_at(i); + Handle value(THREAD, values->obj_at(i)); if (i < local_count) { - BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK); + BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK); ScopeValue* first = get_scope_value(value, type, objects, second, CHECK); if (second != NULL) { locals->append(second); } locals->append(first); } else if (i < local_count + expression_count) { - BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK); + BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK); ScopeValue* first = get_scope_value(value, type, objects, second, CHECK); if (second != NULL) { expressions->append(second); @@ -1088,7 +1100,7 @@ void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scop } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) { - Handle debug_info = site_Infopoint::debugInfo(site); + Handle debug_info (THREAD, site_Infopoint::debugInfo(site)); if (debug_info.is_null()) { JVMCI_ERROR("debug info expected at safepoint at %i", pc_offset); } @@ -1102,7 +1114,7 @@ void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle si } void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) { - Handle debug_info = site_Infopoint::debugInfo(site); + Handle debug_info (THREAD, site_Infopoint::debugInfo(site)); if (debug_info.is_null()) { JVMCI_ERROR("debug info expected at infopoint at %i", pc_offset); } @@ -1117,7 +1129,7 @@ void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle si } void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) { - Handle target = site_Call::target(site); + Handle target(THREAD, site_Call::target(site)); InstanceKlass* target_klass = InstanceKlass::cast(target->klass()); Handle hotspot_method; // JavaMethod @@ -1129,7 +1141,7 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, T hotspot_method = target; } - Handle debug_info = site_Call::debugInfo(site); + Handle debug_info (THREAD, site_Call::debugInfo(site)); assert(hotspot_method.not_null() ^ foreign_call.not_null(), "Call site needs exactly one type"); @@ -1177,11 +1189,11 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, T } void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) { - Handle reference = site_DataPatch::reference(site); + Handle reference(THREAD, site_DataPatch::reference(site)); if (reference.is_null()) { THROW(vmSymbols::java_lang_NullPointerException()); } else if (reference->is_a(site_ConstantReference::klass())) { - Handle constant = site_ConstantReference::constant(reference); + Handle constant(THREAD, site_ConstantReference::constant(reference)); if (constant.is_null()) { THROW(vmSymbols::java_lang_NullPointerException()); } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) { @@ -1213,7 +1225,7 @@ void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle si } void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) { - Handle id_obj = site_Mark::id(site); + Handle id_obj (THREAD, site_Mark::id(site)); if (id_obj.not_null()) { if (!java_lang_boxing_object::is_instance(id_obj(), T_INT)) { diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp index 775a8c19f40..a6a6c466013 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -211,7 +211,7 @@ public: const OopMapSet* oopMapSet() const { return _debug_recorder->_oopmaps; } protected: - Location::Type get_oop_type(Handle value); + Location::Type get_oop_type(Thread* thread, Handle value); ScopeValue* get_scope_value(Handle value, BasicType type, GrowableArray* objects, ScopeValue* &second, TRAPS); MonitorValue* get_monitor_value(Handle value, GrowableArray* objects, TRAPS); @@ -229,11 +229,11 @@ protected: // perform data and call relocation on the CodeBuffer JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, TRAPS); - void assumption_NoFinalizableSubclass(Handle assumption); - void assumption_ConcreteSubtype(Handle assumption); - void assumption_LeafType(Handle assumption); - void assumption_ConcreteMethod(Handle assumption); - void assumption_CallSiteTargetValue(Handle assumption); + void assumption_NoFinalizableSubclass(Thread* thread, Handle assumption); + void assumption_ConcreteSubtype(Thread* thread, Handle assumption); + void assumption_LeafType(Thread* thread, Handle assumption); + void assumption_ConcreteMethod(Thread* thread, Handle assumption); + void assumption_CallSiteTargetValue(Thread* thread, Handle assumption); void site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS); void site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index 5e35a478d41..765aaae7adb 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -148,7 +148,7 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV if (!HAS_PENDING_EXCEPTION) { JavaCallArguments args; args.push_oop(receiver); - args.push_oop((oop)method_result.get_jobject()); + args.push_oop(Handle(THREAD, (oop)method_result.get_jobject())); args.push_int(entry_bci); args.push_long((jlong) (address) env); args.push_int(env->task()->compile_id()); @@ -202,7 +202,7 @@ CompLevel JVMCIRuntime::adjust_comp_level(methodHandle method, bool is_osr, Comp return level; } -void JVMCICompiler::exit_on_pending_exception(Handle exception, const char* message) { +void JVMCICompiler::exit_on_pending_exception(oop exception, const char* message) { JavaThread* THREAD = JavaThread::current(); CLEAR_PENDING_EXCEPTION; @@ -210,7 +210,8 @@ void JVMCICompiler::exit_on_pending_exception(Handle exception, const char* mess if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) { // Only report an error once tty->print_raw_cr(message); - java_lang_Throwable::java_printStackTrace(exception, THREAD); + Handle ex(THREAD, exception); + java_lang_Throwable::java_printStackTrace(ex, THREAD); } else { // Allow error reporting thread to print the stack trace. os::sleep(THREAD, 200, false); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp index 15e4724d482..b1401e6d75f 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ private: /** * Exits the VM due to an unexpected exception. */ - static void exit_on_pending_exception(Handle exception, const char* message); + static void exit_on_pending_exception(oop exception, const char* message); public: JVMCICompiler(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index f7eb56ff404..78daf16e99e 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,7 @@ oop CompilerToVM::get_jvmci_type(KlassHandle klass, TRAPS) { if (klass() != NULL) { JavaValue result(T_OBJECT); JavaCallArguments args; - args.push_oop(klass->java_mirror()); + args.push_oop(Handle(THREAD, klass->java_mirror())); JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedObjectTypeImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::klass_fromMetaspace_signature(), &args, CHECK_NULL); return (oop)result.get_jobject(); @@ -204,7 +204,7 @@ void CompilerToVM::Data::initialize() { } objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) { - objArrayHandle vmIntrinsics = oopFactory::new_objArray(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle())); + objArrayHandle vmIntrinsics = oopFactory::new_objArray_handle(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle())); int index = 0; // The intrinsics for a class are usually adjacent to each other. // When they are, the string for the class name can be reused. @@ -250,8 +250,9 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) VMIntrinsicMethod::klass()->initialize(CHECK_NULL); int len = JVMCIVMStructs::localHotSpotVMStructs_count(); - objArrayHandle vmFields = oopFactory::new_objArray(VMField::klass(), len, CHECK_NULL); + objArrayHandle vmFields = oopFactory::new_objArray_handle(VMField::klass(), len, CHECK_NULL); for (int i = 0; i < len ; i++) { + HandleMark hm(THREAD); VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i]; instanceHandle vmFieldObj = InstanceKlass::cast(VMField::klass())->allocate_instance_handle(CHECK_NULL); size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */; @@ -290,8 +291,9 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) } len = JVMCIVMStructs::localHotSpotVMTypes_count(); - objArrayHandle vmTypes = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); + objArrayHandle vmTypes = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); for (int i = 0; i < len ; i++) { + HandleMark hm(THREAD); VMTypeEntry vmType = JVMCIVMStructs::localHotSpotVMTypes[i]; Handle name = java_lang_String::create_from_str(vmType.typeName, CHECK_NULL); BOXED_LONG(size, vmType.size); @@ -302,9 +304,10 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) int ints_len = JVMCIVMStructs::localHotSpotVMIntConstants_count(); int longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count(); len = ints_len + longs_len; - objArrayHandle vmConstants = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); + objArrayHandle vmConstants = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); int insert = 0; for (int i = 0; i < ints_len ; i++) { + HandleMark hm(THREAD); VMIntConstantEntry c = JVMCIVMStructs::localHotSpotVMIntConstants[i]; Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL); BOXED_LONG(value, c.value); @@ -312,6 +315,7 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) vmConstants->obj_at_put(insert++, value); } for (int i = 0; i < longs_len ; i++) { + HandleMark hm(THREAD); VMLongConstantEntry c = JVMCIVMStructs::localHotSpotVMLongConstants[i]; Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL); BOXED_LONG(value, c.value); @@ -321,8 +325,9 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) assert(insert == len * 2, "must be"); len = JVMCIVMStructs::localHotSpotVMAddresses_count(); - objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); + objArrayHandle vmAddresses = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL); for (int i = 0; i < len ; i++) { + HandleMark hm(THREAD); VMAddressEntry a = JVMCIVMStructs::localHotSpotVMAddresses[i]; Handle name = java_lang_String::create_from_str(a.name, CHECK_NULL); BOXED_LONG(value, a.value); @@ -332,8 +337,9 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) // The last entry is the null entry. len = (int) Flag::numFlags - 1; - objArrayHandle vmFlags = oopFactory::new_objArray(VMFlag::klass(), len, CHECK_NULL); + objArrayHandle vmFlags = oopFactory::new_objArray_handle(VMFlag::klass(), len, CHECK_NULL); for (int i = 0; i < len; i++) { + HandleMark hm(THREAD); Flag* flag = &Flag::flags[i]; instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); Handle name = java_lang_String::create_from_str(flag->_name, CHECK_NULL); @@ -606,21 +612,19 @@ C2V_END C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve)) ResourceMark rm; - Handle name = JNIHandles::resolve(jname); - Symbol* class_name = java_lang_String::as_symbol(name, CHECK_0); + Handle name(THREAD, JNIHandles::resolve(jname)); + Symbol* class_name = java_lang_String::as_symbol(name(), CHECK_0); if (java_lang_String::length(name()) <= 1) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string())); } Klass* resolved_klass = NULL; - Handle class_loader; - Handle protection_domain; if (JNIHandles::resolve(accessing_class) == NULL) { THROW_0(vmSymbols::java_lang_NullPointerException()); } Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class)); - class_loader = accessing_klass->class_loader(); - protection_domain = accessing_klass->protection_domain(); + Handle class_loader(THREAD, accessing_klass->class_loader()); + Handle protection_domain(THREAD, accessing_klass->protection_domain()); if (resolve) { resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0); @@ -656,8 +660,8 @@ C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass access } } } - Handle result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL); - return JNIHandles::make_local(THREAD, result()); + oop result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL); + return JNIHandles::make_local(THREAD, result); C2V_END C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index)) @@ -697,8 +701,8 @@ C2V_END C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool); Klass* resolved_klass = cp->klass_at(index, CHECK_NULL); - Handle klass = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL); - return JNIHandles::make_local(THREAD, klass()); + oop klass = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL); + return JNIHandles::make_local(THREAD, klass); C2V_END C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) @@ -710,13 +714,14 @@ C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constan if (klass.is_null()) { symbol = cp->klass_name_at(index); } - Handle result; + oop result_oop; if (!klass.is_null()) { - result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL); + result_oop = CompilerToVM::get_jvmci_type(klass, CHECK_NULL); } else { - result = java_lang_String::create_from_symbol(symbol, CHECK_NULL); + Handle result = java_lang_String::create_from_symbol(symbol, CHECK_NULL); + result_oop = result(); } - return JNIHandles::make_local(THREAD, result()); + return JNIHandles::make_local(THREAD, result_oop); C2V_END C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index)) @@ -838,11 +843,11 @@ C2V_END C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject installed_code, jobject speculation_log)) ResourceMark rm; HandleMark hm; - Handle target_handle = JNIHandles::resolve(target); - Handle compiled_code_handle = JNIHandles::resolve(compiled_code); + Handle target_handle(THREAD, JNIHandles::resolve(target)); + Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code)); CodeBlob* cb = NULL; - Handle installed_code_handle = JNIHandles::resolve(installed_code); - Handle speculation_log_handle = JNIHandles::resolve(speculation_log); + Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code)); + Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log)); JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR); @@ -900,9 +905,9 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject ResourceMark rm; HandleMark hm; - Handle target_handle = JNIHandles::resolve(target); - Handle compiled_code_handle = JNIHandles::resolve(compiled_code); - Handle metadata_handle = JNIHandles::resolve(metadata); + Handle target_handle(THREAD, JNIHandles::resolve(target)); + Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code)); + Handle metadata_handle(THREAD, JNIHandles::resolve(metadata)); CodeMetadata code_metadata; CodeBlob *cb = NULL; @@ -914,19 +919,19 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject } if (code_metadata.get_nr_pc_desc() > 0) { - typeArrayHandle pcArrayOop = oopFactory::new_byteArray(sizeof(PcDesc) * code_metadata.get_nr_pc_desc(), CHECK_(JVMCIEnv::cache_full)); + typeArrayHandle pcArrayOop = oopFactory::new_byteArray_handle(sizeof(PcDesc) * code_metadata.get_nr_pc_desc(), CHECK_(JVMCIEnv::cache_full)); memcpy(pcArrayOop->byte_at_addr(0), code_metadata.get_pc_desc(), sizeof(PcDesc) * code_metadata.get_nr_pc_desc()); HotSpotMetaData::set_pcDescBytes(metadata_handle, pcArrayOop()); } if (code_metadata.get_scopes_size() > 0) { - typeArrayHandle scopesArrayOop = oopFactory::new_byteArray(code_metadata.get_scopes_size(), CHECK_(JVMCIEnv::cache_full)); + typeArrayHandle scopesArrayOop = oopFactory::new_byteArray_handle(code_metadata.get_scopes_size(), CHECK_(JVMCIEnv::cache_full)); memcpy(scopesArrayOop->byte_at_addr(0), code_metadata.get_scopes_desc(), code_metadata.get_scopes_size()); HotSpotMetaData::set_scopesDescBytes(metadata_handle, scopesArrayOop()); } RelocBuffer* reloc_buffer = code_metadata.get_reloc_buffer(); - typeArrayHandle relocArrayOop = oopFactory::new_byteArray((int) reloc_buffer->size(), CHECK_(JVMCIEnv::cache_full)); + typeArrayHandle relocArrayOop = oopFactory::new_byteArray_handle((int) reloc_buffer->size(), CHECK_(JVMCIEnv::cache_full)); if (reloc_buffer->size() > 0) { memcpy(relocArrayOop->byte_at_addr(0), reloc_buffer->begin(), reloc_buffer->size()); } @@ -937,7 +942,7 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject ResourceMark mark; ImmutableOopMapBuilder builder(oopMapSet); int oopmap_size = builder.heap_size(); - typeArrayHandle oopMapArrayHandle = oopFactory::new_byteArray(oopmap_size, CHECK_(JVMCIEnv::cache_full)); + typeArrayHandle oopMapArrayHandle = oopFactory::new_byteArray_handle(oopmap_size, CHECK_(JVMCIEnv::cache_full)); builder.generate_into((address) oopMapArrayHandle->byte_at_addr(0)); HotSpotMetaData::set_oopMaps(metadata_handle, oopMapArrayHandle()); } @@ -945,7 +950,8 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject AOTOopRecorder* recorder = code_metadata.get_oop_recorder(); int nr_meta_strings = recorder->nr_meta_strings(); - objArrayHandle metadataArrayHandle = oopFactory::new_objectArray(nr_meta_strings, CHECK_(JVMCIEnv::cache_full)); + objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_strings, CHECK_(JVMCIEnv::cache_full)); + objArrayHandle metadataArrayHandle(THREAD, metadataArray); for (int i = 0; i < nr_meta_strings; ++i) { const char* element = recorder->meta_element(i); Handle java_string = java_lang_String::create_from_str(element, CHECK_(JVMCIEnv::cache_full)); @@ -955,7 +961,7 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject ExceptionHandlerTable* handler = code_metadata.get_exception_table(); int table_size = handler->size_in_bytes(); - typeArrayHandle exceptionArrayOop = oopFactory::new_byteArray(table_size, CHECK_(JVMCIEnv::cache_full)); + typeArrayHandle exceptionArrayOop = oopFactory::new_byteArray_handle(table_size, CHECK_(JVMCIEnv::cache_full)); if (table_size > 0) { handler->copy_bytes_to((address) exceptionArrayOop->byte_at_addr(0)); @@ -1134,7 +1140,7 @@ C2V_END C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code)) - Handle installed_code_handle = JNIHandles::resolve(installed_code); + Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code)); nmethod::invalidate_installed_code(installed_code_handle, CHECK); C2V_END @@ -1189,7 +1195,7 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject ResourceMark rm; if (!thread->has_last_Java_frame()) return NULL; - Handle result = HotSpotStackFrameReference::klass()->allocate_instance(thread); + Handle result = HotSpotStackFrameReference::klass()->allocate_instance_handle(thread); HotSpotStackFrameReference::klass()->initialize(thread); StackFrameStream fst(thread); @@ -1248,7 +1254,8 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false); GrowableArray* local_values = scope->locals(); - typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread); + typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), thread); + typeArrayHandle array(THREAD, array_oop); for (int i = 0; i < local_values->length(); i++) { ScopeValue* value = local_values->at(i); if (value->is_object()) { @@ -1289,7 +1296,8 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject HotSpotStackFrameReference::set_frameNumber(result, frame_number); // initialize the locals array - objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread); + objArrayOop array_oop = oopFactory::new_objectArray(locals->size(), CHECK_NULL); + objArrayHandle array(THREAD, array_oop); for (int i = 0; i < locals->size(); i++) { StackValue* var = locals->at(i); if (var->type() == T_OBJECT) { @@ -1341,7 +1349,7 @@ C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_co C2V_END C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject)) - objArrayHandle holders = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, CHECK_NULL); + objArrayHandle holders = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), 2, CHECK_NULL); Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL); Handle vh = java_lang_String::create_from_str("Ljava/lang/invoke/VarHandle;", CHECK_NULL); holders->obj_at_put(0, mh()); @@ -1448,7 +1456,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL); // update the locals array - objArrayHandle array = HotSpotStackFrameReference::locals(hs_frame); + objArrayHandle array(THREAD, HotSpotStackFrameReference::locals(hs_frame)); StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals(); for (int i = 0; i < locals->size(); i++) { StackValue* var = locals->at(i); @@ -1549,7 +1557,7 @@ C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame C2V_END C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_handle)) - Handle lambda_form = JNIHandles::resolve_non_null(lambda_form_handle); + Handle lambda_form(THREAD, JNIHandles::resolve_non_null(lambda_form_handle)); if (lambda_form->is_a(SystemDictionary::LambdaForm_klass())) { TempNewSymbol compileToBytecode = SymbolTable::new_symbol("compileToBytecode", CHECK); JavaValue result(T_VOID); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index c0f21e2b8c2..db2175e964e 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -144,11 +144,11 @@ class JavaArgumentUnboxer : public SignatureIterator { arrayOop _args; int _index; - oop next_arg(BasicType expectedType) { + Handle next_arg(BasicType expectedType) { assert(_index < _args->length(), "out of bounds"); oop arg=((objArrayOop) (_args))->obj_at(_index++); assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); - return arg; + return Handle(Thread::current(), arg); } public: diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index 0fdec7c7fcf..d7a81cd78e8 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -650,7 +650,7 @@ Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, c } else { JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_(Handle())); } - return Handle((oop)result.get_jobject()); + return Handle(THREAD, (oop)result.get_jobject()); } void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { @@ -684,7 +684,7 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { "compilation level adjustment out of bounds"); _comp_level_adjustment = (CompLevelAdjustment) adjustment; _HotSpotJVMCIRuntime_initialized = true; - _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result()); + _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result); } void JVMCIRuntime::initialize_JVMCI(TRAPS) { @@ -863,9 +863,9 @@ if (HAS_PENDING_EXCEPTION) { \ JavaValue result(T_INT); JavaCallArguments args; args.push_oop(receiver); - args.push_oop(method->method_holder()->java_mirror()); - args.push_oop(name()); - args.push_oop(sig()); + args.push_oop(Handle(THREAD, method->method_holder()->java_mirror())); + args.push_oop(name); + args.push_oop(sig); args.push_int(is_osr); args.push_int(level); JavaCalls::call_special(&result, receiver->klass(), vmSymbols::adjustCompilationLevel_name(), diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp index 0aa9bcade19..6ae41945837 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -75,7 +75,7 @@ class JVMCIRuntime: public AllStatic { */ static Handle get_HotSpotJVMCIRuntime(TRAPS) { initialize_JVMCI(CHECK_(Handle())); - return Handle(JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance)); + return Handle(THREAD, JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance)); } static jobject get_HotSpotJVMCIRuntime_jobject(TRAPS) { diff --git a/hotspot/src/share/vm/memory/oopFactory.cpp b/hotspot/src/share/vm/memory/oopFactory.cpp index f8d14feff4e..2df89bccb1c 100644 --- a/hotspot/src/share/vm/memory/oopFactory.cpp +++ b/hotspot/src/share/vm/memory/oopFactory.cpp @@ -85,3 +85,13 @@ objArrayOop oopFactory::new_objArray(Klass* klass, int length, TRAPS) { return InstanceKlass::cast(klass)->allocate_objArray(1, length, THREAD); } } + +objArrayHandle oopFactory::new_objArray_handle(Klass* klass, int length, TRAPS) { + objArrayOop obj = new_objArray(klass, length, CHECK_(objArrayHandle())); + return objArrayHandle(THREAD, obj); +} + +typeArrayHandle oopFactory::new_byteArray_handle(int length, TRAPS) { + typeArrayOop obj = new_byteArray(length, CHECK_(typeArrayHandle())); + return typeArrayHandle(THREAD, obj); +} diff --git a/hotspot/src/share/vm/memory/oopFactory.hpp b/hotspot/src/share/vm/memory/oopFactory.hpp index d44e6907568..55e5c94cf74 100644 --- a/hotspot/src/share/vm/memory/oopFactory.hpp +++ b/hotspot/src/share/vm/memory/oopFactory.hpp @@ -66,6 +66,10 @@ class oopFactory: AllStatic { // Regular object arrays static objArrayOop new_objArray(Klass* klass, int length, TRAPS); + + // Helpers that return handles + static objArrayHandle new_objArray_handle(Klass* klass, int length, TRAPS); + static typeArrayHandle new_byteArray_handle(int length, TRAPS); }; #endif // SHARE_VM_MEMORY_OOPFACTORY_HPP diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index d56e8dd3226..ab66c902094 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -615,20 +615,22 @@ oop Universe::gen_out_of_memory_error(oop default_err) { // return default return default_err; } else { + Thread* THREAD = Thread::current(); + Handle default_err_h(THREAD, default_err); // get the error object at the slot and set set it to NULL so that the // array isn't keeping it alive anymore. - oop exc = preallocated_out_of_memory_errors()->obj_at(next); - assert(exc != NULL, "slot has been used already"); + Handle exc(THREAD, preallocated_out_of_memory_errors()->obj_at(next)); + assert(exc() != NULL, "slot has been used already"); preallocated_out_of_memory_errors()->obj_at_put(next, NULL); // use the message from the default error - oop msg = java_lang_Throwable::message(default_err); + oop msg = java_lang_Throwable::message(default_err_h()); assert(msg != NULL, "no message"); - java_lang_Throwable::set_message(exc, msg); + java_lang_Throwable::set_message(exc(), msg); // populate the stack trace and return it. java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(exc); - return exc; + return exc(); } } diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index d9107ad706d..782e2376f40 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -107,7 +107,7 @@ void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_kl assert((module_entry != NULL) || ((module_entry == NULL) && !ModuleEntryTable::javabase_defined()), "module entry not available post " JAVA_BASE_NAME " definition"); oop module = (module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL; - java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(NULL), CHECK); + java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(), CHECK); } GrowableArray* ArrayKlass::compute_secondary_supers(int num_extra_slots) { diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index a30d19dd685..04ae2104ffe 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -282,7 +282,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& // the lock, so that when the losing writer returns, he can use the linked // cache entry. - objArrayHandle resolved_references = cpool->resolved_references(); + objArrayHandle resolved_references(Thread::current(), cpool->resolved_references()); // Use the resolved_references() lock for this cpCache entry. // resolved_references are created for all classes with Invokedynamic, MethodHandle // or MethodType constant pool cache entries. diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 5b2180f945c..fcaaad0fa34 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -434,8 +434,9 @@ void InstanceKlass::fence_and_clear_init_lock() { void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) { EXCEPTION_MARK; - oop init_lock = this_k->init_lock(); - ObjectLocker ol(init_lock, THREAD, init_lock != NULL); + HandleMark hm(THREAD); + Handle init_lock(THREAD, this_k->init_lock()); + ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); // abort if someone beat us to the initialization if (!this_k->is_not_initialized()) return; // note: not equivalent to is_initialized() @@ -469,7 +470,6 @@ void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) { // Note: implementation moved to static method to expose the this pointer. void InstanceKlass::initialize(TRAPS) { if (this->should_be_initialized()) { - HandleMark hm(THREAD); instanceKlassHandle this_k(THREAD, this); initialize_impl(this_k, CHECK); // Note: at this point the class may be initialized @@ -501,7 +501,6 @@ void InstanceKlass::unlink_class() { void InstanceKlass::link_class(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - HandleMark hm(THREAD); instanceKlassHandle this_k(THREAD, this); link_class_impl(this_k, true, CHECK); } @@ -512,7 +511,6 @@ void InstanceKlass::link_class(TRAPS) { bool InstanceKlass::link_class_or_fail(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - HandleMark hm(THREAD); instanceKlassHandle this_k(THREAD, this); link_class_impl(this_k, false, CHECK_false); } @@ -565,7 +563,6 @@ bool InstanceKlass::link_class_impl( Array* interfaces = this_k->local_interfaces(); int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) { - HandleMark hm(THREAD); instanceKlassHandle ih(THREAD, interfaces->at(index)); link_class_impl(ih, throw_verifyerror, CHECK_false); } @@ -586,11 +583,13 @@ bool InstanceKlass::link_class_impl( // verification & rewriting { - oop init_lock = this_k->init_lock(); - ObjectLocker ol(init_lock, THREAD, init_lock != NULL); + HandleMark hm(THREAD); + Handle init_lock(THREAD, this_k->init_lock()); + ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); // rewritten will have been set if loader constraint error found // on an earlier link attempt // don't verify or rewrite if already rewritten + // if (!this_k->is_linked()) { if (!this_k->is_rewritten()) { @@ -700,6 +699,8 @@ void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAP } void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { + HandleMark hm(THREAD); + // Make sure klass is linked (verified) before initialization // A class could already be verified, since it has been reflected upon. this_k->link_class(CHECK); @@ -711,8 +712,8 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // refer to the JVM book page 47 for description of steps // Step 1 { - oop init_lock = this_k->init_lock(); - ObjectLocker ol(init_lock, THREAD, init_lock != NULL); + Handle init_lock(THREAD, this_k->init_lock()); + ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); Thread *self = THREAD; // it's passed the current thread @@ -853,14 +854,14 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) } void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) { - oop init_lock = this_k->init_lock(); - if (init_lock != NULL) { + Handle init_lock(THREAD, this_k->init_lock()); + if (init_lock() != NULL) { ObjectLocker ol(init_lock, THREAD); this_k->set_init_state(state); this_k->fence_and_clear_init_lock(); ol.notify_all(CHECK); } else { - assert(init_lock != NULL, "The initialization state should never be set twice"); + assert(init_lock() != NULL, "The initialization state should never be set twice"); this_k->set_init_state(state); } } @@ -2300,7 +2301,8 @@ ModuleEntry* InstanceKlass::module() const { void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) { // ensure java/ packages only loaded by boot or platform builtin loaders - check_prohibited_package(name(), loader_data->class_loader(), CHECK); + Handle class_loader(THREAD, loader_data->class_loader()); + check_prohibited_package(name(), class_loader, CHECK); TempNewSymbol pkg_name = package_from_name(name(), CHECK); @@ -2460,7 +2462,7 @@ void InstanceKlass::check_prohibited_package(Symbol* class_name, TRAPS) { ResourceMark rm(THREAD); if (!class_loader.is_null() && - !SystemDictionary::is_platform_class_loader(class_loader) && + !SystemDictionary::is_platform_class_loader(class_loader()) && class_name != NULL && strncmp(class_name->as_C_string(), JAVAPKG, JAVAPKG_LEN) == 0) { TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK); @@ -3140,7 +3142,7 @@ void InstanceKlass::print_loading_log(LogLevel::type type, // source is unknown } } else { - Handle class_loader(loader_data->class_loader()); + oop class_loader = loader_data->class_loader(); log->print(" source: %s", class_loader->klass()->external_name()); } } else { diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index ebc59953842..d789bd04e1c 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -519,7 +519,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec // Only recreate it if not present. A previous attempt to restore may have // gotten an OOM later but keep the mirror if it was created. if (java_mirror() == NULL) { - Handle loader = loader_data->class_loader(); + Handle loader(THREAD, loader_data->class_loader()); ModuleEntry* module_entry = NULL; Klass* k = this; if (k->is_objArray_klass()) { diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index 48e7c337abe..1e7e6b5334b 100644 --- a/hotspot/src/share/vm/oops/oop.cpp +++ b/hotspot/src/share/vm/oops/oop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -96,9 +96,10 @@ void oopDesc::verify() { intptr_t oopDesc::slow_identity_hash() { // slow case; we have to acquire the micro lock in order to locate the header + Thread* THREAD = Thread::current(); ResetNoHandleMark rnm; // Might be called from LEAF/QUICK ENTRY - HandleMark hm; - Handle object(this); + HandleMark hm(THREAD); + Handle object(THREAD, this); return ObjectSynchronizer::identity_hash_value_for(object); } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 68cba128660..3bf2bcf0c37 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -549,9 +549,9 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL); } - Handle result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, - start_index, frames_array_h, CHECK_NULL); - return JNIHandles::make_local(env, result()); + oop result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, + start_index, frames_array_h, CHECK_NULL); + return JNIHandles::make_local(env, result); JVM_END @@ -684,7 +684,7 @@ JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) // This can safepoint and redefine method, so need both new_obj and method // in a handle, for two different reasons. new_obj can move, method can be // deleted if nothing is using it on the stack. - m->method_holder()->add_member_name(new_obj()); + m->method_holder()->add_member_name(new_obj); } } diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index dd241a014d7..f3018e13c0b 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -598,7 +598,8 @@ JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { jclass JvmtiEnvBase::get_jni_class_non_null(Klass* k) { assert(k != NULL, "k != NULL"); - return (jclass)jni_reference(k->java_mirror()); + Thread *thread = Thread::current(); + return (jclass)jni_reference(Handle(thread, k->java_mirror())); } // @@ -693,7 +694,7 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThre *monitor_ptr = NULL; } else { HandleMark hm; - Handle hobj(obj); + Handle hobj(Thread::current(), obj); *monitor_ptr = jni_reference(calling_thread, hobj); } return JVMTI_ERROR_NONE; @@ -813,7 +814,7 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread if (err != JVMTI_ERROR_NONE) { return err; } - Handle hobj(obj); + Handle hobj(Thread::current(), obj); jmsdi->monitor = jni_reference(calling_thread, hobj); jmsdi->stack_depth = stack_depth; owned_monitors_list->append(jmsdi); @@ -953,6 +954,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec HandleMark hm; Handle hobj; + Thread* current_thread = Thread::current(); bool at_safepoint = SafepointSynchronize::is_at_safepoint(); // Check arguments @@ -961,7 +963,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER); - hobj = Handle(mirror); + hobj = Handle(current_thread, mirror); } JavaThread *owning_thread = NULL; @@ -1027,7 +1029,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } HandleMark hm; - Handle th(owning_thread->threadObj()); + Handle th(current_thread, owning_thread->threadObj()); ret.owner = (jthread)jni_reference(calling_thread, th); } // implied else: no owner @@ -1110,7 +1112,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec deallocate((unsigned char*)ret.notify_waiters); return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } - Handle th(pending_thread->threadObj()); + Handle th(current_thread, pending_thread->threadObj()); ret.waiters[i] = (jthread)jni_reference(calling_thread, th); } } @@ -1130,7 +1132,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // If the thread was found on the ObjectWaiter list, then // it has not been notified. This thread can't change the // state of the monitor so it doesn't need to be suspended. - Handle th(wjava_thread->threadObj()); + Handle th(current_thread, wjava_thread->threadObj()); ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th); ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th); } @@ -1362,7 +1364,7 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa // Check that the jobject class matches the return type signature. jobject jobj = value.l; if (tos == atos && jobj != NULL) { // NULL reference is allowed - Handle ob_h = Handle(current_thread, JNIHandles::resolve_external_guard(jobj)); + Handle ob_h(current_thread, JNIHandles::resolve_external_guard(jobj)); NULL_CHECK(ob_h, JVMTI_ERROR_INVALID_OBJECT); KlassHandle ob_kh = KlassHandle(current_thread, ob_h()->klass()); NULL_CHECK(ob_kh, JVMTI_ERROR_INVALID_OBJECT); @@ -1425,7 +1427,7 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState return JVMTI_ERROR_OPAQUE_FRAME; } } - Handle ret_ob_h = Handle(); + Handle ret_ob_h; jvmtiError err = check_top_frame(current_thread, java_thread, value, tos, &ret_ob_h); if (err != JVMTI_ERROR_NONE) { return err; @@ -1479,7 +1481,7 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { _error = err; return; } - Handle hobj(obj); + Handle hobj(Thread::current(), obj); jmsdi->monitor = _env->jni_reference(_calling_thread, hobj); // stack depth is unknown for this monitor. jmsdi->stack_depth = -1; diff --git a/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp b/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp index 9546652cce2..0153c949909 100644 --- a/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -36,15 +36,16 @@ class LoadedClassesClosure : public KlassClosure { private: Stack _classStack; JvmtiEnv* _env; + Thread* _cur_thread; public: - LoadedClassesClosure(JvmtiEnv* env) { - _env = env; + LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _cur_thread(thread), _env(env) { + assert(_cur_thread == Thread::current(), "must be current thread"); } void do_klass(Klass* k) { // Collect all jclasses - _classStack.push((jclass) _env->jni_reference(k->java_mirror())); + _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); } int extract(jclass* result_list) { @@ -225,8 +226,9 @@ class JvmtiGetLoadedClassesClosure : public StackObj { if (that->available()) { oop class_loader = loader_data->class_loader(); if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { + Thread *thread = Thread::current(); for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - oop mirror = l->java_mirror(); + Handle mirror(thread, l->java_mirror()); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } @@ -250,8 +252,9 @@ class JvmtiGetLoadedClassesClosure : public StackObj { JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); assert(that->available(), "no list"); + Thread *thread = Thread::current(); for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - oop mirror = l->java_mirror(); + Handle mirror(thread, l->java_mirror()); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } @@ -262,7 +265,7 @@ class JvmtiGetLoadedClassesClosure : public StackObj { jvmtiError JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) { - LoadedClassesClosure closure(env); + LoadedClassesClosure closure(Thread::current(), env); { // To get a consistent list of classes we need MultiArray_lock to ensure // array classes aren't created. diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index 20905222276..072a0912d4b 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -694,7 +694,7 @@ bool VM_GetOrSetLocal::check_slot_type(javaVFrame* jvf) { JavaThread* cur_thread = JavaThread::current(); HandleMark hm(cur_thread); - Handle obj = Handle(cur_thread, JNIHandles::resolve_external_guard(jobj)); + Handle obj(cur_thread, JNIHandles::resolve_external_guard(jobj)); NULL_CHECK(obj, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); KlassHandle ob_kh = KlassHandle(cur_thread, obj->klass()); NULL_CHECK(ob_kh, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); @@ -777,7 +777,7 @@ void VM_GetOrSetLocal::doit() { case T_FLOAT: locals->set_float_at (_index, _value.f); break; case T_DOUBLE: locals->set_double_at(_index, _value.d); break; case T_OBJECT: { - Handle ob_h(JNIHandles::resolve_external_guard(_value.l)); + Handle ob_h(Thread::current(), JNIHandles::resolve_external_guard(_value.l)); locals->set_obj_at (_index, ob_h); break; } diff --git a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp index 06a091bce9e..b025161a413 100644 --- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp +++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -418,7 +418,7 @@ class RedefineVerifyMark : public StackObj { JvmtiThreadState *state) : _state(state), _scratch_class(*scratch_class) { _state->set_class_versions_map(the_class, scratch_class); - _scratch_mirror = Handle(_scratch_class->java_mirror()); + _scratch_mirror = Handle(Thread::current(), _scratch_class->java_mirror()); (*scratch_class)->set_java_mirror((*the_class)->java_mirror()); } diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 96ccab1071c..ce6d85691a4 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -833,8 +833,8 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { } if (!have_name) { //not java_lang_String::create_from_symbol; let's intern member names - Handle name = StringTable::intern(m->name(), CHECK); - java_lang_invoke_MemberName::set_name(mname(), name()); + oop name = StringTable::intern(m->name(), CHECK); + java_lang_invoke_MemberName::set_name(mname(), name); } if (!have_type) { Handle type = java_lang_String::create_from_symbol(m->signature(), CHECK); @@ -857,14 +857,14 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { } if (!have_name) { //not java_lang_String::create_from_symbol; let's intern member names - Handle name = StringTable::intern(fd.name(), CHECK); - java_lang_invoke_MemberName::set_name(mname(), name()); + oop name = StringTable::intern(fd.name(), CHECK); + java_lang_invoke_MemberName::set_name(mname(), name); } if (!have_type) { // If it is a primitive field type, don't mess with short strings like "I". - Handle type = field_signature_type_or_null(fd.signature()); + Handle type (THREAD, field_signature_type_or_null(fd.signature())); if (type.is_null()) { - java_lang_String::create_from_symbol(fd.signature(), CHECK); + type = java_lang_String::create_from_symbol(fd.signature(), CHECK); } java_lang_invoke_MemberName::set_type(mname(), type()); } @@ -1019,7 +1019,7 @@ void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) { assert_lock_strong(Compile_lock); int marked = 0; - CallSiteDepChange changes(call_site(), target()); + CallSiteDepChange changes(call_site, target); { NoSafepointVerifier nsv; MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); @@ -1283,7 +1283,7 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); intptr_t vmindex = java_lang_invoke_MemberName::vmindex(mname()); Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname()); - objArrayHandle result = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL); + objArrayHandle result = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 2, CHECK_NULL); jvalue vmindex_value; vmindex_value.j = (long)vmindex; oop x = java_lang_boxing_object::create(T_LONG, &vmindex_value, CHECK_NULL); result->obj_at_put(0, x); diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index e130127318a..d2778041788 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -274,7 +274,7 @@ objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArraymethod_holder()->java_mirror()); - java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci()); + java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci()); } // Fill LiveStackFrameInfo with locals, monitors, and expressions diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 0440fabb9c2..c838c38e521 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -124,8 +124,8 @@ public: }; WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) - Handle h_name = JNIHandles::resolve(name); - if (h_name.is_null()) return false; + oop h_name = JNIHandles::resolve(name); + if (h_name == NULL) return false; Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false); TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return @@ -1914,7 +1914,7 @@ JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass)) if (WhiteBoxAPI) { // Make sure that wbclass is loaded by the null classloader instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass()); - Handle loader(ikh->class_loader()); + Handle loader(THREAD, ikh->class_loader()); if (loader.is_null()) { WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0])); WhiteBox::register_extended(env, wbclass, thread); diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index e3b88640768..3fd03c90b6d 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -451,7 +451,6 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread // Compute whether the root vframe returns a float or double value. BasicType return_type; { - HandleMark hm; methodHandle method(thread, array->element(0)->method()); Bytecode_invoke invoke = Bytecode_invoke_check(method, array->element(0)->bci()); return_type = invoke.is_valid() ? invoke.result_type() : T_ILLEGAL; @@ -799,7 +798,7 @@ Deoptimization::DeoptAction Deoptimization::_unloaded_action #if defined(COMPILER2) || INCLUDE_JVMCI bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray* objects, TRAPS) { - Handle pending_exception(thread->pending_exception()); + Handle pending_exception(THREAD, thread->pending_exception()); const char* exception_file = thread->exception_file(); int exception_line = thread->exception_line(); thread->clear_pending_exception(); @@ -1109,7 +1108,7 @@ void Deoptimization::relock_objects(GrowableArray* monitors, JavaT if (mon_info->eliminated()) { assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed"); if (!mon_info->owner_is_scalar_replaced()) { - Handle obj = Handle(mon_info->owner()); + Handle obj(thread, mon_info->owner()); markOop mark = obj->mark(); if (UseBiasedLocking && mark->has_bias_pattern()) { // New allocated objects may have the mark set to anonymously biased. @@ -1246,10 +1245,11 @@ void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* static void collect_monitors(compiledVFrame* cvf, GrowableArray* objects_to_revoke) { GrowableArray* monitors = cvf->monitors(); + Thread* thread = Thread::current(); for (int i = 0; i < monitors->length(); i++) { MonitorInfo* mon_info = monitors->at(i); if (!mon_info->eliminated() && mon_info->owner() != NULL) { - objects_to_revoke->append(Handle(mon_info->owner())); + objects_to_revoke->append(Handle(thread, mon_info->owner())); } } } diff --git a/hotspot/src/share/vm/runtime/handles.cpp b/hotspot/src/share/vm/runtime/handles.cpp index a8b6f8b9f01..71ef098459c 100644 --- a/hotspot/src/share/vm/runtime/handles.cpp +++ b/hotspot/src/share/vm/runtime/handles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -37,15 +37,6 @@ oop* HandleArea::allocate_handle(oop obj) { assert(obj->is_oop(), "not an oop: " INTPTR_FORMAT, p2i(obj)); return real_allocate_handle(obj); } - -Handle::Handle(Thread* thread, oop obj) { - assert(thread == Thread::current(), "sanity check"); - if (obj == NULL) { - _handle = NULL; - } else { - _handle = thread->handle_area()->allocate_handle(obj); - } -} #endif // Copy constructors and destructors for metadata handles diff --git a/hotspot/src/share/vm/runtime/handles.hpp b/hotspot/src/share/vm/runtime/handles.hpp index 6af1c976b84..1a132761ed7 100644 --- a/hotspot/src/share/vm/runtime/handles.hpp +++ b/hotspot/src/share/vm/runtime/handles.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -45,8 +45,7 @@ class Klass; // Handles are declared in a straight-forward manner, e.g. // // oop obj = ...; -// Handle h1(obj); // allocate new handle -// Handle h2(thread, obj); // faster allocation when current thread is known +// Handle h2(thread, obj); // allocate a new handle in thread // Handle h3; // declare handle only, no allocation occurs // ... // h3 = h1; // make h3 refer to same indirection as h1 @@ -55,11 +54,7 @@ class Klass; // // Handles are specialized for different oop types to provide extra type // information and avoid unnecessary casting. For each oop type xxxOop -// there is a corresponding handle called xxxHandle, e.g. -// -// oop Handle -// Method* methodHandle -// instanceOop instanceHandle +// there is a corresponding handle called xxxHandle. //------------------------------------------------------------------------------------------------------------------------ // Base class for all handles. Provides overloading of frequently @@ -76,7 +71,6 @@ class Handle VALUE_OBJ_CLASS_SPEC { public: // Constructors Handle() { _handle = NULL; } - Handle(oop obj); Handle(Thread* thread, oop obj); // General access @@ -113,10 +107,6 @@ class Handle VALUE_OBJ_CLASS_SPEC { public: \ /* Constructors */ \ type##Handle () : Handle() {} \ - type##Handle (type##Oop obj) : Handle((oop)obj) { \ - assert(is_null() || ((oop)obj)->is_a(), \ - "illegal type"); \ - } \ type##Handle (Thread* thread, type##Oop obj) : Handle(thread, (oop)obj) { \ assert(is_null() || ((oop)obj)->is_a(), "illegal type"); \ } \ @@ -277,7 +267,7 @@ class HandleArea: public Arena { // Handle h; // { // HandleMark hm; -// h = Handle(obj); +// h = Handle(THREAD, obj); // } // h()->print(); // WRONG, h destroyed by HandleMark destructor. // diff --git a/hotspot/src/share/vm/runtime/handles.inline.hpp b/hotspot/src/share/vm/runtime/handles.inline.hpp index ede935dbd15..2e205e0a557 100644 --- a/hotspot/src/share/vm/runtime/handles.inline.hpp +++ b/hotspot/src/share/vm/runtime/handles.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -31,16 +31,6 @@ // these inline functions are in a separate file to break an include cycle // between Thread and Handle -inline Handle::Handle(oop obj) { - if (obj == NULL) { - _handle = NULL; - } else { - _handle = Thread::current()->handle_area()->allocate_handle(obj); - } -} - - -#ifndef ASSERT inline Handle::Handle(Thread* thread, oop obj) { assert(thread == Thread::current(), "sanity check"); if (obj == NULL) { @@ -49,7 +39,6 @@ inline Handle::Handle(Thread* thread, oop obj) { _handle = thread->handle_area()->allocate_handle(obj); } } -#endif // ASSERT // Constructors for metadata handles #define DEF_METADATA_HANDLE_FN(name, type) \ diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 0c7187cf745..f156c698caf 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -99,9 +99,6 @@ int compare_methods(Method** a, Method** b) { void collect_profiled_methods(Method* m) { Thread* thread = Thread::current(); - // This HandleMark prevents a huge amount of handles from being added - // to the metadata_handles() array on the thread. - HandleMark hm(thread); methodHandle mh(thread, m); if ((m->method_data() != NULL) && (PrintMethodData || CompilerOracle::should_print(mh))) { diff --git a/hotspot/src/share/vm/runtime/stackValue.cpp b/hotspot/src/share/vm/runtime/stackValue.cpp index a0e6f5104f8..e4cb824b43a 100644 --- a/hotspot/src/share/vm/runtime/stackValue.cpp +++ b/hotspot/src/share/vm/runtime/stackValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -103,7 +103,7 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r value.noop = *(narrowOop*) value_addr; } // Decode narrowoop and wrap a handle around the oop - Handle h(oopDesc::decode_heap_oop(value.noop)); + Handle h(Thread::current(), oopDesc::decode_heap_oop(value.noop)); return new StackValue(h); } #endif @@ -118,7 +118,7 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r val = (oop)NULL; } #endif - Handle h(val); // Wrap a handle around the oop + Handle h(Thread::current(), val); // Wrap a handle around the oop return new StackValue(h); } case Location::addr: { diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index b9004d62860..a596a4e7b57 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -1762,7 +1762,7 @@ class ReleaseJavaMonitorsClosure: public MonitorClosure { if (mid->owner() == THREAD) { if (ObjectMonitor::Knob_VerifyMatch != 0) { ResourceMark rm; - Handle obj((oop) mid->object()); + Handle obj(THREAD, (oop) mid->object()); tty->print("INFO: unexpected locked object:"); javaVFrame::print_locked_object_class_name(tty, obj, "locked"); fatal("exiting JavaThread=" INTPTR_FORMAT diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index 7d9a7b39e6e..e084a87e8b5 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -155,7 +155,8 @@ void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, co } void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { - ResourceMark rm; + Thread* THREAD = Thread::current(); + ResourceMark rm(THREAD); // If this is the first frame and it is java.lang.Object.wait(...) // then print out the receiver. Locals are not always available, @@ -201,8 +202,8 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { // format below for lockbits matches this one. st->print("\t- eliminated (a %s)", k->external_name()); } else { - oop obj = monitor->owner(); - if (obj != NULL) { + Handle obj(THREAD, monitor->owner()); + if (obj() != NULL) { print_locked_object_class_name(st, obj, "eliminated"); } } @@ -252,7 +253,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { mark = NULL; } } - print_locked_object_class_name(st, monitor->owner(), lock_state); + print_locked_object_class_name(st, Handle(THREAD, monitor->owner()), lock_state); if (ObjectMonitor::Knob_Verbose && mark != NULL) { st->print("\t- lockbits="); mark->print_on(st); @@ -309,7 +310,7 @@ static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_ // categorize using oop_mask if (oop_mask.is_oop(index)) { // reference (oop) "r" - Handle h(addr != NULL ? (*(oop*)addr) : (oop)NULL); + Handle h(Thread::current(), addr != NULL ? (*(oop*)addr) : (oop)NULL); return new StackValue(h); } // value (integer) "v" diff --git a/hotspot/src/share/vm/runtime/vframe_hp.cpp b/hotspot/src/share/vm/runtime/vframe_hp.cpp index 30b08a003b9..2ff4b28dfee 100644 --- a/hotspot/src/share/vm/runtime/vframe_hp.cpp +++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -106,7 +106,7 @@ StackValueCollection* compiledVFrame::locals() const { break; case T_OBJECT: { - Handle obj((oop)val->value().l); + Handle obj(Thread::current(), (oop)val->value().l); result->set_obj_at(val->index(), obj); } break; @@ -227,7 +227,7 @@ GrowableArray* compiledVFrame::monitors() const { // Put klass for scalar replaced object. ScopeValue* kv = ((ObjectValue *)ov)->klass(); assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object"); - Handle k(((ConstantOopReadValue*)kv)->value()()); + Handle k(Thread::current(), ((ConstantOopReadValue*)kv)->value()()); assert(java_lang_Class::is_instance(k()), "must be"); result->push(new MonitorInfo(k(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated(), true)); diff --git a/hotspot/src/share/vm/services/gcNotifier.cpp b/hotspot/src/share/vm/services/gcNotifier.cpp index 3130fdbfcc1..b037fd24a39 100644 --- a/hotspot/src/share/vm/services/gcNotifier.cpp +++ b/hotspot/src/share/vm/services/gcNotifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -178,7 +178,7 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR &constructor_args, CHECK_NH); - return Handle(gcInfo_instance()); + return Handle(THREAD, gcInfo_instance()); } void GCNotifier::sendNotification(TRAPS) { diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index 9cb5e2ce5c3..e25473e0ad5 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -1953,7 +1953,8 @@ JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live)) THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "Output file name cannot be null.", -1); } - char* name = java_lang_String::as_platform_dependent_str(on, CHECK_(-1)); + Handle onhandle(THREAD, on); + char* name = java_lang_String::as_platform_dependent_str(onhandle, CHECK_(-1)); if (name == NULL) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "Output file name cannot be null.", -1); diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index 3bd7a9f70ca..69b50bc13df 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -166,7 +166,7 @@ Handle ThreadService::get_current_contended_monitor(JavaThread* thread) { // If obj == NULL, then ObjectMonitor is raw which doesn't count. } - Handle h(obj); + Handle h(Thread::current(), obj); return h; } diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index 2bb3d77e6a5..ba34813b212 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -129,7 +129,7 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, S // therefore the exception oop should be in the oopmap. void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) { assert(exception != NULL, "exception should not be NULL"); - Handle h_exception = Handle(thread, exception); + Handle h_exception(thread, exception); _throw(thread, file, line, h_exception); } @@ -496,7 +496,7 @@ void Exceptions::debug_check_abort(Handle exception, const char* message) { void Exceptions::debug_check_abort_helper(Handle exception, const char* message) { ResourceMark rm; if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) { - oop msg = java_lang_Throwable::message(exception); + oop msg = java_lang_Throwable::message(exception()); if (msg != NULL) { message = java_lang_String::as_utf8_string(msg); } From 8698102379a6366fd3e282a388b75629d8f5530f Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 27 Jan 2017 10:22:19 +0100 Subject: [PATCH 10/86] 8173465: Introduce NearLabel for branches known to be short Reviewed-by: kvn --- hotspot/src/cpu/s390/vm/assembler_s390.hpp | 2 -- hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp | 17 ++++++++++++++--- hotspot/src/share/vm/asm/assembler.hpp | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/hotspot/src/cpu/s390/vm/assembler_s390.hpp b/hotspot/src/cpu/s390/vm/assembler_s390.hpp index 0873d71b00e..8a7ae9d0756 100644 --- a/hotspot/src/cpu/s390/vm/assembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/assembler_s390.hpp @@ -28,8 +28,6 @@ #undef LUCY_DBG -#define NearLabel Label - // Immediate is an abstraction to represent the various immediate // operands which exist on z/Architecture. Neither this class nor // instances hereof have an own state. It consists of methods only. diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp index a7cbd706255..015bccc2aa3 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -1616,6 +1616,8 @@ void MacroAssembler::branch_optimized(Assembler::branch_condition cond, Label& b if (branch_target.is_bound()) { address branch_addr = target(branch_target); branch_optimized(cond, branch_addr); + } else if (branch_target.is_near()) { + z_brc(cond, branch_target); // Caller assures that the target will be in range for z_brc. } else { z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time. } @@ -1674,7 +1676,8 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, bool has_sign) { address branch_origin = pc(); bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2)); - bool is_RelAddr16 = (branch_target.is_bound() && + bool is_RelAddr16 = branch_target.is_near() || + (branch_target.is_bound() && RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin)); unsigned int casenum = (len64?2:0)+(has_sign?0:1); @@ -1744,13 +1747,21 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, Label& branch_target, bool len64, bool has_sign) { - unsigned int casenum = (len64?2:0)+(has_sign?0:1); + unsigned int casenum = (len64 ? 2 : 0) + (has_sign ? 0 : 1); if (branch_target.is_bound()) { address branch_addr = target(branch_target); compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign); } else { - { + if (VM_Version::has_CompareBranch() && branch_target.is_near()) { + switch (casenum) { + case 0: z_crj( r1, r2, cond, branch_target); break; + case 1: z_clrj( r1, r2, cond, branch_target); break; + case 2: z_cgrj( r1, r2, cond, branch_target); break; + case 3: z_clgrj(r1, r2, cond, branch_target); break; + default: ShouldNotReachHere(); break; + } + } else { switch (casenum) { case 0: z_cr( r1, r2); break; case 1: z_clr(r1, r2); break; diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index a7b523d6d81..eed6fbd1f4e 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -93,6 +93,10 @@ class Label VALUE_OBJ_CLASS_SPEC { GrowableArray* _patch_overflow; Label(const Label&) { ShouldNotReachHere(); } + protected: + + // The label will be bound to a location near its users. + bool _is_near; public: @@ -126,6 +130,10 @@ class Label VALUE_OBJ_CLASS_SPEC { bool is_unbound() const { return _loc == -1 && _patch_index > 0; } bool is_unused() const { return _loc == -1 && _patch_index == 0; } + // The label will be bound to a location near its users. Users can + // optimize on this information, e.g. generate short branches. + bool is_near() { return _is_near; } + /** * Adds a reference to an unresolved displacement instruction to * this unbound label @@ -145,6 +153,7 @@ class Label VALUE_OBJ_CLASS_SPEC { _loc = -1; _patch_index = 0; _patch_overflow = NULL; + _is_near = false; } Label() { @@ -152,6 +161,13 @@ class Label VALUE_OBJ_CLASS_SPEC { } }; +// A NearLabel must be bound to a location near its users. Users can +// optimize on this information, e.g. generate short branches. +class NearLabel : public Label { + public: + NearLabel() : Label() { _is_near = true; } +}; + // A union type for code which has to assemble both constant and // non-constant operands, when the distinction cannot be made // statically. From 9b2f8340ec9fd58e9096ba469b32155fb673e1c9 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 27 Jan 2017 11:19:52 +0100 Subject: [PATCH 11/86] 8173470: [C2] Mask shift operands in ideal graph Reviewed-by: lucy, kvn --- hotspot/src/cpu/s390/vm/s390.ad | 3 + hotspot/src/share/vm/opto/mulnode.cpp | 137 ++++++++++++++------------ 2 files changed, 78 insertions(+), 62 deletions(-) diff --git a/hotspot/src/cpu/s390/vm/s390.ad b/hotspot/src/cpu/s390/vm/s390.ad index 8ab6a5026d3..7f7dc767d0b 100644 --- a/hotspot/src/cpu/s390/vm/s390.ad +++ b/hotspot/src/cpu/s390/vm/s390.ad @@ -6770,6 +6770,7 @@ instruct sllI_reg_imm(iRegI dst, iRegI src, immI nbits) %{ format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %} ins_encode %{ int Nbit = $nbits$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6843,6 +6844,7 @@ instruct sraI_reg_imm(iRegI dst, immI src, flagsReg cr) %{ format %{ "SRA $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6895,6 +6897,7 @@ instruct srlI_reg_imm(iRegI dst, immI src) %{ format %{ "SRL $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 0bdde2614f3..5a74bed0999 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -630,23 +630,42 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { } //============================================================================= + +static int getShiftCon(PhaseGVN *phase, Node *shiftNode, int retVal) { + const Type *t = phase->type(shiftNode->in(2)); + if (t == Type::TOP) return retVal; // Right input is dead. + const TypeInt *t2 = t->isa_int(); + if (!t2 || !t2->is_con()) return retVal; // Right input is a constant. + + return t2->get_con(); +} + +static int maskShiftAmount(PhaseGVN *phase, Node *shiftNode, int nBits) { + int shift = getShiftCon(phase, shiftNode, 0); + int maskedShift = shift & (nBits - 1); + + if (maskedShift == 0) return 0; // Let Identity() handle 0 shift count. + + if (shift != maskedShift) { + shiftNode->set_req(2, phase->intcon(maskedShift)); // Replace shift count with masked value. + } + + return maskedShift; +} + //------------------------------Identity--------------------------------------- Node* LShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerInt - 1 ) ) == 0 ) ? in(1) : this; + return ((getShiftCon(phase, this, -1) & (BitsPerJavaInteger - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)< X<type( in(2) ); - if( t == Type::TOP ) return NULL; // Right input is dead - const TypeInt *t2 = t->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerInt - 1 ); // masked shift count - - if ( con == 0 ) return NULL; // let Identity() handle 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (con == 0) { + return NULL; + } // Left input is an add of a constant? Node *add1 = in(1); @@ -744,21 +763,17 @@ const Type* LShiftINode::Value(PhaseGVN* phase) const { //============================================================================= //------------------------------Identity--------------------------------------- Node* LShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + return ((getShiftCon(phase, this, -1) & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)< X<type( in(2) ); - if( t == Type::TOP ) return NULL; // Right input is dead - const TypeInt *t2 = t->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerLong - 1 ); // masked shift count - - if ( con == 0 ) return NULL; // let Identity() handle 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaLong); + if (con == 0) { + return NULL; + } // Left input is an add of a constant? Node *add1 = in(1); @@ -853,26 +868,24 @@ const Type* LShiftLNode::Value(PhaseGVN* phase) const { //============================================================================= //------------------------------Identity--------------------------------------- Node* RShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *t2 = phase->type(in(2))->isa_int(); - if( !t2 ) return this; - if ( t2->is_con() && ( t2->get_con() & ( BitsPerInt - 1 ) ) == 0 ) - return in(1); + int shift = getShiftCon(phase, this, -1); + if (shift == -1) return this; + if ((shift & (BitsPerJavaInteger - 1)) == 0) return in(1); // Check for useless sign-masking - if( in(1)->Opcode() == Op_LShiftI && + if (in(1)->Opcode() == Op_LShiftI && in(1)->req() == 3 && - in(1)->in(2) == in(2) && - t2->is_con() ) { - uint shift = t2->get_con(); + in(1)->in(2) == in(2)) { shift &= BitsPerJavaInteger-1; // semantics of Java shifts // Compute masks for which this shifting doesn't change - int lo = (-1 << (BitsPerJavaInteger - shift-1)); // FFFF8000 + int lo = (-1 << (BitsPerJavaInteger - ((uint)shift)-1)); // FFFF8000 int hi = ~lo; // 00007FFF const TypeInt *t11 = phase->type(in(1)->in(1))->isa_int(); - if( !t11 ) return this; + if (!t11) return this; // Does actual value fit inside of mask? - if( lo <= t11->_lo && t11->_hi <= hi ) + if (lo <= t11->_lo && t11->_hi <= hi) { return in(1)->in(1); // Then shifting is a nop + } } return this; @@ -881,15 +894,13 @@ Node* RShiftINode::Identity(PhaseGVN* phase) { //------------------------------Ideal------------------------------------------ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Inputs may be TOP if they are dead. - const TypeInt *t1 = phase->type( in(1) )->isa_int(); - if( !t1 ) return NULL; // Left input is an integer - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant + const TypeInt *t1 = phase->type(in(1))->isa_int(); + if (!t1) return NULL; // Left input is an integer const TypeInt *t3; // type of in(1).in(2) - int shift = t2->get_con(); - shift &= BitsPerJavaInteger-1; // semantics of Java shifts - - if ( shift == 0 ) return NULL; // let Identity() handle 0 shift count + int shift = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (shift == 0) { + return NULL; + } // Check for (x & 0xFF000000) >> 24, whose mask can be made smaller. // Such expressions arise normally from shift chains like (byte)(x >> 24). @@ -1003,8 +1014,8 @@ const Type* RShiftINode::Value(PhaseGVN* phase) const { //============================================================================= //------------------------------Identity--------------------------------------- Node* RShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + const TypeInt *ti = phase->type(in(2))->isa_int(); // Shift count is an int. + return (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Value------------------------------------------ @@ -1061,25 +1072,25 @@ const Type* RShiftLNode::Value(PhaseGVN* phase) const { //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); - if ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerInt - 1 ) ) == 0 ) return in(1); + int shift = getShiftCon(phase, this, -1); + if ((shift & (BitsPerJavaInteger - 1)) == 0) return in(1); // Check for "((x << LogBytesPerWord) + (wordSize-1)) >> LogBytesPerWord" which is just "x". // Happens during new-array length computation. // Safe if 'x' is in the range [0..(max_int>>LogBytesPerWord)] Node *add = in(1); - if( add->Opcode() == Op_AddI ) { - const TypeInt *t2 = phase->type(add->in(2))->isa_int(); - if( t2 && t2->is_con(wordSize - 1) && - add->in(1)->Opcode() == Op_LShiftI ) { - // Check that shift_counts are LogBytesPerWord + if (add->Opcode() == Op_AddI) { + const TypeInt *t2 = phase->type(add->in(2))->isa_int(); + if (t2 && t2->is_con(wordSize - 1) && + add->in(1)->Opcode() == Op_LShiftI) { + // Check that shift_counts are LogBytesPerWord. Node *lshift_count = add->in(1)->in(2); const TypeInt *t_lshift_count = phase->type(lshift_count)->isa_int(); - if( t_lshift_count && t_lshift_count->is_con(LogBytesPerWord) && - t_lshift_count == phase->type(in(2)) ) { + if (t_lshift_count && t_lshift_count->is_con(LogBytesPerWord) && + t_lshift_count == phase->type(in(2))) { Node *x = add->in(1)->in(1); const TypeInt *t_x = phase->type(x)->isa_int(); - if( t_x != NULL && 0 <= t_x->_lo && t_x->_hi <= (max_jint>>LogBytesPerWord) ) { + if (t_x != NULL && 0 <= t_x->_lo && t_x->_hi <= (max_jint>>LogBytesPerWord)) { return x; } } @@ -1091,10 +1102,11 @@ Node* URShiftINode::Identity(PhaseGVN* phase) { //------------------------------Ideal------------------------------------------ Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & 31; // Shift count is always masked - if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (con == 0) { + return NULL; + } + // We'll be wanting the right-shift amount as a mask of that many bits const int mask = right_n_bits(BitsPerJavaInteger - con); @@ -1117,7 +1129,8 @@ Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); - if( in1_op == Op_AddI ) { + const TypeInt *t2 = phase->type(in(2))->isa_int(); + if (in1_op == Op_AddI) { Node *lshl = add->in(1); if( lshl->Opcode() == Op_LShiftI && phase->type(lshl->in(2)) == t2 ) { @@ -1231,17 +1244,16 @@ const Type* URShiftINode::Value(PhaseGVN* phase) const { //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + return ((getShiftCon(phase, this, -1) & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerLong - 1 ); // Shift count is always masked - if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count - // note: mask computation below does not work for 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaLong); + if (con == 0) { + return NULL; + } + // We'll be wanting the right-shift amount as a mask of that many bits const jlong mask = jlong(max_julong >> con); @@ -1250,7 +1262,8 @@ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); - if( add->Opcode() == Op_AddL ) { + const TypeInt *t2 = phase->type(in(2))->isa_int(); + if (add->Opcode() == Op_AddL) { Node *lshl = add->in(1); if( lshl->Opcode() == Op_LShiftL && phase->type(lshl->in(2)) == t2 ) { From 804ff732cea743aa4667dd879cb588a1f92ffce5 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 8 Feb 2017 16:33:53 +0100 Subject: [PATCH 12/86] 8174199: ci replay doesn't reallocate static final fields of recorded klass Reviewed-by: kvn --- hotspot/src/share/vm/ci/ciReplay.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index 50a1dd37c3b..5fed56977b1 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -751,7 +751,7 @@ class CompileReplay : public StackObj { assert(k->is_initialized(), "must be"); - const char* field_name = parse_escaped_string();; + const char* field_name = parse_escaped_string(); const char* field_signature = parse_string(); fieldDescriptor fd; Symbol* name = SymbolTable::lookup(field_name, (int)strlen(field_name), CHECK); @@ -840,9 +840,8 @@ class CompileReplay : public StackObj { Handle value = java_lang_String::create_from_str(string_value, CHECK); java_mirror->obj_field_put(fd.offset(), value()); } else if (field_signature[0] == 'L') { - Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK); - KlassHandle kelem = resolve_klass(field_signature, CHECK); - oop value = InstanceKlass::cast(kelem())->allocate_instance(CHECK); + KlassHandle k = resolve_klass(string_value, CHECK); + oop value = InstanceKlass::cast(k())->allocate_instance(CHECK); java_mirror->obj_field_put(fd.offset(), value); } else { report_error("unhandled staticfield"); From 50d01f670b413c0e437b05d4e5eb9021415a1418 Mon Sep 17 00:00:00 2001 From: Bob Vandette Date: Thu, 9 Feb 2017 15:43:54 -0500 Subject: [PATCH 13/86] 8172670: AOT Platform Support for Windows and Mac OS X x64 Reviewed-by: kvn --- hotspot/make/lib/Lib-jdk.aot.gmk | 53 -- .../src/cpu/x86/vm/compiledIC_aot_x86_64.cpp | 4 +- .../jaotc/binformat/BinaryContainer.java | 44 +- .../tools/jaotc/binformat/ByteContainer.java | 6 +- .../jdk/tools/jaotc/binformat/Container.java} | 6 +- .../tools/jaotc/binformat/NativeSymbol.java} | 40 +- .../src/jdk/tools/jaotc/binformat/Symbol.java | 14 +- .../jdk/tools/jaotc/binformat/elf/Elf.java | 256 +++++++ .../jaotc/binformat/elf/ElfByteBuffer.java | 43 ++ .../jaotc/binformat/elf/ElfContainer.java | 85 +++ .../tools/jaotc/binformat/elf/ElfHeader.java | 78 ++ .../jaotc/binformat/elf/ElfRelocEntry.java | 51 ++ .../jaotc/binformat/elf/ElfRelocTable.java | 81 +++ .../tools/jaotc/binformat/elf/ElfSection.java | 181 +++++ .../tools/jaotc/binformat/elf/ElfSymbol.java | 57 ++ .../tools/jaotc/binformat/elf/ElfSymtab.java | 147 ++++ .../jaotc/binformat/elf/ElfTargetInfo.java | 83 +++ .../jaotc/binformat/elf/JELFRelocObject.java | 442 ++++++------ .../binformat/macho/JMachORelocObject.java | 474 ++++++++++++ .../tools/jaotc/binformat/macho/MachO.java | 307 ++++++++ .../binformat/macho/MachOByteBuffer.java | 44 ++ .../jaotc/binformat/macho/MachOContainer.java | 83 +++ .../jaotc/binformat/macho/MachODySymtab.java | 54 ++ .../jaotc/binformat/macho/MachOHeader.java | 60 ++ .../binformat/macho/MachORelocEntry.java | 65 ++ .../binformat/macho/MachORelocTable.java | 89 +++ .../jaotc/binformat/macho/MachOSection.java | 115 +++ .../jaotc/binformat/macho/MachOSegment.java | 56 ++ .../jaotc/binformat/macho/MachOSymbol.java | 54 ++ .../jaotc/binformat/macho/MachOSymtab.java | 211 ++++++ .../binformat/macho/MachOTargetInfo.java | 87 +++ .../jaotc/binformat/macho/MachOVersion.java | 49 ++ .../binformat/pecoff/JPECoffRelocObject.java | 422 +++++++++++ .../tools/jaotc/binformat/pecoff/PECoff.java | 200 ++++++ .../binformat/pecoff/PECoffByteBuffer.java} | 19 +- .../binformat/pecoff/PECoffContainer.java | 85 +++ .../jaotc/binformat/pecoff/PECoffHeader.java | 68 ++ .../binformat/pecoff/PECoffRelocEntry.java | 49 ++ .../binformat/pecoff/PECoffRelocTable.java | 92 +++ .../jaotc/binformat/pecoff/PECoffSection.java | 140 ++++ .../jaotc/binformat/pecoff/PECoffSymbol.java | 61 ++ .../jaotc/binformat/pecoff/PECoffSymtab.java | 151 ++++ .../binformat/pecoff/PECoffTargetInfo.java | 74 ++ .../jdk/tools/jaotc/jnilibelf/ELFSymbol.java | 76 -- .../jaotc/jnilibelf/JNIELFContainer.java | 476 ------------ .../jaotc/jnilibelf/JNIELFRelocation.java | 148 ---- .../jaotc/jnilibelf/JNIELFTargetInfo.java | 127 ---- .../tools/jaotc/jnilibelf/JNILibELFAPI.java | 677 ------------------ .../jdk/tools/jaotc/jnilibelf/Pointer.java | 72 -- .../tools/jaotc/jnilibelf/linux/Elf_Cmd.java | 80 --- .../src/jdk/tools/jaotc/Main.java | 79 +- .../tools/jaotc/collect/ClassCollector.java | 11 +- .../jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c | 522 -------------- .../unix/native/libjelfshim/shim_functions.c | 226 ------ hotspot/src/share/vm/aot/aotCodeHeap.cpp | 31 +- .../src/share/vm/aot/aotCompiledMethod.cpp | 3 +- hotspot/src/share/vm/aot/aotLoader.cpp | 14 +- hotspot/src/share/vm/aot/compiledIC_aot.cpp | 4 +- .../test/compiler/aot/DeoptimizationTest.java | 4 +- .../test/compiler/aot/RecompilationTest.java | 4 +- .../test/compiler/aot/SharedUsageTest.java | 4 +- .../fromAot/AotInvokeDynamic2AotTest.java | 4 +- .../AotInvokeDynamic2CompiledTest.java | 4 +- .../AotInvokeDynamic2InterpretedTest.java | 4 +- .../fromAot/AotInvokeDynamic2NativeTest.java | 4 +- .../fromAot/AotInvokeInterface2AotTest.java | 4 +- .../AotInvokeInterface2CompiledTest.java | 4 +- .../AotInvokeInterface2InterpretedTest.java | 4 +- .../AotInvokeInterface2NativeTest.java | 4 +- .../fromAot/AotInvokeSpecial2AotTest.java | 4 +- .../AotInvokeSpecial2CompiledTest.java | 4 +- .../AotInvokeSpecial2InterpretedTest.java | 4 +- .../fromAot/AotInvokeSpecial2NativeTest.java | 4 +- .../fromAot/AotInvokeStatic2AotTest.java | 4 +- .../fromAot/AotInvokeStatic2CompiledTest.java | 4 +- .../AotInvokeStatic2InterpretedTest.java | 4 +- .../fromAot/AotInvokeStatic2NativeTest.java | 4 +- .../fromAot/AotInvokeVirtual2AotTest.java | 4 +- .../AotInvokeVirtual2CompiledTest.java | 4 +- .../AotInvokeVirtual2InterpretedTest.java | 4 +- .../fromAot/AotInvokeVirtual2NativeTest.java | 4 +- .../CompiledInvokeDynamic2AotTest.java | 4 +- .../CompiledInvokeInterface2AotTest.java | 4 +- .../CompiledInvokeSpecial2AotTest.java | 4 +- .../CompiledInvokeStatic2AotTest.java | 4 +- .../CompiledInvokeVirtual2AotTest.java | 4 +- .../InterpretedInvokeDynamic2AotTest.java | 4 +- .../InterpretedInvokeInterface2AotTest.java | 4 +- .../InterpretedInvokeSpecial2AotTest.java | 4 +- .../InterpretedInvokeStatic2AotTest.java | 4 +- .../InterpretedInvokeVirtual2AotTest.java | 4 +- .../NativeInvokeSpecial2AotTest.java | 4 +- .../NativeInvokeStatic2AotTest.java | 4 +- .../NativeInvokeVirtual2AotTest.java | 4 +- .../aot/cli/DisabledAOTWithLibraryTest.java | 4 +- .../aot/cli/IncorrectAOTLibraryTest.java | 4 +- .../aot/cli/MultipleAOTLibraryTest.java | 4 +- .../aot/cli/NonExistingAOTLibraryTest.java | 6 +- .../aot/cli/SingleAOTLibraryTest.java | 4 +- .../compiler/aot/cli/SingleAOTOptionTest.java | 4 +- .../aot/cli/jaotc/ClasspathOptionTest.java | 4 +- .../ClasspathOptionUnknownClassTest.java | 4 +- .../aot/cli/jaotc/CompileClassTest.java | 4 +- .../aot/cli/jaotc/CompileDirectoryTest.java | 4 +- .../aot/cli/jaotc/CompileJarTest.java | 4 +- .../aot/cli/jaotc/CompileModuleTest.java | 4 +- .../aot/cli/jaotc/JaotcTestHelper.java | 4 +- .../cli/jaotc/ListOptionNotExistingTest.java | 4 +- .../aot/cli/jaotc/ListOptionTest.java | 4 +- .../cli/jaotc/ListOptionWrongFileTest.java | 4 +- .../compiler/aot/fingerprint/SelfChanged.java | 4 +- .../aot/fingerprint/SelfChangedCDS.java | 4 +- .../aot/fingerprint/SuperChanged.java | 4 +- .../jaotc/jnilibelf/test/JNILibELFTest.java | 99 --- .../test/NativeOrderOutputStreamTest.java | 4 +- .../ClassAndLibraryNotMatchTest.java | 4 +- .../vmflags/NotTrackedFlagTest.java | 4 +- .../verification/vmflags/TrackedFlagTest.java | 4 +- 118 files changed, 4686 insertions(+), 2977 deletions(-) delete mode 100644 hotspot/make/lib/Lib-jdk.aot.gmk rename hotspot/src/jdk.aot/share/classes/{jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java => jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java} (87%) rename hotspot/src/jdk.aot/share/classes/{jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java => jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java} (65%) create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java rename hotspot/src/jdk.aot/share/classes/{jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java => jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java} (70%) create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java create mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java delete mode 100644 hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java delete mode 100644 hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c delete mode 100644 hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c delete mode 100644 hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java diff --git a/hotspot/make/lib/Lib-jdk.aot.gmk b/hotspot/make/lib/Lib-jdk.aot.gmk deleted file mode 100644 index d799fa45286..00000000000 --- a/hotspot/make/lib/Lib-jdk.aot.gmk +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -include $(SPEC) -include NativeCompilation.gmk - -$(eval $(call IncludeCustomExtension, hotspot, lib/Lib-jdk.aot.gmk)) - -############################################################################## -# Build libjelfshim only when AOT is enabled. -ifeq ($(ENABLE_AOT), true) - JELFSHIM_NAME := jelfshim - - $(eval $(call SetupNativeCompilation, BUILD_LIBJELFSHIM, \ - TOOLCHAIN := TOOLCHAIN_DEFAULT, \ - OPTIMIZATION := LOW, \ - LIBRARY := $(JELFSHIM_NAME), \ - OUTPUT_DIR := $(call FindLibDirForModule, $(MODULE)), \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.aot/unix/native/libjelfshim, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ELF_CFLAGS) \ - -DAOT_VERSION_STRING='"$(VERSION_STRING)"' \ - -I$(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \ - LDFLAGS := $(LDFLAGS_JDKLIB), \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib$(JELFSHIM_NAME), \ - LIBS := $(ELF_LIBS) $(LIBS_JDKLIB), \ - )) - - TARGETS += $(BUILD_LIBJELFSHIM) -endif - -############################################################################## diff --git a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp index 6b711506fab..d884ef2a87c 100644 --- a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,6 +21,8 @@ * questions. */ +#include "precompiled.hpp" + #include "aot/compiledIC_aot.hpp" #include "code/codeCache.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java index 7be7a80192e..239e825213c 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -36,6 +36,8 @@ import java.util.Map; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.elf.JELFRelocObject; +import jdk.tools.jaotc.binformat.macho.JMachORelocObject; +import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; /** @@ -43,7 +45,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; * *

* This class holds information necessary to create platform-specific binary containers such as - * ELFContainer for Linux and Solaris operating systems or yet-to be created MachOContainer for Mac + * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac * OS or PEContainer for MS Windows operating systems. * *

@@ -263,29 +265,29 @@ public class BinaryContainer implements SymbolTable { // read only, code codeContainer = new CodeContainer(".text", this); - extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this); + extLinkageContainer = new CodeContainer(".hs.plt.linkage", this); // read only, info configContainer = new ReadOnlyDataContainer(".config", this); - metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this); + metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this); methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this); - klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this); - klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this); + klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this); + klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this); headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this)); stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this); codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this); - constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this); + constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this); // needs relocation patching at load time by the loader - methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this); + methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this); // writable sections - metaspaceGotContainer = new ByteContainer(".metaspace.got", this); + metaspaceGotContainer = new ByteContainer(".meta.got", this); metadataGotContainer = new ByteContainer(".metadata.got", this); - methodStateContainer = new ByteContainer(".method.state", this); + methodStateContainer = new ByteContainer(".meth.state", this); oopGotContainer = new ByteContainer(".oop.got", this); - extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this); + extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this); addGlobalSymbols(); @@ -490,11 +492,21 @@ public class BinaryContainer implements SymbolTable { switch (osName) { case "Linux": case "SunOS": - JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion); - elfso.createELFRelocObject(relocationTable, symbolTable.values()); + JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion); + elfobj.createELFRelocObject(relocationTable, symbolTable.values()); + break; + case "Mac OS X": + JMachORelocObject machobj = new JMachORelocObject(this, outputFileName); + machobj.createMachORelocObject(relocationTable, symbolTable.values()); break; default: - throw new InternalError("Unsupported platform: " + osName); + if (osName.startsWith("Windows")) { + JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion); + pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values()); + break; + } + else + throw new InternalError("Unsupported platform: " + osName); } } @@ -735,11 +747,11 @@ public class BinaryContainer implements SymbolTable { } /** - * Add constant data as follows. - Adding the data to the method.constdata section + * Add constant data as follows. - Adding the data to the meth.constdata section * * @param data * @param alignment - * @return the offset in the method.constdata of the data + * @return the offset in the meth.constdata of the data */ public int addConstantData(byte[] data, int alignment) { // Get the current length of the metaspaceNameContainer diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java index 12daa9f356f..3d44ab0cf72 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; +import jdk.tools.jaotc.binformat.Container; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; @@ -41,7 +41,7 @@ import java.util.Arrays; * The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not * reflected in {@code contentStream}. */ -public class ByteContainer implements ELFContainer { +public class ByteContainer implements Container { /** * {@code ByteBuffer} representation of {@code BinaryContainer}. */ diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java similarity index 87% rename from hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java index b65b6ae8d25..ad2b405ab90 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,9 +21,9 @@ * questions. */ -package jdk.tools.jaotc.jnilibelf; +package jdk.tools.jaotc.binformat; -public interface ELFContainer { +public interface Container { String getContainerName(); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java similarity index 65% rename from hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java index be7423c1cad..e03870ebd40 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,27 +21,31 @@ * questions. */ -package jdk.tools.jaotc.jnilibelf.sunos; +package jdk.tools.jaotc.binformat; /** - * Represent Elf_Cmd enums defined in libelf.h on SunOS as they slightly different from libelf.h on - * Linux. + * This class represents ia native OS specific Symbol */ -public enum Elf_Cmd { - /** Must be first, 0. */ - ELF_C_NULL, +public abstract class NativeSymbol { - ELF_C_READ, - ELF_C_WRITE, - ELF_C_CLR, - ELF_C_SET, - ELF_C_FDDONE, - ELF_C_FDREAD, - ELF_C_RDWR, - ELF_C_WRIMAGE, - ELF_C_IMAGE, + /** String table index. */ + private int index; - /** Must be last. */ - ELF_C_NUM + public NativeSymbol(int index) { + this.index = index; + } + /** + * @return the index + */ + public int getIndex() { + return index; + } + + /** + * @index + */ + public void setIndex(int index) { + this.index = index; + } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java index ba0f9090ee7..8fbc0dd23a6 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat; import java.util.Objects; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; +import jdk.tools.jaotc.binformat.NativeSymbol; public class Symbol { @@ -51,7 +51,7 @@ public class Symbol { private final Kind kind; private ByteContainer section; - private ELFSymbol elfSymbol; + private NativeSymbol nativeSymbol; /** * Create symbol info. @@ -77,12 +77,12 @@ public class Symbol { return name; } - public ELFSymbol getElfSymbol() { - return elfSymbol; + public NativeSymbol getNativeSymbol() { + return nativeSymbol; } - public void setElfSymbol(ELFSymbol elfSymbol) { - this.elfSymbol = elfSymbol; + public void setNativeSymbol(NativeSymbol nativeSym) { + this.nativeSymbol = nativeSym; } public Binding getBinding() { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java new file mode 100644 index 00000000000..e61176d07e7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +/** + * + * Support for the creation of Elf Object files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class Elf { + + /** + * Elf64_Ehdr structure defines + */ + public enum Elf64_Ehdr { + e_ident( 0,16), + e_type(16, 2), + e_machine(18, 2), + e_version(20, 4), + e_entry(24, 8), + e_phoff(32, 8), + e_shoff(40, 8), + e_flags(48, 4), + e_ehsize(52, 2), + e_phentsize(54, 2), + e_phnum(56, 2), + e_shentsize(58, 2), + e_shnum(60, 2), + e_shstrndx(62, 2); + + public final int off; + public final int sz; + + Elf64_Ehdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Ehdr defines + */ + + /** + * e_ident + */ + public static final int EI_MAG0 = 0; + public static final byte ELFMAG0 = 0x7f; + public static final int EI_MAG1 = 1; + public static final byte ELFMAG1 = 0x45; + public static final int EI_MAG2 = 2; + public static final byte ELFMAG2 = 0x4c; + public static final int EI_MAG3 = 3; + public static final byte ELFMAG3 = 0x46; + + public static final int EI_CLASS = 4; + public static final byte ELFCLASS64 = 0x2; + + public static final int EI_DATA = 5; + public static final byte ELFDATA2LSB = 0x1; + + public static final int EI_VERSION = 6; + public static final byte EV_CURRENT = 0x1; + + public static final int EI_OSABI = 7; + public static final byte ELFOSABI_NONE = 0x0; + + /** + * e_type + */ + public static final char ET_REL = 0x1; + + /** + * e_machine + */ + public static final char EM_NONE = 0; + public static final char EM_X86_64 = 62; + public static final char EM_AARCH64 = 183; + + /** + * e_version + */ + // public static final int EV_CURRENT = 1; + + } + + /** + * Elf64_Shdr structure defines + */ + public enum Elf64_Shdr { + sh_name( 0, 4), + sh_type( 4, 4), + sh_flags( 8, 8), + sh_addr(16, 8), + sh_offset(24, 8), + sh_size(32, 8), + sh_link(40, 4), + sh_info(44, 4), + sh_addralign(48, 8), + sh_entsize(56, 8); + + public final int off; + public final int sz; + + Elf64_Shdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Shdr defines + */ + + /** + * sh_type + */ + public static final int SHT_PROGBITS = 0x1; + public static final int SHT_SYMTAB = 0x2; + public static final int SHT_STRTAB = 0x3; + public static final int SHT_RELA = 0x4; + public static final int SHT_NOBITS = 0x8; + public static final int SHT_REL = 0x9; + + public static final byte SHN_UNDEF = 0x0; + + /** + * sh_flag + */ + public static final int SHF_WRITE = 0x1; + public static final int SHF_ALLOC = 0x2; + public static final int SHF_EXECINSTR = 0x4; + + } + + /** + * Symbol table entry definitions + * + * Elf64_Sym structure defines + */ + public enum Elf64_Sym { + st_name( 0, 4), + st_info( 4, 1), + st_other( 5, 1), + st_shndx( 6, 2), + st_value( 8, 8), + st_size(16, 8); + + public final int off; + public final int sz; + + Elf64_Sym(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + /* ST_BIND is in bits 4-7 of st_info. ST_TYPE is in low 4 bits */ + public static final byte STB_LOCAL = 0x0; + public static final byte STB_GLOBAL = 0x1; + + public static final byte STT_NOTYPE = 0x0; + public static final byte STT_OBJECT = 0x1; + public static final byte STT_FUNC = 0x2; + + public static byte ELF64_ST_INFO(byte bind, byte type) { + return (byte)(((bind) << 4) + ((type) & 0xf)); + } + + } + + /** + * Elf64_Rel structure defines + */ + public enum Elf64_Rel { + r_offset( 0, 8), + r_info( 8, 8); + + public final int off; + public final int sz; + + Elf64_Rel(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + /** + * Relocation types + */ + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + } + + /** + * Elf64_Rela structure defines + */ + public enum Elf64_Rela { + r_offset( 0, 8), + r_info( 8, 8), + r_addend(16, 8); + + public final int off; + public final int sz; + + Elf64_Rela(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + public static long ELF64_R_INFO(int symidx, int type) { + return (((long)symidx << 32) + ((long)type)); + } + + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java new file mode 100644 index 00000000000..8d7c8e7d41d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; + +public class ElfByteBuffer { + + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java new file mode 100644 index 00000000000..03b8682c95e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.io.File; +import java.io.FileOutputStream; + +public class ElfContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public ElfContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("ElfContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("ElfContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java new file mode 100644 index 00000000000..e930d5580a3 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfHeader { + ByteBuffer header; + + public ElfHeader() { + header = ElfByteBuffer.allocate(Elf64_Ehdr.totalsize); + + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE); + + header.putChar(Elf64_Ehdr.e_type.off, Elf64_Ehdr.ET_REL); + header.putChar(Elf64_Ehdr.e_machine.off, ElfTargetInfo.getElfArch()); + header.putInt(Elf64_Ehdr.e_version.off, Elf64_Ehdr.EV_CURRENT); + header.putChar(Elf64_Ehdr.e_ehsize.off, (char)Elf64_Ehdr.totalsize); + header.putChar(Elf64_Ehdr.e_shentsize.off, (char)Elf64_Shdr.totalsize); + + } + + // Update header with file offset of first section + public void setSectionOff(int offset) { + header.putLong(Elf64_Ehdr.e_shoff.off, offset); + } + + // Update header with the number of total sections + public void setSectionNum(int count) { + header.putChar(Elf64_Ehdr.e_shnum.off, (char)count); + } + + // Update header with the section index containing the + // string table for section names + public void setSectionStrNdx(int index) { + header.putChar(Elf64_Ehdr.e_shstrndx.off, (char)index); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java new file mode 100644 index 00000000000..817648ec65b --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfRelocEntry { + ByteBuffer entry; + + public ElfRelocEntry(int offset, int symno, int type, int addend) { + + entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize); + + entry.putLong(Elf64_Rela.r_offset.off, offset); + entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno,type)); + entry.putLong(Elf64_Rela.r_addend.off, addend); + } + + public byte[] getArray() { + return entry.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java new file mode 100644 index 00000000000..0e28a9f384e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.ElfRelocEntry; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfRelocTable { + ArrayList> relocEntries; + + public ElfRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type, + int addend) { + + ElfRelocEntry entry = new ElfRelocEntry(offset, + symno, + type, + addend); + relocEntries.get(sectindex).add(entry); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + ElfRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java new file mode 100644 index 00000000000..5b8814a7fa9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSection { + String name; + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + + /** + * String holding section name strings + */ + private static StringBuilder sectNameTab = new StringBuilder(); + + /** + * Keeps track of bytes in section string table since strTabContent.length() + * is number of chars, not bytes. + */ + private static int shStrTabNrOfBytes = 0; + + public ElfSection(String sectName, byte [] sectData, int sectFlags, + int sectType, boolean hasRelocations, int sectIndex) { + + long align; + + section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize); + + // Return all 0's for NULL section + if (sectIndex == 0) { + sectNameTab.append('\0'); + shStrTabNrOfBytes += 1; + data = null; + hasrelocations = false; + sectionIndex = 0; + return; + } + + section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes); + sectNameTab.append(sectName).append('\0'); + shStrTabNrOfBytes += (sectName.getBytes().length + 1); + name = sectName; + + section.putInt(Elf64_Shdr.sh_type.off, sectType); + section.putLong(Elf64_Shdr.sh_flags.off, sectFlags); + section.putLong(Elf64_Shdr.sh_addr.off, 0); + section.putLong(Elf64_Shdr.sh_offset.off, 0); + + if (sectName.equals(".shstrtab")) { + section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes); + data = sectNameTab.toString().getBytes(); + } + else { + data = sectData; + section.putLong(Elf64_Shdr.sh_size.off, sectData.length); + } + + section.putLong(Elf64_Shdr.sh_entsize.off, 0); + + // Determine the alignment and entrysize + // based on type of section + switch (sectType) { + case Elf64_Shdr.SHT_PROGBITS: + if ((sectFlags & Elf64_Shdr.SHF_EXECINSTR) != 0) + align = 16; + else + align = 4; + break; + case Elf64_Shdr.SHT_SYMTAB: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize); + break; + case Elf64_Shdr.SHT_STRTAB: + align = 1; + break; + case Elf64_Shdr.SHT_RELA: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize); + break; + case Elf64_Shdr.SHT_REL: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize); + break; + case Elf64_Shdr.SHT_NOBITS: + align = 4; + break; + default: + align = 8; + break; + } + section.putLong(Elf64_Shdr.sh_addralign.off, align); + + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public String getName() { + return name; + } + + public long getSize() { + return section.getLong(Elf64_Shdr.sh_size.off); + } + + public int getDataAlign() { + return ((int)section.getLong(Elf64_Shdr.sh_addralign.off)); + } + + // Alignment requirements for the Elf64_Shdr structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putLong(Elf64_Shdr.sh_offset.off, offset); + } + + public void setLink(int link) { + section.putInt(Elf64_Shdr.sh_link.off, link); + } + + public void setInfo(int info) { + section.putInt(Elf64_Shdr.sh_info.off, info); + } + + public long getOffset() { + return (section.getLong(Elf64_Shdr.sh_offset.off)); + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java new file mode 100644 index 00000000000..6a22019f6bf --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymbol extends NativeSymbol { + ByteBuffer sym; + + public ElfSymbol(int symbolindex, int strindex, byte type, byte bind, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = ElfByteBuffer.allocate(Elf64_Sym.totalsize); + + sym.putInt(Elf64_Sym.st_name.off, strindex); + sym.put(Elf64_Sym.st_info.off, Elf64_Sym.ELF64_ST_INFO(bind, type)); + sym.put(Elf64_Sym.st_other.off, (byte)0); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.putChar(Elf64_Sym.st_shndx.off, (char)(sectindex)); + sym.putLong(Elf64_Sym.st_value.off, offset); + sym.putLong(Elf64_Sym.st_size.off, size); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java new file mode 100644 index 00000000000..4105c152693 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymtab { + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public ElfSymtab() { + symbolCount = 0; + } + + public ElfSymbol addSymbolEntry(String name, byte type, byte bind, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + ElfSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append("_").append(name).append('\0'); + strTabContent.append(name).append('\0'); + // + 1 for null, + 1 for "_" + //strTabNrOfBytes += (name.getBytes().length + 1 + 1); + strTabNrOfBytes += (name.getBytes().length + 1); + + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + if ((bind & Elf64_Sym.STB_GLOBAL) != 0) + globalSymbols.add(sym); + else + localSymbols.add(sym); + } + symbolCount++; + return (sym); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local then global. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + + + // Create a single byte array that contains the symbol table entries + public byte[] getSymtabArray() { + int index = 0; + ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount*Elf64_Sym.totalsize); + byte [] retarray; + + updateIndexes(); + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + retarray = symtabData.array(); + + return (retarray); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + return (strs); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java new file mode 100644 index 00000000000..2c9a6a3c4a0 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class ElfTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Architecture endian-ness. + */ + private static final int endian = Elf64_Ehdr.ELFDATA2LSB; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = Elf64_Ehdr.EM_X86_64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = Elf64_Ehdr.EM_NONE; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.equals("linux") && !osName.equals("sunos")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getElfArch() { + return arch; + } + + public static int getElfEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java index 82bac0c7170..e616f9857ec 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import jdk.tools.jaotc.binformat.Container; import jdk.tools.jaotc.binformat.BinaryContainer; import jdk.tools.jaotc.binformat.ByteContainer; import jdk.tools.jaotc.binformat.CodeContainer; @@ -37,36 +38,60 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; import jdk.tools.jaotc.binformat.Relocation; import jdk.tools.jaotc.binformat.Relocation.RelocType; import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; -import jdk.tools.jaotc.jnilibelf.JNIELFContainer; -import jdk.tools.jaotc.jnilibelf.JNIELFRelocation; -import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; -import jdk.tools.jaotc.jnilibelf.Pointer; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; public class JELFRelocObject { private final BinaryContainer binContainer; - private final JNIELFContainer elfContainer; + private final ElfContainer elfContainer; private final int segmentSize; public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { this.binContainer = binContainer; - this.elfContainer = new JNIELFContainer(outputFileName, aotVersion); + this.elfContainer = new ElfContainer(outputFileName, aotVersion); this.segmentSize = binContainer.getCodeSegmentSize(); } - private void createByteSection(ByteContainer c, int scnFlags) { + private ElfSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int scnFlags, + int scnType) { + + ElfSection sect = new ElfSection(sectName, + scnData, + scnFlags, + scnType, + hasRelocs, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + ElfSection sect; + boolean hasRelocs = c.hasRelocations(); byte[] scnData = c.getByteArray(); - int scnType = ELF.SHT_PROGBITS; - boolean zeros = !c.hasRelocations(); + + int scnType = Elf64_Shdr.SHT_PROGBITS; + boolean zeros = hasRelocs; if (zeros) { for (byte b : scnData) { if (b != 0) { @@ -75,30 +100,30 @@ public class JELFRelocObject { } } if (zeros) { - scnType = ELF.SHT_NOBITS; + scnType = Elf64_Shdr.SHT_NOBITS; } } - int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0); - c.setSectionId(sectionId); - // Clear out code section data to allow for GC - c.clear(); + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, + scnFlags, scnType); + c.setSectionId(sect.getSectionId()); } - private void createCodeSection(CodeContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR); + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR); } - private void createReadOnlySection(ReadOnlyDataContainer c) { - createByteSection(c, ELF.SHF_ALLOC); + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC); } - private void createReadWriteSection(ByteContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE); + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE); } /** - * Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API. + * Create an ELF relocatable object * * @param relocationTable * @param symbols @@ -106,145 +131,171 @@ public class JELFRelocObject { */ public void createELFRelocObject(Map> relocationTable, Collection symbols) throws IOException { // Allocate ELF Header - elfContainer.createELFHeader(ELF.ET_REL); + ElfHeader eh = new ElfHeader(); + + ArrayList sections = new ArrayList(); + + // Create the null section + createByteSection(sections, null, null, false, 0, 0); // Create text section - createCodeSection(binContainer.getCodeContainer()); - createReadOnlySection(binContainer.getMetaspaceNamesContainer()); - createReadOnlySection(binContainer.getKlassesOffsetsContainer()); - createReadOnlySection(binContainer.getMethodsOffsetsContainer()); - createReadOnlySection(binContainer.getKlassesDependenciesContainer()); - createReadWriteSection(binContainer.getMetaspaceGotContainer()); - createReadWriteSection(binContainer.getMetadataGotContainer()); - createReadWriteSection(binContainer.getMethodStateContainer()); - createReadWriteSection(binContainer.getOopGotContainer()); - createReadWriteSection(binContainer.getMethodMetadataContainer()); - createReadOnlySection(binContainer.getStubsOffsetsContainer()); - createReadOnlySection(binContainer.getHeaderContainer().getContainer()); - createReadOnlySection(binContainer.getCodeSegmentsContainer()); - createReadOnlySection(binContainer.getConstantDataContainer()); - createReadOnlySection(binContainer.getConfigContainer()); + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); // createExternalLinkage(); - createCodeSection(binContainer.getExtLinkageContainer()); - createReadWriteSection(binContainer.getExtLinkageGOTContainer()); + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); // Get ELF symbol data from BinaryContainer object's symbol tables - createELFSymbolTables(symbols); + ElfSymtab symtab = createELFSymbolTables(sections, symbols); // Create string table section and symbol table sections in - // that order since symtab section needs to set the index of strtab in sh_link field - int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + // that order since symtab section needs to set the index of + // strtab in sh_link field + ElfSection strTabSection = createByteSection(sections, + ".strtab", + symtab.getStrtabArray(), + false, + 0, + Elf64_Shdr.SHT_STRTAB); - // Now create .symtab section with the symtab data constructed. On Linux, sh_link of symtab - // contains the index of string table its symbols reference and - // sh_info contains the index of first non-local symbol - int scnInfo = elfContainer.getFirstNonLocalSymbolIndex(); - int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo); + // Now create .symtab section with the symtab data constructed. + // On Linux, sh_link of symtab contains the index of string table + // its symbols reference and sh_info contains the index of first + // non-local symbol + ElfSection symTabSection = createByteSection(sections, + ".symtab", + symtab.getSymtabArray(), + false, + 0, + Elf64_Shdr.SHT_SYMTAB); + symTabSection.setLink(strTabSection.getSectionId()); + symTabSection.setInfo(symtab.getNumLocalSyms()); - buildRelocations(relocationTable, symTabSectionIndex); + ElfRelocTable elfRelocTable = createElfRelocTable(sections, + relocationTable); + + createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId()); // Now, finally, after creating all sections, create shstrtab section - elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + ElfSection shStrTabSection = createByteSection(sections, + ".shstrtab", + null, + false, + 0, + Elf64_Shdr.SHT_STRTAB); + eh.setSectionStrNdx(shStrTabSection.getSectionId()); - // Run elf_update - elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL); + // Update all section offsets and the Elf header section offset + // Write the Header followed by the contents of each section + // and then the section structures (section table). + int file_offset = Elf64_Ehdr.totalsize; - // Run elfUpdate again to write it out. - elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE); - // Finish ELF processing - elfContainer.elfEnd(); + // and round it up + file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) & + ~((sections.get(1).getDataAlign()-1)); + + // Calc file offsets for section data skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Align the section table + file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) & + ~((ElfSection.getShdrAlign()-1)); + + // Update the Elf Header with the offset of the first Elf64_Shdr + // and the number of sections. + eh.setSectionOff(file_offset); + eh.setSectionNum(sections.size()); + + // Write out the Header + elfContainer.writeBytes(eh.getArray()); + + // Write out each section contents skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign()); + } + + elfContainer.close(); } - - private void buildRelocations(Map> relocationTable, final int symTabSectionIndex) { - /* - * Create relocation sections. This needs to be done after symbol table sections were - * created since relocation entries will need indices of sections to which they apply. - */ - createELFRelocationTables(relocationTable); - createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex)); - } - /** * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF * symbol table and ELF symbol table are created from BinaryContainer's symbol info. * * @param symbols */ - private void createELFSymbolTables(Collection symbols) { + private ElfSymtab createELFSymbolTables(ArrayList sections, Collection symbols) { + ElfSymtab symtab = new ElfSymtab(); + // First, create the initial null symbol. This is a local symbol. - elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true); + symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0); // Now create ELF symbol entries for all symbols. for (Symbol symbol : symbols) { // Get the index of section this symbol is defined in. int secHdrIndex = symbol.getSection().getSectionId(); - boolean isLocal = (symbol.getBinding() == Binding.LOCAL); - ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal); - symbol.setElfSymbol(elfSymbol); + ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)elfSymbol); } + return (symtab); } - /** - * Construct ELF symbol data from BinaryContainer object's symbol tables. - * - * @return a byte array containing the symbol table - */ - private byte[] getELFSymbolTableData() { - final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry(); - - // First, add all local symbols. - List localSymbols = elfContainer.getLocalSymbols(); - List globalSymbols = elfContainer.getGlobalSymbols(); - - int localSymCount = localSymbols.size(); - int globalSymCount = globalSymbols.size(); - byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize]; - - for (int i = 0; i < localSymCount; i++) { - ELFSymbol symbol = localSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, i * entrySize); - } - - // Next, add all global symbols. - - for (int i = 0; i < globalSymCount; i++) { - ELFSymbol symbol = globalSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize); - } - - return sectionDataArray; - } - - private static int getELFTypeOf(Symbol sym) { + private static byte getELFTypeOf(Symbol sym) { Kind kind = sym.getKind(); if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { - return ELF.STT_FUNC; + return Elf64_Sym.STT_FUNC; } else if (kind == Symbol.Kind.OBJECT) { - return ELF.STT_OBJECT; + return Elf64_Sym.STT_OBJECT; } - return ELF.STT_NOTYPE; + return Elf64_Sym.STT_NOTYPE; } - private static int getELFBindOf(Symbol sym) { + private static byte getELFBindOf(Symbol sym) { Binding binding = sym.getBinding(); if (binding == Symbol.Binding.GLOBAL) { - return ELF.STB_GLOBAL; + return Elf64_Sym.STB_GLOBAL; } - return ELF.STB_LOCAL; + return Elf64_Sym.STB_LOCAL; } /** - * Construct ELF relocation section data from BinaryContainer object's relocation tables. + * Construct a Elf relocation table from BinaryContainer object's relocation tables. * + * @param sections * @param relocationTable */ - private void createELFRelocationTables(Map> relocationTable) { + private ElfRelocTable createElfRelocTable(ArrayList sections, + Map> relocationTable) { + + ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size()); /* - * For each of the symbols with associated relocation records, create an ELF relocation + * For each of the symbols with associated relocation records, create a Elf relocation * entry. */ for (Map.Entry> entry : relocationTable.entrySet()) { @@ -252,18 +303,26 @@ public class JELFRelocObject { Symbol symbol = entry.getKey(); for (Relocation reloc : relocs) { - createRelocation(symbol, reloc); + createRelocation(symbol, reloc, elfRelocTable); } } for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { - createRelocation(entry.getKey(), entry.getValue()); + createRelocation(entry.getKey(), entry.getValue(), elfRelocTable); } + + return (elfRelocTable); } - private void createRelocation(Symbol symbol, Relocation reloc) { + private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { RelocType relocType = reloc.getType(); + int elfRelocType = getELFRelocationType(relocType); + ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; switch (relocType) { case FOREIGN_CALL_DIRECT: @@ -271,85 +330,89 @@ public class JELFRelocObject { case STUB_CALL_DIRECT: case FOREIGN_CALL_INDIRECT_GOT: { // Create relocation entry - int addend = -4; // Size in bytes of the patch location + // System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + addend = -4; // Size in bytes of the patch location // Relocation should be applied at the location after call operand - int offset = reloc.getOffset() + reloc.getSize() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend; break; } case FOREIGN_CALL_DIRECT_FAR: { // Create relocation entry - int addend = -8; // Size in bytes of the patch location + addend = -8; // Size in bytes of the patch location // Relocation should be applied at the location after call operand // 10 = 2 (jmp [r]) + 8 (imm64) - int offset = reloc.getOffset() + reloc.getSize() + addend - 2; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend - 2; break; } case FOREIGN_CALL_INDIRECT: case JAVA_CALL_INDIRECT: case STUB_CALL_INDIRECT: { // Do nothing. - break; + return; } case EXTERNAL_DATA_REFERENCE_FAR: { // Create relocation entry - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads + * offset points to the test instruction after the instruction that loads * the address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case METASPACE_GOT_REFERENCE: case EXTERNAL_PLT_TO_GOT: case STATIC_STUB_TO_STATIC_METHOD: case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* - * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads - * the address of polling page. So set the offset appropriately. + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case EXTERNAL_GOT_TO_PLT: case LOADTIME_ADDRESS: { // this is load time relocations - elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol()); break; } default: throw new InternalError("Unhandled relocation type: " + relocType); } + elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); } - // TODO: Populate the mapping of RelocType to ELF relocation types private static int getELFRelocationType(RelocType relocType) { int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH - switch (JNIELFTargetInfo.getELFArch()) { - case ELF.EM_X64_64: + switch (ElfTargetInfo.getElfArch()) { + case Elf64_Ehdr.EM_X86_64: // Return R_X86_64_* entries based on relocType - if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32; + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PLT32; } else if (relocType == RelocType.STUB_CALL_DIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; + elfRelocType = Elf64_Rela.R_X86_64_PC32; } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; - } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE; + elfRelocType = Elf64_Rela.R_X86_64_64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + elfRelocType = Elf64_Rela.R_X86_64_NONE; } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL; - } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || - relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; - } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; + elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PC32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + elfRelocType = Elf64_Rela.R_X86_64_64; } else { assert false : "Unhandled relocation type: " + relocType; } @@ -360,61 +423,26 @@ public class JELFRelocObject { return elfRelocType; } - private void createAllRelocationSections(ELFContainer symtab) { - for (Map.Entry> entry : elfContainer.getRelocTables().entrySet()) { - createRelocationSection(entry.getKey(), entry.getValue(), symtab); - } - } + private void createElfRelocSections(ArrayList sections, + ElfRelocTable elfRelocTable, + int symtabsectidx) { - private void createRelocationSection(ELFContainer container, ArrayList relocations, ELFContainer symtab) { - String secName = container.getContainerName(); - int entrySize = JNIELFTargetInfo.sizeOfRelocEntry(); - int numEntries = relocations.size(); - byte[] sectionDataBytes = new byte[numEntries * entrySize]; + // Grab count before we create new sections + int count = sections.size(); - for (int index = 0; index < relocations.size(); index++) { - Pointer entry = relocations.get(index); - entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize); - } - String fullSecName; - // If relocDat is non-null create section - if (sectionDataBytes.length > 0) { - int scnType; - Elf_Type dataType; - if (JNIELFTargetInfo.createReloca() == 0) { - scnType = ELF.SHT_REL; - dataType = Elf_Type.ELF_T_REL; - fullSecName = ".rel" + secName; - } else { - scnType = ELF.SHT_RELA; - dataType = Elf_Type.ELF_T_RELA; - fullSecName = ".rela" + secName; + for (int i = 0; i < count; i++) { + if (elfRelocTable.getNumRelocs(i) > 0) { + ElfSection sect = sections.get(i); + String relname = ".rela" + sect.getName(); + ElfSection relocSection = createByteSection(sections, + relname, + elfRelocTable.getRelocData(i), + false, + 0, + Elf64_Shdr.SHT_RELA); + relocSection.setLink(symtabsectidx); + relocSection.setInfo(sect.getSectionId()); } - // assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array - // copy"; - // sh_link holds the index of section header of symbol table associated with this - // relocation table. - // sh_info holds the index of section header to which this relocation table applies - // to. - elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId()); - } - } - - private static class SymTabELFContainer implements ELFContainer { - private final int symTabSectionIndex; - - public SymTabELFContainer(int symTabSectionIndex) { - this.symTabSectionIndex = symTabSectionIndex; - } - - @Override - public String getContainerName() { - return ".symtab"; - } - - @Override - public int getSectionId() { - return symTabSectionIndex; } } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java new file mode 100644 index 00000000000..7223c327763 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * + * File Layout generated by JMachORelocObject + * + * MachO Header + * Load Commands + * LC_SEGMENT_64 + * - Sections + * LC_VERSION_MIN_MAX + * LC_SYMTAB + * LC_DYSYMTAB + * Section Data + * Relocation entries + * Symbol table + * + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOContainer; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOSymtab; +import jdk.tools.jaotc.binformat.macho.MachORelocTable; + +public class JMachORelocObject { + + private final BinaryContainer binContainer; + + private final MachOContainer machoContainer; + + private final int segmentSize; + + public JMachORelocObject(BinaryContainer binContainer, String outputFileName) { + this.binContainer = binContainer; + this.machoContainer = new MachOContainer(outputFileName); + this.segmentSize = binContainer.getCodeSegmentSize(); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, String sectName, String segName, int scnFlags) { + + if (c.getByteArray().length == 0) { + // System.out.println("Skipping creation of " + sectName + " section, no data\n"); + } + + MachOSection sect = new MachOSection(sectName, + segName, + c.getByteArray(), + scnFlags, + c.hasRelocations()); + // Add this section to our list + sections.add(sect); + + // Record the section Id (0 relative) + c.setSectionId(sections.size()-1); + + // TODO: Clear out code section data to allow for GC + // c.clear(); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, /*c.getContainerName()*/ "__text", "__TEXT", + section_64.S_ATTR_PURE_INSTRUCTIONS| + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, c.getContainerName(), "__TEXT", + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR); + } + + /** + * Create an MachO relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createMachORelocObject(Map> relocationTable, Collection symbols) throws IOException { + // Allocate MachO Header + // with 4 load commands + // LC_SEGMENT_64 + // LC_VERSION_MIN_MACOSX + // LC_SYMTAB + // LC_DYSYMTAB + + MachOHeader mh = new MachOHeader(); + + ArrayList sections = new ArrayList(); + + // Create Sections contained in the main Segment LC_SEGMENT_64 + + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + // Update the Header sizeofcmds size. + // This doesn't include the Header struct size + mh.setCmdSizes(4, segment_command_64.totalsize + + (section_64.totalsize * sections.size()) + + version_min_command.totalsize + + symtab_command.totalsize + + dysymtab_command.totalsize); + + // Initialize file offset for data past commands + int file_offset = mach_header_64.totalsize + mh.getCmdSize(); + // and round it up + file_offset = (file_offset + (sections.get(0).getAlign()-1)) & ~((sections.get(0).getAlign()-1)); + long address = 0; + int segment_offset = file_offset; + + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + file_offset = (file_offset + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + address = (address + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + sect.setOffset(file_offset); + sect.setAddr(address); + file_offset += sect.getSize(); + address += sect.getSize(); + } + + // File size for Segment data + int segment_size = file_offset - segment_offset; + + // Create the LC_SEGMENT_64 Segment which contains the MachOSections + MachOSegment seg = new MachOSegment(segment_command_64.totalsize + + (section_64.totalsize * sections.size()), + segment_offset, + segment_size, + sections.size()); + + + MachOVersion vers = new MachOVersion(); + + // Get symbol data from BinaryContainer object's symbol tables + MachOSymtab symtab = createMachOSymbolTables(sections, symbols); + + // Create LC_DYSYMTAB command + MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(), + symtab.getNumGlobalSyms(), + symtab.getNumUndefSyms()); + + // Create the Relocation Tables + MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab); + // Calculate file offset for relocation data + file_offset = (file_offset + (machORelocs.getAlign()-1)) & ~((machORelocs.getAlign()-1)); + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = machORelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + file_offset += (nreloc * reloc_info.totalsize); + } + } + + // Calculate and set file offset for symbol table data + file_offset = (file_offset + (symtab.getAlign()-1)) & ~((symtab.getAlign()-1)); + symtab.setOffset(file_offset); + + + // Write Out Header + machoContainer.writeBytes(mh.getArray()); + // Write out first Segment + machoContainer.writeBytes(seg.getArray()); + // Write out sections within first Segment + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getArray()); + } + + // Write out LC_VERSION_MIN_MACOSX command + machoContainer.writeBytes(vers.getArray()); + + // Write out LC_SYMTAB command + symtab.calcSizes(); + machoContainer.writeBytes(symtab.getCmdArray()); + + // Write out LC_DYSYMTAB command + machoContainer.writeBytes(dysymtab.getArray()); + + // Write out data associated with each Section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getDataArray(), sect.getAlign()); + } + + // Write out the relocation tables for all sections + for (int i = 0; i < sections.size(); i++) { + if (machORelocs.getNumRelocs(i) > 0) + machoContainer.writeBytes(machORelocs.getRelocData(i), machORelocs.getAlign()); + } + + // Write out data associated with LC_SYMTAB + machoContainer.writeBytes(symtab.getDataArray(), symtab.getAlign()); + + machoContainer.close(); + } + + /** + * Construct MachO symbol data from BinaryContainer object's symbol tables. Both dynamic MachO + * symbol table and MachO symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + * @param symtab + */ + private MachOSymtab createMachOSymbolTables(ArrayListsections, + Collection symbols) { + MachOSymtab symtab = new MachOSymtab(); + // First, create the initial null symbol. This is a local symbol. + symtab.addSymbolEntry("", (byte)nlist_64.N_UNDF, (byte)0, (long)0); + + // Now create MachO symbol entries for all symbols. + for (Symbol symbol : symbols) { + int sectionId = symbol.getSection().getSectionId(); + + // Symbol offsets are relative to the section memory addr + long sectionAddr = sections.get(sectionId).getAddr(); + + MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(), + getMachOTypeOf(symbol), + (byte)sectionId, + symbol.getOffset() + sectionAddr); + symbol.setNativeSymbol((NativeSymbol)machoSymbol); + } + + // Now that all symbols are enterred, update the + // symbol indexes. This is necessary since they will + // be reordered based on local, global and undefined. + symtab.updateIndexes(); + + return (symtab); + } + + private static byte getMachOTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + byte type = nlist_64.N_UNDF; + + // Global or Local + if (sym.getBinding() == Symbol.Binding.GLOBAL) + type = nlist_64.N_EXT; + + // If Function or Data, add section type + if (kind == Symbol.Kind.NATIVE_FUNCTION || + kind == Symbol.Kind.JAVA_FUNCTION || + kind == Symbol.Kind.OBJECT) { + type |= (nlist_64.N_SECT); + } + + return (type); + } + + /** + * Construct a MachO relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + * @param symtab + */ + private MachORelocTable createMachORelocTable(ArrayList sections, + Map> relocationTable, + MachOSymtab symtab) { + + MachORelocTable machORelocTable = new MachORelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a MachO relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, machORelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), machORelocTable); + } + + return (machORelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) { + RelocType relocType = reloc.getType(); + + int machORelocType = getMachORelocationType(relocType); + MachOSymbol sym = (MachOSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int pcrel = 0; + int length = 0; + int isextern = 1; + +/* + System.out.println("reloctype: " + relocType + " size is " + + reloc.getSize() + " offset is " + offset + + " Section Index is " + (sectindex) + + " Symbol Index is " + symno + + " Symbol Name is " + symbol.getName() + "\n"); +*/ + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + // System.out.println("getMachORelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + int addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + pcrel = 1; length = 2; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + int addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + pcrel = 0; length = 3; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 0; length = 2; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 1; length = 2; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + pcrel = 0; length = 3; + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + machORelocTable.createRelocationEntry(sectindex, offset, symno, + pcrel, length, isextern, + machORelocType); + } + + private static int getMachORelocationType(RelocType relocType) { + int machORelocType = 0; + switch (MachOTargetInfo.getMachOArch()) { + case mach_header_64.CPU_TYPE_X86_64: + // Return X86_64_RELOC_* entries based on relocType + if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { + machORelocType = reloc_info.X86_64_RELOC_NONE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + machORelocType = reloc_info.X86_64_RELOC_GOT; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return machORelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java new file mode 100644 index 00000000000..752723f25dc --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +/** + * + * Support for the creation of Mach-o Object files. + * Current support is limited to 64 bit x86_64. + * + * File Format Overview: + * + * mach_header + * load_commands + * Typical Mac OSX 64-bit object files have these 4 load_commands + * (LC_SEGMENT_64, LC_SYMTAB, LC_VERSIN_MIN_MACOSX, LC_DYSYMTAB) + * Segments corresponding to load_commands + * (which each include multiple Sections) + */ + +public class MachO { + + /** + * mach_header_64 structure defines + */ + public enum mach_header_64 { + magic( 0, 4), + cputype( 4, 4), + cpusubtype( 8, 4), + filetype(12, 4), + ncmds(16, 4), + sizeofcmds(20, 4), + flags(24, 4), + reserved(28, 4); + + public final int off; + public final int sz; + + mach_header_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 32; + + /** + * mach_header_64 defines + */ + public static final int MH_MAGIC = 0xfeedface; + public static final int MH_MAGIC_64 = 0xfeedfacf; + public static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000; + + /** + * filetype + */ + public static final int MH_OBJECT = 0x1; + + /** + * cputype + */ + public static final int CPU_TYPE_ANY = -1; + public static final int CPU_ARCH_ABI64 = 0x1000000; + public static final int CPU_TYPE_X86_64 = 0x1000007; + public static final int CPU_TYPE_ARM64 = 0x100000c; + /** + * cpusubtype + */ + public static final int CPU_SUBTYPE_I386_ALL = 3; + public static final int CPU_SUBTYPE_ARM64_ALL = 0; + public static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0; + public static final int CPU_SUBTYPE_BIG_ENDIAN = 1; + + } + + /** + * segment_command_64 structure defines + */ + public enum segment_command_64 { + cmd( 0, 4), + cmdsize( 4, 4), + segname( 8,16), + vmaddr(24, 8), + vmsize(32, 8), + fileoff(40, 8), + filesize(48, 8), + maxprot(56, 4), + initprot(60, 4), + nsects(64, 4), + flags(68, 4); + + public final int off; + public final int sz; + + segment_command_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 72; + + public static final int LC_SEGMENT_64 = 0x19; + } + + /** + * section_64 structure defines + */ + public enum section_64 { + sectname( 0,16), + segname(16,16), + addr(32, 8), + size(40, 8), + offset(48, 4), + align(52, 4), + reloff(56, 4), + nreloc(60, 4), + flags(64, 4), + reserved1(68, 4), + reserved2(72, 4), + reserved3(76, 4); + + public final int off; + public final int sz; + + section_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static int S_REGULAR = 0x0; + public static int S_CSTRING_LITERALS = 0x2; + public static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000; + public static int S_ATTR_SOME_INSTRUCTIONS = 0x400; + } + + /** + * version_min_command structure defines + */ + public enum version_min_command { + cmd( 0, 4), + cmdsize( 4, 4), + version( 8, 4), + sdk(12, 4); + + public final int off; + public final int sz; + + version_min_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int LC_VERSION_MIN_MACOSX = 0x24; + public static final int LC_VERSION_MIN_IPHONEOS = 0x25; + } + + /** + * symtab_command structure defines + */ + public enum symtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + symoff( 8, 4), + nsyms(12, 4), + stroff(16, 4), + strsize(20, 4); + + public final int off; + public final int sz; + + symtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int LC_SYMTAB = 0x2; + } + + /** + * Symbol table entry definitions + * + * nlist_64 structure defines + */ + public enum nlist_64 { + n_strx( 0, 4), + n_type( 4, 1), + n_sect( 5, 1), + n_desc( 6, 2), + n_value( 8, 8); + + public final int off; + public final int sz; + + nlist_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int N_EXT = 0x1; + public static final int N_TYPE = 0xe; + public static final int N_UNDF = 0x0; + public static final int N_SECT = 0xe; + } + + /** + * dysymtab_command structure defines + */ + public enum dysymtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + ilocalsym( 8, 4), + nlocalsym(12, 4), + iextdefsym(16, 4), + nextdefsym(20, 4), + iundefsym(24, 4), + nundefsym(28, 4), + tocoff(32, 4), + ntoc(36, 4), + modtaboff(40, 4), + nmodtab(44, 4), + extrefsymoff(48, 4), + nextrefsyms(52, 4), + indirectsymoff(56, 4), + nindirectsyms(60, 4), + extreloff(64, 4), + nextrel(68, 4), + locreloff(72, 4), + nlocrel(76, 4); + + public final int off; + public final int sz; + + dysymtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static final int LC_DYSYMTAB = 0xb; + } + + /** + * relocation_info structure defines + */ + public enum reloc_info { + r_address( 0, 4), + r_relocinfo( 4, 4); + + public final int off; + public final int sz; + + reloc_info(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 8; + + public static final int REL_SYMNUM_MASK = 0xffffff; + public static final int REL_SYMNUM_SHIFT = 0x0; + public static final int REL_PCREL_MASK = 0x1; + public static final int REL_PCREL_SHIFT = 0x18; + public static final int REL_LENGTH_MASK = 0x3; + public static final int REL_LENGTH_SHIFT = 0x19; + public static final int REL_EXTERN_MASK = 0x1; + public static final int REL_EXTERN_SHIFT = 0x1b; + public static final int REL_TYPE_MASK = 0xf; + public static final int REL_TYPE_SHIFT = 0x1c; + + /* reloc_type_x86_64 defines */ + + public static final int X86_64_RELOC_NONE = 0x0; + public static final int X86_64_RELOC_BRANCH = 0x2; + public static final int X86_64_RELOC_GOT = 0x4; + public static final int X86_64_RELOC_GOT_LOAD = 0x3; + public static final int X86_64_RELOC_SIGNED = 0x1; + public static final int X86_64_RELOC_UNSIGNED = 0x0; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java new file mode 100644 index 00000000000..14b75387277 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +public class MachOByteBuffer { + + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (MachOTargetInfo.getMachOEndian() == + MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java new file mode 100644 index 00000000000..bcb46c368c7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.io.File; +import java.io.FileOutputStream; + +public class MachOContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public MachOContainer(String fileName) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("MachOContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("MachOContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java new file mode 100644 index 00000000000..4ede3869087 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachODySymtab { + ByteBuffer dysymtab; + + public MachODySymtab(int nlocal, int nglobal, int nundef) { + dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize); + + dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB); + dysymtab.putInt(dysymtab_command.cmdsize.off, dysymtab_command.totalsize); + dysymtab.putInt(dysymtab_command.ilocalsym.off, 0); + dysymtab.putInt(dysymtab_command.nlocalsym.off, nlocal); + dysymtab.putInt(dysymtab_command.iextdefsym.off, nlocal); + dysymtab.putInt(dysymtab_command.nextdefsym.off, nglobal); + dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal+nglobal); + dysymtab.putInt(dysymtab_command.nundefsym.off, nundef); + } + + public byte[] getArray() { + return dysymtab.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java new file mode 100644 index 00000000000..ae50f0186d9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOHeader { + ByteBuffer header; + + public MachOHeader() { + header = MachOByteBuffer.allocate(mach_header_64.totalsize); + + header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64); + header.putInt(mach_header_64.cputype.off, MachOTargetInfo.getMachOArch()); + header.putInt(mach_header_64.cpusubtype.off, MachOTargetInfo.getMachOSubArch()); + header.putInt(mach_header_64.flags.off, 0x2000); + header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT); + } + + public void setCmdSizes(int ncmds, int sizeofcmds) { + header.putInt(mach_header_64.ncmds.off, ncmds); + header.putInt(mach_header_64.sizeofcmds.off, sizeofcmds); + } + + public int getCmdSize() { + return (header.getInt(mach_header_64.sizeofcmds.off)); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java new file mode 100644 index 00000000000..f32cfda3d78 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocEntry { + ByteBuffer entry; + + public MachORelocEntry(int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + entry = MachOByteBuffer.allocate(reloc_info.totalsize); + + entry.putInt(reloc_info.r_address.off, offset); + + // Encode and store the relocation entry bitfields + entry.putInt(reloc_info.r_relocinfo.off, + ((symno & reloc_info.REL_SYMNUM_MASK) + << reloc_info.REL_SYMNUM_SHIFT) | + ((pcrel & reloc_info.REL_PCREL_MASK) + << reloc_info.REL_PCREL_SHIFT) | + ((length & reloc_info.REL_LENGTH_MASK) + << reloc_info.REL_LENGTH_SHIFT) | + ((isextern & reloc_info.REL_EXTERN_MASK) + << reloc_info.REL_EXTERN_SHIFT) | + ((type & reloc_info.REL_TYPE_MASK) + << reloc_info.REL_TYPE_SHIFT)); + } + + public byte[] getArray() { + return entry.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java new file mode 100644 index 00000000000..196ae4615a8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachORelocEntry; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocTable { + ArrayList> relocEntries; + int fileOffset; + + public MachORelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + MachORelocEntry entry = new MachORelocEntry(offset, + symno, + pcrel, + length, + isextern, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { + return (4); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + MachORelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java new file mode 100644 index 00000000000..890ff91e5ec --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + + public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations) { + section = MachOByteBuffer.allocate(section_64.totalsize); + + // TODO: Hotspot uses long section names. + // They are getting truncated. + // Is this a problem?? + byte[] sectNameBytes = sectName.getBytes(); + int sectNameMax = section_64.sectname.sz < sectNameBytes.length ? + section_64.sectname.sz : sectNameBytes.length; + + for (int i = 0; i < sectNameMax; i++) + section.put(section_64.sectname.off+i, sectNameBytes[i]); + + byte[] segNameBytes = segName.getBytes(); + int segNameMax = section_64.segname.sz < segNameBytes.length ? + section_64.segname.sz : segNameBytes.length; + + for (int i = 0; i < segNameMax; i++) + section.put(section_64.segname.off+i, segNameBytes[i]); + + section.putLong(section_64.size.off, sectData.length); + + // For now use 8 byte alignment + section.putInt(section_64.align.off, 3); + + section.putInt(section_64.flags.off, sectFlags); + + data = sectData; + + hasrelocations = hasRelocations; + } + + public long getSize() { + return section.getLong(section_64.size.off); + } + + public int getAlign() { + return (1 << section.getInt(section_64.align.off)); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setAddr(long addr) { + section.putLong(section_64.addr.off, addr); + } + + public long getAddr() { + return (section.getLong(section_64.addr.off)); + } + + public void setOffset(int offset) { + section.putInt(section_64.offset.off, offset); + } + + public int getOffset() { + return (section.getInt(section_64.offset.off)); + } + + public void setReloff(int offset) { + section.putInt(section_64.reloff.off, offset); + } + + public void setRelcount(int count) { + section.putInt(section_64.nreloc.off, count); + } + + public boolean hasRelocations() { + return hasrelocations; + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java new file mode 100644 index 00000000000..3f588512783 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSegment { + ByteBuffer segment; + + public MachOSegment(int size, int fileoff, int filesize, int nsects) { + segment = MachOByteBuffer.allocate(segment_command_64.totalsize); + + segment.putInt(segment_command_64.cmd.off, segment_command_64.LC_SEGMENT_64); + segment.putInt(segment_command_64.cmdsize.off, size); + segment.putInt(segment_command_64.maxprot.off, 7); + segment.putInt(segment_command_64.initprot.off, 7); + segment.putInt(segment_command_64.nsects.off, nsects); + segment.putInt(segment_command_64.flags.off, 0); + segment.putLong(segment_command_64.vmaddr.off, 0); + segment.putLong(segment_command_64.vmsize.off, filesize); + segment.putLong(segment_command_64.fileoff.off, fileoff); + segment.putLong(segment_command_64.filesize.off, filesize); + } + + public byte[] getArray() { + return segment.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java new file mode 100644 index 00000000000..7c4444d9cab --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymbol extends NativeSymbol { + ByteBuffer sym; + + public MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) { + super(symbolindex); + sym = MachOByteBuffer.allocate(nlist_64.totalsize); + + sym.putInt(nlist_64.n_strx.off, strindex); + sym.put(nlist_64.n_type.off, type); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.put(nlist_64.n_sect.off, (byte)(sectindex+1)); + sym.putChar(nlist_64.n_desc.off, (char )0); + sym.putLong(nlist_64.n_value.off, offset); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java new file mode 100644 index 00000000000..be24bc83cd8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOSymbol; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymtab { + + /** + * ByteBuffer holding the LC_SYMTAB command contents + */ + ByteBuffer symtabCmd; + + /** + * ByteBuffer holding the symbol table entries and strings + */ + ByteBuffer symtabData; + + int symtabDataSize; + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + ArrayListundefSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public MachOSymtab() { + symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize); + + symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB); + symtabCmd.putInt(symtab_command.cmdsize.off, symtab_command.totalsize); + + symbolCount = 0; + + } + + public int getAlign() { + return (4); + } + + public MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) { + // Get the current symbol index and append symbol name to string table. + int index; + MachOSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + strTabContent.append("_").append(name).append('\0'); + // + 1 for null, + 1 for "_" + strTabNrOfBytes += (name.getBytes().length + 1 + 1); + + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + switch (type) { + case nlist_64.N_EXT: + undefSymbols.add(sym); + break; + case nlist_64.N_SECT: + case nlist_64.N_UNDF: // null symbol + localSymbols.add(sym); + break; + case nlist_64.N_SECT|nlist_64.N_EXT: + globalSymbols.add(sym); + break; + default: + System.out.println("Unsupported Symbol type " + type); + break; + } + } + symbolCount++; + return (sym); + } + + public void setOffset(int symoff) { + symtabCmd.putInt(symtab_command.symoff.off, symoff); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local, global and Undefined. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + + // Update the undefined symbol indexes + for (int i = index; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + sym.setIndex(index++); + } + } + + // Update LC_SYMTAB command fields based on the number of symbols added + // return the file size taken up by symbol table entries and strings + public int calcSizes() { + int stroff; + + stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount); + symtabCmd.putInt(symtab_command.nsyms.off, symbolCount); + symtabCmd.putInt(symtab_command.stroff.off, stroff); + symtabCmd.putInt(symtab_command.strsize.off, strTabNrOfBytes); + symtabDataSize = (nlist_64.totalsize * symbolCount) + strTabNrOfBytes; + + return (symtabDataSize); + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + public int getNumUndefSyms() { return undefSymbols.size(); } + + public byte[] getCmdArray() { + return symtabCmd.array(); + } + + // Create a single byte array that contains the symbol table entries + // and string table + public byte[] getDataArray() { + int index = 0; + symtabData = MachOByteBuffer.allocate(symtabDataSize); + byte [] retarray; + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the undefined symbols + for (int i = 0; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + + // Add the stringtable + byte [] strs = strTabContent.toString().getBytes(); + symtabData.put(strs); + + retarray = symtabData.array(); + + return (retarray); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java new file mode 100644 index 00000000000..1a0a199d499 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class MachOTargetInfo { + /** + * Target architecture and subtype. + */ + private static final int arch; + private static final int subarch; + + /** + * Architecture endian-ness. + */ + private static final int endian = mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN; + + /** + * Target OS string. + */ + private static final String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = mach_header_64.CPU_TYPE_X86_64; + subarch = mach_header_64.CPU_SUBTYPE_I386_ALL; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = mach_header_64.CPU_TYPE_ANY; + subarch = 0; + } + + osName = System.getProperty("os.name").toLowerCase(); + } + + public static int getMachOArch() { + return arch; + } + + public static int getMachOSubArch() { + return subarch; + } + + public static int getMachOEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java new file mode 100644 index 00000000000..57475aeb0eb --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOVersion { + ByteBuffer version; + + public MachOVersion() { + version = MachOByteBuffer.allocate(version_min_command.totalsize); + + version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX); + version.putInt(version_min_command.cmdsize.off, version_min_command.totalsize); + version.putInt(version_min_command.version.off, (10 << 16) | (10 << 8)); /* MacOSX 10.10 */ + version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */ + } + + public byte[] getArray() { + return version.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java new file mode 100644 index 00000000000..a5f47f03cd1 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.Container; +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; + +public class JPECoffRelocObject { + + private final BinaryContainer binContainer; + + private final PECoffContainer pecoffContainer; + + private final int segmentSize; + + public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { + this.binContainer = binContainer; + this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion); + this.segmentSize = binContainer.getCodeSegmentSize(); + } + + private PECoffSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int scnFlags) { + + PECoffSection sect = new PECoffSection(sectName, + scnData, + scnFlags, + hasRelocs, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + PECoffSection sect; + boolean hasRelocs = c.hasRelocations(); + byte[] scnData = c.getByteArray(); + + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, + scnFlags); + + c.setSectionId(sect.getSectionId()); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_8BYTES; + + if (c.getByteArray().length > 0) + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA; + else + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA; + + createByteSection(sections, c, scnFlags); + } + + /** + * Create an PECoff relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createPECoffRelocObject(Map> relocationTable, Collection symbols) throws IOException { + ArrayList sections = new ArrayList(); + + // Create text section + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + + // Allocate PECoff Header + PECoffHeader header = new PECoffHeader(); + + // Get PECoff symbol data from BinaryContainer object's symbol tables + PECoffSymtab symtab = createPECoffSymbolTables(sections, symbols); + + // Add Linker Directives Section + createByteSection(sections, ".drectve", + symtab.getDirectiveArray(), false, + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_1BYTES); + + // Create the Relocation Tables + PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable); + + // File Output Order + // + // HEADER (Need address of Symbol Table + symbol count) + // SECTIONS (Need pointer to Section Data, Relocation Table) + // DIRECTIVES + // SYMBOL TABLE + // SYMBOLS + // SECTION DATA + // RELOCATION TABLE + + // Calculate Offset for Symbol table + int file_offset = IMAGE_FILE_HEADER.totalsize + + (IMAGE_SECTION_HEADER.totalsize*sections.size()); + + // Update Header fields + header.setSectionCount(sections.size()); + header.setSymbolCount(symtab.getSymtabCount()); + header.setSymbolOff(file_offset); + + // Calculate file offset for first section + file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) + + symtab.getStrtabSize()); + // And round it up + file_offset = (file_offset + (sections.get(0).getDataAlign()-1)) & + ~((sections.get(0).getDataAlign()-1)); + + // Calc file offsets for section data + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = pecoffRelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + // extended relocations add an addition entry + if (nreloc > 0xFFFF) nreloc++; + file_offset += (nreloc * IMAGE_RELOCATION.totalsize); + } + } + + // Write out the Header + pecoffContainer.writeBytes(header.getArray()); + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign()); + } + + // Write out the symbol table and string table + pecoffContainer.writeBytes(symtab.getSymtabArray(), 4); + pecoffContainer.writeBytes(symtab.getStrtabArray(), 1); + + // Write out each section contents + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out Relocation Tables + for (int i = 0; i < sections.size(); i++) { + if (pecoffRelocs.getNumRelocs(i) > 0) { + pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i)); + } + } + pecoffContainer.close(); + } + + /** + * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff + * symbol table and PECoff symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + */ + private PECoffSymtab createPECoffSymbolTables(ArrayList sections, Collection symbols) { + PECoffSymtab symtab = new PECoffSymtab(); + + // First, create the initial null symbol. This is a local symbol. + // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0); + + // Now create PECoff symbol entries for all symbols. + for (Symbol symbol : symbols) { + // Get the index of section this symbol is defined in. + int secHdrIndex = symbol.getSection().getSectionId(); + PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)pecoffSymbol); + } + return (symtab); + } + + private static byte getPECoffTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION; + } + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE; + } + + private static byte getPECoffClassOf(Symbol sym) { + Binding binding = sym.getBinding(); + if (binding == Symbol.Binding.GLOBAL) { + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL; + } + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC; + } + + /** + * Construct a PECoff relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + */ + private PECoffRelocTable createPECoffRelocTable(ArrayList sections, + Map> relocationTable) { + + PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a PECoff relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, pecoffRelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable); + } + + return (pecoffRelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) { + RelocType relocType = reloc.getType(); + + int pecoffRelocType = getPECoffRelocationType(relocType); + PECoffSymbol sym = (PECoffSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType); + } + + // Return IMAGE_RELOCATION Type based on relocType + private static int getPECoffRelocationType(RelocType relocType) { + int pecoffRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH + switch (PECoffTargetInfo.getPECoffArch()) { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return pecoffRelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java new file mode 100644 index 00000000000..74f6324742e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +/** + * + * Support for the creation of Coff files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class PECoff { + + /** + * IMAGE_FILE_HEADER structure defines + */ + public enum IMAGE_FILE_HEADER { + Machine( 0, 2), + NumberOfSections( 2, 2), + TimeDateStamp( 4, 4), + PointerToSymbolTable( 8, 4), + NumberOfSymbols(12, 4), + SizeOfOptionalHeader(16, 2), + Characteristics(18, 2); + + public final int off; + public final int sz; + + IMAGE_FILE_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 20; + + /** + * IMAGE_FILE_HEADER defines + */ + + /** + * Machine + */ + public static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0; + public static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664; + + } + + /** + * IMAGE_SECTION_HEADER structure defines + */ + public enum IMAGE_SECTION_HEADER { + Name( 0, 8), + PhysicalAddress( 8, 4), + VirtualSize( 8, 4), + VirtualAddress(12, 4), + SizeOfRawData(16, 4), + PointerToRawData(20, 4), + PointerToRelocations(24, 4), + PointerToLinenumbers(28, 4), + NumberOfRelocations(32, 2), + NumberOfLinenumbers(34, 2), + Characteristics(36, 4); + + public final int off; + public final int sz; + + IMAGE_SECTION_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 40; + + /** + * IMAGE_SECTION_HEADER defines + */ + + /** + * Characteristics + */ + public static final int IMAGE_SCN_CNT_CODE = 0x20; + public static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40; + public static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80; + public static final int IMAGE_SCN_LNK_COMDAT = 0x1000; + public static final int IMAGE_SCN_LNK_INFO = 0x200; + public static final int IMAGE_SCN_LNK_REMOVE = 0x800; + + public static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000; + public static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000; + public static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000; + public static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000; + public static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000; + public static final int IMAGE_SCN_ALIGN_MASK = 0xf00000; + public static final int IMAGE_SCN_ALIGN_SHIFT = 20; + + public static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; + + public static final int IMAGE_SCN_MEM_SHARED = 0x10000000; + public static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000; + public static final int IMAGE_SCN_MEM_READ = 0x40000000; + public static final int IMAGE_SCN_MEM_WRITE = 0x80000000; + + } + + /** + * Symbol table entry definitions + * + * IMAGE_SYMBOL structure defines + */ + public enum IMAGE_SYMBOL { + ShortName( 0, 8), + Short( 0, 4), + Long( 4, 4), + Value( 8, 4), + SectionNumber(12, 2), + Type(14, 2), + StorageClass(16, 1), + NumberOfAuxSymbols(17, 1); + + public final int off; + public final int sz; + + IMAGE_SYMBOL(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 18; + + /** + * Type + */ + public static final int IMAGE_SYM_DTYPE_NONE = 0x0; + public static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20; + + /** + * StorageClass + */ + public static final int IMAGE_SYM_CLASS_NULL = 0x0; + public static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2; + public static final int IMAGE_SYM_CLASS_STATIC = 0x3; + public static final int IMAGE_SYM_CLASS_LABEL = 0x6; + + } + + /** + * IMAGE_RELOCATION structure defines + */ + public enum IMAGE_RELOCATION { + VirtualAddress( 0, 4), + SymbolTableIndex( 4, 4), + Type( 8, 2); + + public final int off; + public final int sz; + + IMAGE_RELOCATION(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 10; + + /** + * Relocation types + */ + public static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0; + public static final int IMAGE_REL_AMD64_ADDR32 = 0x2; + public static final int IMAGE_REL_AMD64_ADDR64 = 0x1; + public static final int IMAGE_REL_AMD64_REL32 = 0x4; + public static final int IMAGE_REL_AMD64_REL32_1 = 0x5; + public static final int IMAGE_REL_AMD64_REL32_2 = 0x6; + public static final int IMAGE_REL_AMD64_REL32_3 = 0x7; + public static final int IMAGE_REL_AMD64_REL32_4 = 0x8; + public static final int IMAGE_REL_AMD64_REL32_5 = 0x9; + + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java similarity index 70% rename from hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java index 08e271028b6..e212c6b64d7 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -21,15 +21,18 @@ * questions. */ -package jdk.tools.jaotc.jnilibelf; +package jdk.tools.jaotc.binformat.pecoff; -import jdk.internal.misc.Unsafe; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { +public class PECoffByteBuffer { - static final Unsafe UNSAFE = Unsafe.getUnsafe(); + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + // Only support Little Endian on Windows + buf.order(ByteOrder.LITTLE_ENDIAN); + return (buf); + } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java new file mode 100644 index 00000000000..75158fd219f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.io.File; +import java.io.FileOutputStream; + +public class PECoffContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public PECoffContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("PECoffContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("PECoffContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java new file mode 100644 index 00000000000..7d2c84f841d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffHeader { + ByteBuffer header; + + public PECoffHeader() { + header = PECoffByteBuffer.allocate(IMAGE_FILE_HEADER.totalsize); + + header.putChar(IMAGE_FILE_HEADER.Machine.off, IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64); + header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int)(System.currentTimeMillis()/1000)); + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, 0); + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, 0); + header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char)0); + header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char)0); + + } + + // Update header with the number of total sections + public void setSectionCount(int count) { + header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char)count); + } + + // Update header with the number of total symbols + public void setSymbolCount(int count) { + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count); + } + + // Update header with the offset of symbol table + public void setSymbolOff(int offset) { + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java new file mode 100644 index 00000000000..11284dc77a4 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocEntry { + ByteBuffer entry; + + public PECoffRelocEntry(int offset, int symno, int type) { + + entry = PECoffByteBuffer.allocate(IMAGE_RELOCATION.totalsize); + + entry.putInt(IMAGE_RELOCATION.VirtualAddress.off, offset); + entry.putInt(IMAGE_RELOCATION.SymbolTableIndex.off, symno); + entry.putChar(IMAGE_RELOCATION.Type.off, (char)type); + } + + public byte[] getArray() { + return entry.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java new file mode 100644 index 00000000000..c51b9e8710a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffRelocEntry; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocTable { + ArrayList> relocEntries; + + public PECoffRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type) { + + PECoffRelocEntry entry = new PECoffRelocEntry(offset, + symno, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { return (4); } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + int entryCount = entryList.size(); + int allocCount = entryCount; + + if (entryCount == 0) + return null; + + if (entryCount > 0xFFFF) + allocCount++; + + ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize); + + // If number of relocs exceeds 65K, add the real size + // in a dummy first reloc entry + if (entryCount > 0xFFFF) { + PECoffRelocEntry entry = new PECoffRelocEntry(allocCount, 0, 0); + relocData.put(entry.getArray()); + } + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryCount; i++) { + PECoffRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java new file mode 100644 index 00000000000..0e05fdb830a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + int align; + + public PECoffSection(String sectName, byte [] sectData, int sectFlags, + boolean hasRelocations, int sectIndex) { + + section = PECoffByteBuffer.allocate(IMAGE_SECTION_HEADER.totalsize); + + // bug: If JVM.oop.got section is empty, VM exits since JVM.oop.got + // symbol ends up as external forwarded reference. + if (sectData.length == 0) sectData = new byte[8]; + + // Copy only Max allowed bytes to Section Entry + byte [] Name = sectName.getBytes(); + int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ? + Name.length : IMAGE_SECTION_HEADER.Name.sz; + + section.put(Name, IMAGE_SECTION_HEADER.Name.off, max); + + section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0); + section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0); + section.putInt(IMAGE_SECTION_HEADER.SizeOfRawData.off, sectData.length); + section.putInt(IMAGE_SECTION_HEADER.PointerToLinenumbers.off, 0); + section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char)0); + + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, sectFlags); + + // Extract alignment from Characteristics field + int alignshift = (sectFlags & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) >> + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT; + + // Use 8 byte alignment if not specified + if (alignshift == 0) + alignshift = 3; + else + --alignshift; + + align = 1 << alignshift; + + data = sectData; + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public long getSize() { + return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off); + } + + public int getDataAlign() { + return (align); + } + + // Alignment requirements for the IMAGE_SECTION_HEADER structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int)offset); + } + + public long getOffset() { + return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off)); + } + + public void setReloff(int offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset); + } + + public void setRelcount(int count) { + // If the number of relocs is larger than 65K, then set + // the overflow bit. The real count will be written to + // the first reloc entry for this section. + if (count > 0xFFFF) { + int flags; + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)0xFFFF); + flags = section.getInt(IMAGE_SECTION_HEADER.Characteristics.off); + flags |= IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_NRELOC_OVFL; + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, flags); + } + else { + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)count); + } + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java new file mode 100644 index 00000000000..c305dbe071d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymbol extends NativeSymbol { + ByteBuffer sym; + + public PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize); + + // We don't use short names + sym.putInt(IMAGE_SYMBOL.Short.off, 0); + + sym.putInt(IMAGE_SYMBOL.Long.off, strindex); + sym.putInt(IMAGE_SYMBOL.Value.off, (int)offset); + + // Section indexes start at 1 but we manage the index internally + // as 0 relative except in this structure + sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char)(sectindex+1)); + + sym.putChar(IMAGE_SYMBOL.Type.off, (char)type); + sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass); + sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte)0); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java new file mode 100644 index 00000000000..34e0ef73f5e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymtab { + ArrayListsymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent; + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes; + + /** + * String holding Linker Directives + */ + private StringBuilder directives; + + public PECoffSymtab() { + symbolCount = 0; + strTabContent = new StringBuilder(); + directives = new StringBuilder(); + + // The first 4 bytes of the string table contain + // the length of the table (including this length field). + strTabNrOfBytes = 4; + + // Make room for the 4 byte length field + strTabContent.append('\0').append('\0').append('\0').append('\0'); + + // Linker Directives start with 3 spaces to signify ANSI + directives.append(" "); + } + + public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + PECoffSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + } else { + int nameSize = name.getBytes().length; + + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append('_').append(name).append('\0'); + strTabContent.append(name).append('\0'); + strTabNrOfBytes += (nameSize + 1); + + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) + addDirective(name, type); + } + symbolCount++; + return (sym); + } + + private void addDirective(String name, byte type) { + directives.append("/EXPORT:" + name); + if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) { + directives.append(",DATA"); + } + directives.append(" "); + } + + public int getSymtabCount() { + return symbolCount; + } + + public int getStrtabSize() { + return strTabNrOfBytes; + } + + // Return a byte array that contains the symbol table entries + public byte[] getSymtabArray() { + ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount*IMAGE_SYMBOL.totalsize); + symtabData.order(ByteOrder.LITTLE_ENDIAN); + + // copy all symbols + for (int i = 0; i < symbolCount; i++ ) { + PECoffSymbol sym = symbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + return (symtabData.array()); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + + // Update the size of the string table + ByteBuffer buff = ByteBuffer.wrap(strs); + buff.order(ByteOrder.LITTLE_ENDIAN); + buff.putInt(0, strTabNrOfBytes); + + return (strs); + } + + public byte[] getDirectiveArray() { + return (directives.toString().getBytes()); + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java new file mode 100644 index 00000000000..9c40f64733f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class PECoffTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.contains("windows")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getPECoffArch() { + return arch; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java deleted file mode 100644 index ddad5a018da..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -/** - * This class represents a {@code Elf32_Sym} or {@code Elf64_Sym} as defined in {@code elf.h}. - */ -public class ELFSymbol { - /** Symbol name. */ - private final String name; - - /** String table index. */ - private final int index; - - /** Native memory address of ELF sym entry. */ - private final Pointer address; - private final boolean isLocal; - - public ELFSymbol(String name, int index, Pointer address, boolean isLocal) { - this.name = name; - this.index = index; - this.address = address; - this.isLocal = isLocal; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @return the index - */ - public int getIndex() { - return index; - } - - /** - * @return the address - */ - public Pointer getAddress() { - return address; - } - - @Override - public String toString() { - return "name=" + name + ", index=" + index + ", address=" + address; - } - - public boolean isLocal() { - return isLocal; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java deleted file mode 100644 index 64d699f0371..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -import java.io.File; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; - -/** - * A class abstraction of an ELF file. - * - */ -public class JNIELFContainer { - - private String outputFileName; - private File outFile; - private int outFileDesc; - - /** - * Pointer to Elf file. This is the same as struct Elf found in libelf.h - */ - private Pointer elfPtr; - - /** - * Class of the ELF container - one of ELFCLASS32 or ELFCLASS64. - */ - private final int elfClass; - - /** - * Pointer to ELF Header. - */ - private Pointer ehdrPtr; - - /** - * Pointer to Program Header. - */ - private Pointer phdrPtr; - - /** - * String holding .shstrtab contents. - */ - private String shStrTabContent = ""; - - /** - * Map of local symbol indexes to ELF symbol entries. - */ - private List localSymbolIndex = new ArrayList<>(); - - /** - * Map of global symbol indexes to ELF symbol entries. - */ - private List globalSymbolIndex = new ArrayList<>(); - - /** - * String holding .strtab contents. - */ - private StringBuilder strTabContent = new StringBuilder(); - - /** - * Keeps track of nr of bytes in .strtab since strTabContent.length() is number of chars, not - * bytes. - */ - private int strTabNrOfBytes = 0; - - /** - * A hashtable that holds (section-name, relocation-table) pairs. For example, [(".rela.text", - * rela-text-reloc-entries), (".rela.plt", rela-plt-reloc-entries), ...]. - */ - private Map> relocTables = new HashMap<>(); - - /** - * Create reloca; 0 => false and non-zero => true. - */ - private final int createReloca; - - /** - * Construct an ELFContainer in preparation for a disk image with file {@code prefix}. - * - * @param fileName name of ELF file to be created - */ - public JNIELFContainer(String fileName, String aotVersion) { - // Check for version compatibility - if (!JNILibELFAPI.elfshim_version().equals(aotVersion)) { - throw new InternalError("libelfshim version mismatch: " + JNILibELFAPI.elfshim_version() + " vs " + aotVersion); - } - - elfClass = JNIELFTargetInfo.getELFClass(); - createReloca = JNIELFTargetInfo.createReloca(); - outputFileName = fileName; - } - - /** - * Get the local ELF symbol table. - * - * @return local symbol table - */ - public List getLocalSymbols() { - return localSymbolIndex; - } - - /** - * Get the global ELF symbol table. - * - * @return list of global ELF symbol table entries - */ - public List getGlobalSymbols() { - return globalSymbolIndex; - } - - /** - * Get string table content (.strtab). - * - * @return string table content - */ - public String getStrTabContent() { - return strTabContent.toString(); - } - - /** - * Get section header string table content (.shstrtab). - * - * @return section header string table content - */ - public String getShStrTabContent() { - return shStrTabContent; - } - - /** - * Get relocation tables. - * - * @return relocation tables - */ - public Map> getRelocTables() { - return relocTables; - } - - /** - * Get the index of first non-local symbol in symbol table. - * - * @return symbol table index - */ - public int getFirstNonLocalSymbolIndex() { - return localSymbolIndex.size(); - } - - /** - * Create ELF header of type {@code ececType}. - * - * @param type type of ELF executable - */ - public void createELFHeader(int type) { - // Check for version compatibility - if (JNILibELFAPI.elf_version(ELF.EV_CURRENT) == ELF.EV_NONE) { - throw new InternalError("ELF version mismatch"); - } - - outFile = constructRelocFile(outputFileName); - // Open a temporary file for the shared library to be created - // TODO: Revisit file permissions; need to add execute permission - outFileDesc = JNILibELFAPI.open_rw(outFile.getPath()); - - if (outFileDesc == -1) { - System.out.println("Failed to open file " + outFile.getPath() + " to write relocatable object."); - } - - elfPtr = JNILibELFAPI.elf_begin(outFileDesc, LibELF.Elf_Cmd.ELF_C_WRITE.intValue(), new Pointer(0L)); - if (elfPtr == null) { - throw new InternalError("elf_begin failed"); - } - - // Allocate new Ehdr of current architecture class - - ehdrPtr = JNILibELFAPI.gelf_newehdr(elfPtr, elfClass); - - JNILibELFAPI.ehdr_set_data_encoding(ehdrPtr, JNIELFTargetInfo.getELFEndian()); - JNILibELFAPI.set_Ehdr_e_machine(elfClass, ehdrPtr, JNIELFTargetInfo.getELFArch()); - JNILibELFAPI.set_Ehdr_e_type(elfClass, ehdrPtr, type); - JNILibELFAPI.set_Ehdr_e_version(elfClass, ehdrPtr, ELF.EV_CURRENT); - } - - /** - * If the file name has a .so extension, replace it with .o extension. Else just add .o - * extension - * - * @param fileName - * @return File object - */ - private static File constructRelocFile(String fileName) { - File relocFile = new File(fileName); - if (relocFile.exists()) { - if (!relocFile.delete()) { - throw new InternalError("Failed to delete existing " + fileName + " file"); - } - } - return relocFile; - } - - /** - * Create {@code count} number of Program headers. - * - * @param count number of program headers to create - * @return true upon success; false upon failure - */ - public boolean createProgramHeader(int count) { - phdrPtr = JNILibELFAPI.gelf_newphdr(elfPtr, count); - if (phdrPtr == null) { - System.out.println("gelf_newphdr error"); - return false; - } - return true; - } - - /** - * Set program header to be of type self. - * - * @return true - */ - public boolean setProgHdrTypeToSelf() { - // Set program header to be of type self - JNILibELFAPI.phdr_set_type_self(elfClass, ehdrPtr, phdrPtr); - // And thus mark it as dirty so that elfUpdate can recompute the structures - JNILibELFAPI.elf_flagphdr(elfPtr, LibELF.Elf_Cmd.ELF_C_SET.intValue(), LibELF.ELF_F_DIRTY); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Create a section. The corresponding section header and section data are created by calling - * the necessary libelf APIs. The section that is created is inserted into the ELF container. - * - * @param secName name of the section - * @param scnData section data - * @param dataType data type - * @param align section alignment - * @param scnType section type - * @param scnFlags section flags - * @param scnLink sh_link field of Elf{32,64}_Shdr - * @param scnInfo sh_info field of Elf{32,64}_Shdr - * @return section index - */ - public int createSection(String secName, byte[] scnData, Elf_Type dataType, int align, int scnType, int scnFlags, int scnLink, int scnInfo) { - // Create a new section - Pointer scnPtr = JNILibELFAPI.elf_newscn(elfPtr); - if (scnPtr == null) { - throw new InternalError("elf_newscn error"); - } - - // Allocate section data for the section - Pointer scnDataPtr = JNILibELFAPI.elf_newdata(scnPtr); - if (scnDataPtr == null) { - String errMsg = JNILibELFAPI.elf_errmsg(-1); - throw new InternalError("elf_newdata error: " + errMsg); - } - - // Get the pointer to section header associated with the new section - Pointer scnHdrPtr = JNILibELFAPI.elf64_getshdr(scnPtr); - - // Add name of the section to section name string - // If secName is null, point the name to the 0th index - // that holds `\0' - byte[] modScnData; - if (secName.isEmpty()) { - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, 0); - modScnData = scnData; - } else { - if (secName.equals(".shstrtab")) { - // Modify .shstrtab data by inserting '\0' at index 0 - String shstrtabSecName = ".shstrtab" + '\0'; - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1 + shstrtabSecName.length()); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - nbuf.position(scnData.length + 1); - // Add the section name ".shstrtab" to its own data - nbuf.put(shstrtabSecName.getBytes(StandardCharsets.UTF_8)); - modScnData = nbuf.array(); - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, scnData.length + 1); - // Set strtab section index - JNILibELFAPI.set_Ehdr_e_shstrndx(elfClass, ehdrPtr, JNILibELFAPI.elf_ndxscn(scnPtr)); - } else if (secName.equals(".strtab")) { - // Modify strtab section data to insert '\0' at position 0. - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - modScnData = nbuf.array(); - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - } else { - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - modScnData = scnData; - } - } - - final int scnDataBufSize = modScnData.length; - - Pointer scnDataBufPtr = null; - if (scnType != ELF.SHT_NOBITS) { - // Allocate native memory for section data - final long address = UNSAFE.allocateMemory(scnDataBufSize + 1); - scnDataBufPtr = new Pointer(address); - scnDataBufPtr.put(modScnData); - } else { - scnDataBufPtr = new Pointer(0L); - } - - // Set data descriptor fields - JNILibELFAPI.set_Data_d_align(scnDataPtr, align); - JNILibELFAPI.set_Data_d_buf(scnDataPtr, scnDataBufPtr); - JNILibELFAPI.set_Data_d_size(scnDataPtr, scnDataBufSize); - JNILibELFAPI.set_Data_d_off(scnDataPtr, 0); - JNILibELFAPI.set_Data_d_type(scnDataPtr, dataType.intValue()); - JNILibELFAPI.set_Data_d_version(scnDataPtr, ELF.EV_CURRENT); - - JNILibELFAPI.set_Shdr_sh_type(elfClass, scnHdrPtr, scnType); - JNILibELFAPI.set_Shdr_sh_flags(elfClass, scnHdrPtr, scnFlags); - JNILibELFAPI.set_Shdr_sh_entsize(elfClass, scnHdrPtr, 0); // TODO: Is this right?? - JNILibELFAPI.set_Shdr_sh_link(elfClass, scnHdrPtr, scnLink); - JNILibELFAPI.set_Shdr_sh_info(elfClass, scnHdrPtr, scnInfo); - - // Add hash section to section pointer list - int index = JNILibELFAPI.elf_ndxscn(scnPtr); - return index; - } - - /** - * Create an ELF symbol entry for a symbol with the given properties. - * - * @param name name of the section in which symName is referenced - * @param type type of symName - * @param bind binding of symName - * @param secHdrIndex section header index of the section in which symName is referenced - * (st_shndx of ELF symbol entry) - * @param size symName size (st_size of ELF symbol entry) - * @param value symName value (st_value of ELF symbol entry) - * @param isLocal true if symbol is local. - */ - public ELFSymbol createELFSymbolEntry(String name, int type, int bind, int secHdrIndex, int size, int value, boolean isLocal) { - // Get the current symbol index and append symbol name to string table. - int index; - if (name.isEmpty()) { - index = 0; - } else { - // NOTE: The +1 comes from the null symbol! - // We can't trust strTabContent.length() since that is chars (UTF16), keep track of - // bytes on our own. - index = strTabNrOfBytes + 1; - strTabContent.append(name).append('\0'); - strTabNrOfBytes += name.getBytes(StandardCharsets.UTF_8).length + 1; - } - - // Create ELF symbol entry - long address = JNILibELFAPI.create_sym_entry(elfClass, index, type, bind, secHdrIndex, size, value); - if (address == 0) { - throw new InternalError("create_sym_entry failed"); - } - Pointer ptr = new Pointer(address); - - if (isLocal) { - final int localIndex = localSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, localIndex, ptr, isLocal); - localSymbolIndex.add(symbol); - return symbol; - } else { - final int globalIndex = globalSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, globalIndex, ptr, isLocal); - globalSymbolIndex.add(symbol); - return symbol; - } - } - - /** - * Create an ELF relocation entry for given symbol {@code name} to section {@code secname}. - * - * @param container the section - * @param offset offset into the section contents at which the relocation needs to be applied - * @param type ELF type of the relocation entry - * @param addend Addend for for relocation of type reloca - */ - public void createELFRelocationEntry(ELFContainer container, int offset, int type, int addend, ELFSymbol elfSymbol) { - // Get the index of the symbol. - int index; - if (elfSymbol.isLocal()) { - index = elfSymbol.getIndex(); - } else { - /* - * For global symbol entries the index will be offset by the number of local symbols - * which will be listed first in the symbol table. - */ - index = elfSymbol.getIndex() + localSymbolIndex.size(); - } - - long address = JNILibELFAPI.create_reloc_entry(elfClass, offset, index, type, addend, createReloca); - if (address == 0) { - throw new InternalError("create_reloc_entry failed"); - } - Pointer ptr = new Pointer(address); - /* - * If section name associated with this symbol is set to undefined i.e., secname is null, - * symIndex is undef i.e., 0. - */ - if (relocTables.get(container) == null) { - // Allocate a new table and add it to the hash table of reloc tables - relocTables.put(container, new ArrayList<>()); - } - - // Add the entry - relocTables.get(container).add(ptr); - } - - /** - * Invokes native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param cmd command - * @return return value of the native function called - */ - public boolean elfUpdate(LibELF.Elf_Cmd cmd) { - JNILibELFAPI.elf_update(elfPtr, cmd.intValue()); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Wrapper function that invokes int elf_end (Elf *elfPtr). and closes ELF output file - * descriptor - * - * @return true - */ - public boolean elfEnd() { - // Finish ELF processing - JNILibELFAPI.elf_end(elfPtr); - // Close file descriptor - JNILibELFAPI.close(outFileDesc); - return true; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java deleted file mode 100644 index 4c4cffd7abe..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -/** - * Class that abstracts ELF relocations. - * - */ -public interface JNIELFRelocation { - int R_UNDEF = -1; - - /** - * x86-specific relocation types. - * - */ - public interface I386 { - /* i386 relocs. */ - - int R_386_NONE = 0; /* No reloc */ - int R_386_32 = 1; /* Direct 32 bit */ - int R_386_PC32 = 2; /* PC relative 32 bit */ - int R_386_GOT32 = 3; /* 32 bit GOT entry */ - int R_386_PLT32 = 4; /* 32 bit PLT address */ - int R_386_COPY = 5; /* Copy symbol at runtime */ - int R_386_GLOB_DAT = 6; /* Create GOT entry */ - int R_386_JMP_SLOT = 7; /* Create PLT entry */ - int R_386_RELATIVE = 8; /* Adjust by program base */ - int R_386_GOTOFF = 9; /* 32 bit offset to GOT */ - int R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */ - int R_386_32PLT = 11; - int R_386_TLS_TPOFF = 14; /* Offset in static TLS block */ - int R_386_TLS_IE = 15; /* Address of GOT entry for static TLS block offset */ - int R_386_TLS_GOTIE = 16; /* GOT entry for static TLS block offset */ - int R_386_TLS_LE = 17; /* Offset relative to static TLS block */ - int R_386_TLS_GD = 18; /* Direct 32 bit for GNU version of general dynamic thread local data */ - int R_386_TLS_LDM = 19; /* - * Direct 32 bit for GNU version of local dynamic thread local data - * in LE code - */ - int R_386_16 = 20; - int R_386_PC16 = 21; - int R_386_8 = 22; - int R_386_PC8 = 23; - int R_386_TLS_GD_32 = 24; /* Direct 32 bit for general dynamic thread local data */ - int R_386_TLS_GD_PUSH = 25; /* Tag for pushl in GD TLS code */ - int R_386_TLS_GD_CALL = 26; /* Relocation for call to __tls_get_addr() */ - int R_386_TLS_GD_POP = 27; /* Tag for popl in GD TLS code */ - int R_386_TLS_LDM_32 = 28; /* Direct 32 bit for local dynamic thread local data in LE code */ - int R_386_TLS_LDM_PUSH = 29; /* Tag for pushl in LDM TLS code */ - int R_386_TLS_LDM_CALL = 30; /* Relocation for call to __tls_get_addr() in LDM code */ - int R_386_TLS_LDM_POP = 31; /* Tag for popl in LDM TLS code */ - int R_386_TLS_LDO_32 = 32; /* Offset relative to TLS block */ - int R_386_TLS_IE_32 = 33; /* GOT entry for negated static TLS block offset */ - int R_386_TLS_LE_32 = 34; /* Negated offset relative to static TLS block */ - int R_386_TLS_DTPMOD32 = 35; /* ID of module containing symbol */ - int R_386_TLS_DTPOFF32 = 36; /* Offset in TLS block */ - int R_386_TLS_TPOFF32 = 37; /* Negated offset in static TLS block */ - int R_386_SIZE32 = 38; /* 32-bit symbol size */ - int R_386_TLS_GOTDESC = 39; /* GOT offset for TLS descriptor. */ - int R_386_TLS_DESC_CALL = 40; /* Marker of call through TLS descriptor for relaxation. */ - int R_386_TLS_DESC = 41; /* - * TLS descriptor containing pointer to code and to argument, - * returning the TLS offset for the symbol. - */ - int R_386_IRELATIVE = 42; /* Adjust indirectly by program base */ - /* Keep this the last entry. */ - int R_386_NUM = 43; - } - - /** - * x86_64-specific relocation types. - */ - public interface X86_64 { - /* AMD x86-64 relocations. */ - int R_X86_64_NONE = 0; /* No reloc */ - int R_X86_64_64 = 1; /* Direct 64 bit */ - int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */ - int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */ - int R_X86_64_PLT32 = 4; /* 32 bit PLT address */ - int R_X86_64_COPY = 5; /* Copy symbol at runtime */ - int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */ - int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */ - int R_X86_64_RELATIVE = 8; /* Adjust by program base */ - int R_X86_64_GOTPCREL = 9; /* 32 bit signed PC relative offset to GOT */ - int R_X86_64_32 = 10; /* Direct 32 bit zero extended */ - int R_X86_64_32S = 11; /* Direct 32 bit sign extended */ - int R_X86_64_16 = 12; /* Direct 16 bit zero extended */ - int R_X86_64_PC16 = 13; /* 16 bit sign extended pc relative */ - int R_X86_64_8 = 14; /* Direct 8 bit sign extended */ - int R_X86_64_PC8 = 15; /* 8 bit sign extended pc relative */ - int R_X86_64_DTPMOD64 = 16; /* ID of module containing symbol */ - int R_X86_64_DTPOFF64 = 17; /* Offset in module's TLS block */ - int R_X86_64_TPOFF64 = 18; /* Offset in initial TLS block */ - int R_X86_64_TLSGD = 19; /* - * 32 bit signed PC relative offset to two GOT entries for GD - * symbol - */ - int R_X86_64_TLSLD = 20; /* - * 32 bit signed PC relative offset to two GOT entries for LD - * symbol - */ - int R_X86_64_DTPOFF32 = 21; /* Offset in TLS block */ - int R_X86_64_GOTTPOFF = 22; /* - * 32 bit signed PC relative offset to GOT entry for IE symbol - */ - int R_X86_64_TPOFF32 = 23; /* Offset in initial TLS block */ - int R_X86_64_PC64 = 24; /* PC relative 64 bit */ - int R_X86_64_GOTOFF64 = 25; /* 64 bit offset to GOT */ - int R_X86_64_GOTPC32 = 26; /* 32 bit signed pc relative offset to GOT */ - int R_X86_64_GOT64 = 27; /* 64-bit GOT entry offset */ - int R_X86_64_GOTPCREL64 = 28; /* 64-bit PC relative offset to GOT entry */ - int R_X86_64_GOTPC64 = 29; /* 64-bit PC relative offset to GOT */ - int R_X86_64_GOTPLT64 = 30; /* like GOT64, says PLT entry needed */ - int R_X86_64_PLTOFF64 = 31; /* 64-bit GOT relative offset to PLT entry */ - int R_X86_64_SIZE32 = 32; /* Size of symbol plus 32-bit addend */ - int R_X86_64_SIZE64 = 33; /* Size of symbol plus 64-bit addend */ - int R_X86_64_GOTPC32_TLSDESC = 34; /* GOT offset for TLS descriptor. */ - int R_X86_64_TLSDESC_CALL = 35; /* - * Marker for call through TLS descriptor. - */ - int R_X86_64_TLSDESC = 36; /* TLS descriptor. */ - int R_X86_64_IRELATIVE = 37; /* Adjust indirectly by program base */ - int R_X86_64_RELATIVE64 = 38; /* 64-bit adjust by program base */ - - int R_X86_64_NUM = 39; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java deleted file mode 100644 index 8248d6fba29..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import java.nio.ByteOrder; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; - -/** - * Class that abstracts ELF target details. - * - */ -public class JNIELFTargetInfo { - /** - * ELF Class of the target. - */ - private static final int elfClass; - /** - * Target architecture. - */ - private static final int arch; - /** - * Architecture endian-ness. - */ - private static final int endian; - - /** - * Target OS string. - */ - private static final String osName; - - static { - // Find the target arch details - String archStr = System.getProperty("os.arch").toLowerCase(); - String datamodelStr = System.getProperty("sun.arch.data.model"); - - if (datamodelStr.equals("32")) { - elfClass = ELF.ELFCLASS32; - } else if (datamodelStr.equals("64")) { - elfClass = ELF.ELFCLASS64; - } else { - System.out.println("Failed to discover ELF class!"); - elfClass = ELF.ELFCLASSNONE; - } - - ByteOrder bo = ByteOrder.nativeOrder(); - if (bo == ByteOrder.LITTLE_ENDIAN) { - endian = ELF.ELFDATA2LSB; - } else if (bo == ByteOrder.BIG_ENDIAN) { - endian = ELF.ELFDATA2MSB; - } else { - System.out.println("Failed to discover endian-ness!"); - endian = ELF.ELFDATANONE; - } - - if (archStr.equals("x86")) { - arch = ELF.EM_386; - } else if (archStr.equals("amd64") || archStr.equals("x86_64")) { - arch = ELF.EM_X64_64; - } else if (archStr.equals("sparcv9")) { - arch = ELF.EM_SPARCV9; - } else { - System.out.println("Unsupported architecture " + archStr); - arch = ELF.EM_NONE; - } - - osName = System.getProperty("os.name").toLowerCase(); - } - - public static int getELFArch() { - return arch; - } - - public static int getELFClass() { - return elfClass; - } - - public static int getELFEndian() { - return endian; - } - - public static String getOsName() { - return osName; - } - - public static int createReloca() { - switch (arch) { - case ELF.EM_X64_64: - return 1; - default: - return 0; - } - } - - public static int sizeOfSymtabEntry() { - return JNILibELFAPI.size_of_Sym(elfClass); - } - - public static int sizeOfRelocEntry() { - if (createReloca() == 1) { - return JNILibELFAPI.size_of_Rela(elfClass); - } else { - return JNILibELFAPI.size_of_Rel(elfClass); - } - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java deleted file mode 100644 index 5dc277b16ed..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -public class JNILibELFAPI { - - static { - System.loadLibrary("jelfshim"); - } - - /** - * Definitions for file open. - */ - public static enum OpenFlags { - O_RDONLY(0x0), - O_WRONLY(0x1), - O_RDWR(0x2), - O_CREAT(0x40); - - private final int intVal; - - private OpenFlags(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /** - * Definitions reflecting those in elf.h. - * - */ - public interface ELF { - int EI_NIDENT = 16; - - int EI_CLASS = 4; /* File class byte index */ - int ELFCLASSNONE = 0; /* Invalid class */ - int ELFCLASS32 = 1; /* 32-bit objects */ - int ELFCLASS64 = 2; /* 64-bit objects */ - int ELFCLASSNUM = 3; - - int EI_DATA = 5; /* Data encoding byte index */ - int ELFDATANONE = 0; /* Invalid data encoding */ - int ELFDATA2LSB = 1; /* 2's complement, little endian */ - int ELFDATA2MSB = 2; /* 2's complement, big endian */ - int ELFDATANUM = 3; - - // Legal architecture values for e_machine (add others as needed) - int EM_NONE = 0; /* No machine */ - int EM_SPARC = 2; /* SUN SPARC */ - int EM_386 = 3; /* Intel 80386 */ - int EM_SPARCV9 = 43; /* SPARC v9 64-bit */ - int EM_X64_64 = 62; /* AMD x86-64 architecture */ - - /* Legal values for e_type (object file type). */ - - int ET_NONE = 0; /* No file type */ - int ET_REL = 1; /* Relocatable file */ - int ET_EXEC = 2; /* Executable file */ - int ET_DYN = 3; /* Shared object file */ - int ET_CORE = 4; /* Core file */ - int ET_NUM = 5; /* Number of defined types */ - int ET_LOOS = 0xfe00; /* OS-specific range start */ - int ET_HIOS = 0xfeff; /* OS-specific range end */ - int ET_LOPROC = 0xff00; /* Processor-specific range start */ - int ET_HIPROC = 0xffff; /* Processor-specific range end */ - - /* Legal values for e_version (version). */ - - int EV_NONE = 0; /* Invalid ELF version */ - int EV_CURRENT = 1; /* Current version */ - int EV_NUM = 2; - - /* Legal values for p_type (segment type). */ - - int PT_NULL = 0; /* Program header table entry unused */ - int PT_LOAD = 1; /* Loadable program segment */ - int PT_DYNAMIC = 2; /* Dynamic linking information */ - int PT_INTERP = 3; /* Program interpreter */ - int PT_NOTE = 4; /* Auxiliary information */ - int PT_SHLIB = 5; /* Reserved */ - int PT_PHDR = 6; /* Entry for header table itself */ - int PT_TLS = 7; /* Thread-local storage segment */ - int PT_NUM = 8; /* Number of defined types */ - int PT_LOOS = 0x60000000; /* Start of OS-specific */ - int PT_GNU_EH_FRAME = 0x6474e550; /* GCC .eh_frame_hdr segment */ - int PT_GNU_STACK = 0x6474e551; /* Indicates stack executability */ - int PT_GNU_RELRO = 0x6474e552; /* Read-only after relocation */ - int PT_LOSUNW = 0x6ffffffa; - int PT_SUNWBSS = 0x6ffffffa; /* Sun Specific segment */ - int PT_SUNWSTACK = 0x6ffffffb; /* Stack segment */ - int PT_HISUNW = 0x6fffffff; - int PT_HIOS = 0x6fffffff; /* End of OS-specific */ - int PT_LOPROC = 0x70000000; /* Start of processor-specific */ - int PT_HIPROC = 0x7fffffff; /* End of processor-specific */ - - /* Special section indices. */ - - int SHN_UNDEF = 0; /* Undefined section */ - int SHN_LORESERVE = 0xff00; /* Start of reserved indices */ - int SHN_LOPROC = 0xff00; /* Start of processor-specific */ - int SHN_BEFORE = 0xff00; /* Order section before all others (Solaris). */ - int SHN_AFTER = 0xff01; /* Order section after all others (Solaris). */ - int SHN_HIPROC = 0xff1f; /* End of processor-specific */ - int SHN_LOOS = 0xff20; /* Start of OS-specific */ - int SHN_HIOS = 0xff3f; /* End of OS-specific */ - int SHN_ABS = 0xfff1; /* Associated symbol is absolute */ - int SHN_COMMON = 0xfff2; /* Associated symbol is common */ - int SHN_XINDEX = 0xffff; /* Index is in extra table. */ - int SHN_HIRESERVE = 0xffff; /* End of reserved indices */ - - /* Legal values for sh_type (section type). */ - - int SHT_NULL = 0; /* Section header table entry unused */ - int SHT_PROGBITS = 1; /* Program data */ - int SHT_SYMTAB = 2; /* Symbol table */ - int SHT_STRTAB = 3; /* String table */ - int SHT_RELA = 4; /* Relocation entries with addends */ - int SHT_HASH = 5; /* Symbol hash table */ - int SHT_DYNAMIC = 6; /* Dynamic linking information */ - int SHT_NOTE = 7; /* Notes */ - int SHT_NOBITS = 8; /* Program space with no data (bss) */ - int SHT_REL = 9; /* Relocation entries, no addends */ - int SHT_SHLIB = 10; /* Reserved */ - int SHT_DYNSYM = 11; /* Dynamic linker symbol table */ - int SHT_INIT_ARRAY = 14; /* Array of constructors */ - int SHT_FINI_ARRAY = 15; /* Array of destructors */ - int SHT_PREINIT_ARRAY = 16; /* Array of pre-constructors */ - int SHT_GROUP = 17; /* Section group */ - int SHT_SYMTAB_SHNDX = 18; /* Extended section indeces */ - int SHT_NUM = 19; /* Number of defined types. */ - int SHT_LOOS = 0x60000000; /* Start OS-specific. */ - int SHT_GNU_ATTRIBUTES = 0x6ffffff5; /* Object attributes. */ - int SHT_GNU_HASH = 0x6ffffff6; /* GNU-style hash table. */ - int SHT_GNU_LIBLIST = 0x6ffffff7; /* Prelink library list */ - int SHT_CHECKSUM = 0x6ffffff8; /* Checksum for DSO content. */ - int SHT_LOSUNW = 0x6ffffffa; /* Sun-specific low bound. */ - int SHT_SUNW_move = 0x6ffffffa; - int SHT_SUNW_COMDAT = 0x6ffffffb; - int SHT_SUNW_syminfo = 0x6ffffffc; - int SHT_GNU_verdef = 0x6ffffffd; /* Version definition section. */ - int SHT_GNU_verneed = 0x6ffffffe; /* Version needs section. */ - int SHT_GNU_versym = 0x6fffffff; /* Version symbol table. */ - int SHT_HISUNW = 0x6fffffff; /* Sun-specific high bound. */ - int SHT_HIOS = 0x6fffffff; /* End OS-specific type */ - int SHT_LOPROC = 0x70000000; /* Start of processor-specific */ - int SHT_HIPROC = 0x7fffffff; /* End of processor-specific */ - int SHT_LOUSER = 0x80000000; /* Start of application-specific */ - int SHT_HIUSER = 0x8fffffff; /* End of application-specific */ - - /* Legal values for sh_flags (section flags). */ - - int SHF_WRITE = (1 << 0); /* Writable */ - int SHF_ALLOC = (1 << 1); /* Occupies memory during execution */ - int SHF_EXECINSTR = (1 << 2); /* Executable */ - int SHF_MERGE = (1 << 4); /* Might be merged */ - int SHF_STRINGS = (1 << 5); /* Contains nul-terminated strings */ - int SHF_INFO_LINK = (1 << 6); /* `sh_info' contains SHT index */ - int SHF_LINK_ORDER = (1 << 7); /* Preserve order after combining */ - int SHF_OS_NONCONFORMING = (1 << 8); /* Non-standard OS specific handling required */ - int SHF_GROUP = (1 << 9); /* Section is member of a group. */ - int SHF_TLS = (1 << 10); /* Section hold thread-local data. */ - int SHF_MASKOS = 0x0ff00000; /* OS-specific. */ - int SHF_MASKPROC = 0xf0000000; /* Processor-specific */ - int SHF_ORDERED = (1 << 30); /* Special ordering requirement (Solaris). */ - int SHF_EXCLUDE = (1 << 31); /* - * Section is excluded unless referenced or allocated - * (Solaris). - */ - - /* Legal values for ST_BIND subfield of st_info (symbol binding). */ - - int STB_LOCAL = 0; /* Local symbol */ - int STB_GLOBAL = 1; /* Global symbol */ - int STB_WEAK = 2; /* Weak symbol */ - int STB_NUM = 3; /* Number of defined types. */ - int STB_LOOS = 10; /* Start of OS-specific */ - int STB_GNU_UNIQUE = 10; /* Unique symbol. */ - int STB_HIOS = 12; /* End of OS-specific */ - int STB_LOPROC = 13; /* Start of processor-specific */ - int STB_HIPROC = 15; /* End of processor-specific */ - - /* Legal values for ST_TYPE subfield of st_info (symbol type). */ - - int STT_NOTYPE = 0; /* Symbol type is unspecified */ - int STT_OBJECT = 1; /* Symbol is a data object */ - int STT_FUNC = 2; /* Symbol is a code object */ - int STT_SECTION = 3; /* Symbol associated with a section */ - int STT_FILE = 4; /* Symbol's name is file name */ - int STT_COMMON = 5; /* Symbol is a common data object */ - int STT_TLS = 6; /* Symbol is thread-local data object */ - int STT_NUM = 7; /* Number of defined types. */ - int STT_LOOS = 10; /* Start of OS-specific */ - int STT_GNU_IFUNC = 10; /* Symbol is indirect code object */ - int STT_HIOS = 12; /* End of OS-specific */ - int STT_LOPROC = 13; /* Start of processor-specific */ - int STT_HIPROC = 15; /* End of processor-specific */ - } - - /** - * Definitions reflecting those in libelf.h. - * - */ - public interface LibELF { - - public static enum Elf_Cmd { - ELF_C_NULL("NULL"), /* Nothing, terminate, or compute only. */ - ELF_C_READ("READ"), /* Read .. */ - ELF_C_RDWR("RDWR"), /* Read and write .. */ - ELF_C_WRITE("WRITE"), /* Write .. */ - ELF_C_CLR("CLR"), /* Clear flag. */ - ELF_C_SET("SET"), /* Set flag. */ - ELF_C_FDDONE("FDDONE"), /* - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDREAD("FDREAD"), /* - * Read rest of data so that file descriptor is not used - * anymore. - */ - /* The following are Linux-only extensions. */ - ELF_C_READ_MMAP("READ_MMAP"), /* Read, but mmap the file if possible. */ - ELF_C_RDWR_MMAP("RDWR_MMAP"), /* Read and write, with mmap. */ - ELF_C_WRITE_MMAP("WRITE_MMAP"), /* Write, with mmap. */ - ELF_C_READ_MMAP_PRIVATE("READ_MMAP_PRIVATE"), /* - * Read, but memory is writable, results - * are not written to the file. - */ - ELF_C_EMPTY("EMPTY"), /* Copy basic file data but not the content. */ - /* The following are SunOS-only enums */ - ELF_C_WRIMAGE("WRIMAGE"), - ELF_C_IMAGE("IMAGE"), - /* Common last entry. */ - ELF_C_NUM("NUM"); - private final int intVal; - private final String name; - - private Elf_Cmd(String cmd) { - name = "ELF_C_" + cmd; - switch (cmd) { - case "NULL": - // ELF_C_NULL has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NULL.ordinal(); - break; - - case "READ": - // ELF_C_READ has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ.ordinal(); - break; - - // Enums defined in libelf.h of both Linux and SunOS - // but with different ordinals - case "RDWR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "CLR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_CLR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_CLR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "SET": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_SET.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_SET.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDDONE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDREAD": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "NUM": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NUM.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_NUM.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - // Linux-only Elf_Cmd enums - case "READ_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "RDWR_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "READ_MMAP_PRIVATE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP_PRIVATE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "EMPTY": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_EMPTY.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - // SunOS-only Elf_Cmd enums - case "WRIMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRIMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - case "IMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_IMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - default: - intVal = -1; - } - } - - public int intValue() { - assert intVal != -1 : "enum " + name + "not supported on " + JNIELFTargetInfo.getOsName(); - return intVal; - } - - public String getName() { - return name; - } - } - - public static enum Elf_Type { - ELF_T_BYTE(0), /* unsigned char */ - ELF_T_ADDR(1), /* Elf32_Addr, Elf64_Addr, ... */ - ELF_T_DYN(2), /* Dynamic section record. */ - ELF_T_EHDR(3), /* ELF header. */ - ELF_T_HALF(4), /* Elf32_Half, Elf64_Half, ... */ - ELF_T_OFF(5), /* Elf32_Off, Elf64_Off, ... */ - ELF_T_PHDR(6), /* Program header. */ - ELF_T_RELA(7), /* Relocation entry with addend. */ - ELF_T_REL(8), /* Relocation entry. */ - ELF_T_SHDR(9), /* Section header. */ - ELF_T_SWORD(10), /* Elf32_Sword, Elf64_Sword, ... */ - ELF_T_SYM(11), /* Symbol record. */ - ELF_T_WORD(12), /* Elf32_Word, Elf64_Word, ... */ - ELF_T_XWORD(13), /* Elf32_Xword, Elf64_Xword, ... */ - ELF_T_SXWORD(14), /* Elf32_Sxword, Elf64_Sxword, ... */ - ELF_T_VDEF(15), /* Elf32_Verdef, Elf64_Verdef, ... */ - ELF_T_VDAUX(16), /* Elf32_Verdaux, Elf64_Verdaux, ... */ - ELF_T_VNEED(17), /* Elf32_Verneed, Elf64_Verneed, ... */ - ELF_T_VNAUX(18), /* Elf32_Vernaux, Elf64_Vernaux, ... */ - ELF_T_NHDR(19), /* Elf32_Nhdr, Elf64_Nhdr, ... */ - ELF_T_SYMINFO(20), /* Elf32_Syminfo, Elf64_Syminfo, ... */ - ELF_T_MOVE(21), /* Elf32_Move, Elf64_Move, ... */ - ELF_T_LIB(22), /* Elf32_Lib, Elf64_Lib, ... */ - ELF_T_GNUHASH(23), /* GNU-style hash section. */ - ELF_T_AUXV(24), /* Elf32_auxv_t, Elf64_auxv_t, ... */ - /* Keep this the last entry. */ - ELF_T_NUM(25); - - private final int intVal; - - private Elf_Type(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /* Flags for the ELF structures. */ - int ELF_F_DIRTY = 0x1; - int ELF_F_LAYOUT = 0x4; - int ELF_F_PERMISSIVE = 0x8; - - public static enum Elf_Kind { - ELF_K_NONE(0), /* Unknown. */ - ELF_K_AR(1), /* Archive. */ - ELF_K_COFF(2), /* Stupid old COFF. */ - ELF_K_ELF(3), /* ELF file. */ - /* Keep this the last entry. */ - ELF_K_NUM(4); - private final int intVal; - - private Elf_Kind(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - } - - /** - * Invoke native libelf function unsigned int elf_version (unsigned int v). - * - * @param v version - * @return return value of native call - */ - // Checkstyle: stop method name check - static native int elf_version(int v); - - /** - * Return version recorded in libelfshim. - * - * @return return version string - */ - // Checkstyle: stop method name check - static native String elfshim_version(); - - /** - * Invoke native libelf function Elf *elf_begin (int fildes, Elf_Cmd cmd, Elf *elfPtr). - * - * @param fildes open file descriptor - * @param elfCRead command - * @param elfHdrPtr pointer to ELF header - * @return return value of native call - */ - static native Pointer elf_begin(int fildes, int elfCRead, Pointer elfHdrPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_end(Pointer elfPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_kind(Pointer elfPtr); - - /** - * Invoke native libelf function unsigned int elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int - * flags). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @param flags flags - * @return return value of native call - */ - static native int elf_flagphdr(Pointer elfPtr, int cmd, int flags); - - /** - * Invoke native libelf function Elf_Scn *elf_newscn (Elf *elfPtr). - * - * @param elfPtr Elf header pointer - * @return return value of native call - */ - static native Pointer elf_newscn(Pointer elfPtr); - - /** - * Invoke native libelf function Elf_Data *elf_newdata (Elf_Scn *scn). - * - * @param scnPtr pointer to section for which the new data descriptor is to be created - * @return return value of native call - */ - static native Pointer elf_newdata(Pointer scnPtr); - - /** - * Invoke native libelf function Elf64_Shdr *elf64_getshdr (Elf_Scn *scnPtr). - * - * @param scnPtr pointer to section whose header information is to be retrieved - * @return return value of native call - */ - static native Pointer elf64_getshdr(Pointer scnPtr); - - /** - * Invoke native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @return return value of native call - */ - static native long elf_update(Pointer elfPtr, int cmd); - - /** - * Invoke native libelf function char *elf_errmsg (int error). - * - * @param error error - * @return return value of native call - */ - static native String elf_errmsg(int error); - - /** - * Invoke native libelf function size_t elf_ndxscn (Elf_Scn *scn). - * - * @param scn section pointer - * @return return value of native call - */ - static native int elf_ndxscn(Pointer scn); - - /** - * GELF interfaces - */ - /** - * Invoke native libelf function unsigned long int gelf_newehdr (Elf *elf, int elfClass). - * - * @param elf ELF Header pointer - * @param elfclass ELF class - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newehdr(Pointer elf, int elfclass); - - /** - * Invoke native libelf function unsigned long int gelf_newphdr (Elf *elf, size_t phnum). - * - * @param elf ELF header pointer - * @param phnum number of program headers - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newphdr(Pointer elf, int phnum); - - /** - * Miscellaneous convenience native methods that help peek and poke ELF data structures. - */ - static native int size_of_Sym(int elfClass); - - static native int size_of_Rela(int elfClass); - - static native int size_of_Rel(int elfClass); - - static native void ehdr_set_data_encoding(Pointer ehdr, int val); - - static native void set_Ehdr_e_machine(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_type(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_version(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_shstrndx(int elfclass, Pointer structPtr, int val); - - static native void phdr_set_type_self(int elfclass, Pointer ehdr, Pointer phdr); - - static native void set_Shdr_sh_name(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_type(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_flags(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_entsize(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_link(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_info(int elfclass, Pointer structPtr, int val); - - static native void set_Data_d_align(Pointer structPtr, int val); - - static native void set_Data_d_off(Pointer structPtr, int val); - - static native void set_Data_d_buf(Pointer structPtr, Pointer val); - - static native void set_Data_d_type(Pointer structPtr, int val); - - static native void set_Data_d_size(Pointer structPtr, int val); - - static native void set_Data_d_version(Pointer structPtr, int val); - - static native long create_sym_entry(int elfclass, int index, int type, int bind, int shndx, int size, int value); - - static native long create_reloc_entry(int elfclass, int roffset, int symtabIdx, int relocType, int raddend, int reloca); - - /** - * File Operations. - */ - static native int open_rw(String fileName); - - static native int open(String fileName, int flags); - - static native int open(String fileName, int flags, int mode); - - static native int close(int fd); - // Checkstyle: resume method name check -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java deleted file mode 100644 index a569584a8ce..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import jdk.internal.misc.Unsafe; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -public class Pointer { - - private final long address; - - public Pointer(long val) { - address = val; - } - - /** - * Put (i.e., copy) content of byte array at consecutive addresses beginning at this Pointer. - * - * @param src source byte array - */ - public void put(byte[] src) { - UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length); - } - - /** - * Get (i.e., copy) content at this Pointer to the given byte array. - * - * @param dst destination byte array - */ - public void get(byte[] dst) { - UNSAFE.copyMemory(null, address, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET, dst.length); - } - - /** - * Read {@code readSize} number of bytes to copy them starting at {@code startIndex} of - * {@code byteArray} - * - * @param byteArray target array to copy bytes - * @param readSize number of bytes to copy - * @param startIndex index of the array to start copy at - */ - public void copyBytesTo(byte[] byteArray, int readSize, int startIndex) { - long end = (long)startIndex + (long)readSize; - if (end > byteArray.length) { - throw new IllegalArgumentException("writing beyond array bounds"); - } - UNSAFE.copyMemory(null, address, byteArray, Unsafe.ARRAY_BYTE_BASE_OFFSET+startIndex, readSize); - } - -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java deleted file mode 100644 index a32d202486c..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf.linux; - -/** - * Represent Elf_Cmd enums defined in libelf.h on Linux as they slightly different from libelf.h on - * SunOS. - */ -public enum Elf_Cmd { - /** Nothing, terminate, or compute only. */ - ELF_C_NULL, - - /** Read. */ - ELF_C_READ, - - /** Read and write. */ - ELF_C_RDWR, - - /** Write. */ - ELF_C_WRITE, - - /** Clear flag. */ - ELF_C_CLR, - - /** Set flag. */ - ELF_C_SET, - - /** - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDDONE, - - /** - * Read rest of data so that file descriptor is not used anymore. - */ - ELF_C_FDREAD, - - /* The following are extensions. */ - - /** Read, but mmap the file if possible. */ - ELF_C_READ_MMAP, - - /** Read and write, with mmap. */ - ELF_C_RDWR_MMAP, - - /** Write, with mmap. */ - ELF_C_WRITE_MMAP, - - /** - * Read, but memory is writable, results are not written to the file. - */ - ELF_C_READ_MMAP_PRIVATE, - - /** Copy basic file data but not the content. */ - ELF_C_EMPTY, - - /** Keep this the last entry. */ - ELF_C_NUM; -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index a1257b7a013..fb23bdb96ba 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -134,9 +134,6 @@ public class Main implements LogPrinter { @Override void process(Main task, String opt, String arg) { String name = arg; - if (name.endsWith(".so")) { - name = name.substring(0, name.length() - ".so".length()); - } task.options.outputName = name; } }, new Option(" --compile-commands Name of file with compile commands", true, "--compile-commands") { @@ -216,7 +213,7 @@ public class Main implements LogPrinter { public List files = new LinkedList<>(); public String module = null; public String modulepath = "modules"; - public String outputName = "unnamed"; + public String outputName = "unnamed.so"; public String methodList; public String classpath = "."; @@ -317,6 +314,21 @@ public class Main implements LogPrinter { } } + /** + * Search for Visual Studio link.exe + * Search Order is: VS2013, VS2015, VS2012 + */ + private String getWindowsLinkPath() { + String vs2013 = "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"; + String vs2015 = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"; + String vs2012 = "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe"; + + if (new File(vs2015).exists()) return vs2015; + if (new File(vs2013).exists()) return vs2013; + if (new File(vs2012).exists()) return vs2012; + return null; + } + @SuppressWarnings("try") private void run() throws Exception { openLog(); @@ -399,8 +411,57 @@ public class Main implements LogPrinter { System.gc(); } - String objectFileName = options.outputName + ".o"; - String libraryFileName = options.outputName + ".so"; + String name = options.outputName; + String objectFileName = name; + + // [TODO] The jtregs tests expect .so extension so don't + // override with platform specific file extension until the + // tests are fixed. + String libraryFileName = name; + + String ldCmd; + String osName = System.getProperty("os.name"); + + if (name.endsWith(".so")) { + objectFileName = name.substring(0, name.length() - ".so".length()); + } + else if (name.endsWith(".dylib")) { + objectFileName = name.substring(0, name.length() - ".dylib".length()); + } + else if (name.endsWith(".dll")) { + objectFileName = name.substring(0, name.length() - ".dll".length()); + } + + switch (osName) { + case "Linux": + // libraryFileName = options.outputName + ".so"; + objectFileName = objectFileName + ".o"; + ldCmd = "ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; + break; + case "SunOS": + // libraryFileName = options.outputName + ".so"; + objectFileName = objectFileName + ".o"; + ldCmd = "ld -shared -o " + libraryFileName + " " + objectFileName; + break; + case "Mac OS X": + // libraryFileName = options.outputName + ".dylib"; + objectFileName = objectFileName + ".o"; + ldCmd = "ld -dylib -o " + libraryFileName + " " + objectFileName; + break; + default: + if (osName.startsWith("Windows")) { + // libraryFileName = options.outputName + ".dll"; + objectFileName = objectFileName + ".obj"; + String linkpath = getWindowsLinkPath(); + if (linkpath == null) { + throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe"); + } + ldCmd = linkpath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; + break; + } + else + throw new InternalError("Unsupported platform: " + osName); + } try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) { binaryContainer.createBinary(objectFileName, JVM_VERSION); @@ -414,7 +475,7 @@ public class Main implements LogPrinter { } try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) { - Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName); + Process p = Runtime.getRuntime().exec(ldCmd); final int exitCode = p.waitFor(); if (exitCode != 0) { InputStream stderr = p.getErrorStream(); @@ -432,7 +493,7 @@ public class Main implements LogPrinter { } // Make non-executable for all. File libFile = new File(libraryFileName); - if (libFile.exists()) { + if (libFile.exists() && !osName.startsWith("Windows")) { if (!libFile.setExecutable(false, false)) { throw new InternalError("Failed to change attribute for " + libraryFileName + " file"); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java index c46b3bfd062..1a88dc69f95 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -206,8 +206,10 @@ public class ClassCollector { } private URI makeJarFileURI(String fileName) { + String name = Paths.get(fileName).toAbsolutePath().toString(); + name = name.replace('\\', '/'); try { - return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/"); + return new URI("jar:file:///" + name + "!/"); } catch (URISyntaxException e) { throw new InternalError(e); } @@ -252,7 +254,9 @@ public class ClassCollector { } private URL[] buildUrls(String fileName) throws MalformedURLException { - return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") }; + String name = Paths.get(fileName).toAbsolutePath().toString(); + name = name.replace('\\', '/'); + return new URL[]{ new URL("jar:file:///" + name + "!/") }; } private URL[] buildUrls(File file) throws MalformedURLException { @@ -274,6 +278,7 @@ public class ClassCollector { } String className = fileName.substring(start, fileName.length() - ".class".length()); className = className.replace('/', '.'); + className = className.replace('\\', '.'); try { return loader.loadClass(className); } catch (Throwable e) { diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c deleted file mode 100644 index d6d69cb439a..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jdk_tools_jaotc_jnilibelf_JNILibELFAPI.h" - -// For file open and close -#include -#include -#include -#include -#include -#include - -#include - -// For libelf interfaces -#include -#include - -// Convenience macro to shut the compiler warnings -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - -/** - * libelfshim version - */ -#ifndef AOT_VERSION_STRING - #error AOT_VERSION_STRING must be defined -#endif - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elfshim_1version -(JNIEnv* env, jclass UNUSED(c)) { - const char* ver = AOT_VERSION_STRING; - return (*env)->NewStringUTF(env, ver); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1version -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint v) { - return elf_version(v); -} - -/** - * Unbox the Pointer object the encapsulated native address. - */ - -static jlong getNativeAddress(JNIEnv* env, jobject ptrObj) { - jclass ptrClass; - jfieldID fidNumber; - jlong nativeAddress = -1; - assert (ptrObj != NULL); - // Get a reference to ptr object's class - ptrClass = (*env)->GetObjectClass(env, ptrObj); - - // Get the Field ID of the instance variables "address" - fidNumber = (*env)->GetFieldID(env, ptrClass, "address", "J"); - if (fidNumber != NULL) { - // Get the long given the Field ID - nativeAddress = (*env)->GetLongField(env, ptrObj, fidNumber); - } - // fprintf(stderr, "Native address : %lx\n", nativeAddress); - return nativeAddress; -} - -/** - * Box the nativeAddress as a Pointer object. - */ -static jobject makePointerObject(JNIEnv* env, jlong nativeAddr) { - jclass ptrClass = (*env)->FindClass(env, "jdk/tools/jaotc/jnilibelf/Pointer"); - // Call back constructor to allocate a Pointer object, with an int argument - jmethodID constructorId = (*env)->GetMethodID(env, ptrClass, "", "(J)V"); - jobject retObj = (*env)->NewObject(env, ptrClass, constructorId, nativeAddr); - return retObj; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1begin -(JNIEnv* env, jclass UNUSED(class), jint filedes, jint cmd, jobject ptrObj) { - - Elf* elfPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfPtr = elf_begin(filedes, cmd, (Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_begin()\n"); - } - - return makePointerObject(env, (jlong) elfPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1end -(JNIEnv* env, jclass UNUSED(class), jobject ptrObj) { - - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_end((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_end()\n"); - return -1; - } -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1kind -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_kind((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_kind()\n"); - return -1; - } -} -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1flagphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd, jint flags) { - - jlong addr = getNativeAddress(env, ptrObj); - unsigned int retVal = 0; - - if (addr != -1) { - // Call libelf function - if ((retVal = elf_flagphdr((Elf *) addr, cmd, flags)) == 0) { - errx(EX_SOFTWARE, "elf_flagphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_flagphdr()\n"); - } - return retVal; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Scn* elfSecPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfSecPtr = elf_newscn((Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newscn()\n"); - } - - return makePointerObject(env, (jlong) elfSecPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newdata -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Data* elfDataPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfDataPtr = elf_newdata((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newdata()\n"); - } - return makePointerObject(env, (jlong) elfDataPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf64_1getshdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf64_Shdr* elf64ShdrPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elf64ShdrPtr = elf64_getshdr((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf64_getshdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_getshdr()\n"); - } - return makePointerObject(env, (jlong) elf64ShdrPtr); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1update -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd) { - - off_t size = -1; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((size = elf_update((Elf*) addr, cmd)) == -1) { - errx(EX_SOFTWARE, "elf_update() failed: %s size (%d) cmd (%d).", elf_errmsg(-1), (int)size, cmd); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_update()\n"); - } - return size; -} - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1errmsg -(JNIEnv* env, jclass UNUSED(c), jint errno) { - - const char * retPtr = NULL; - // Call libelf function - if ((retPtr = elf_errmsg(errno)) == NULL) { - errx(EX_SOFTWARE, "elf_errmsg() failed: %s.", elf_errmsg(-1)); - } - return (*env)->NewStringUTF(env, retPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1ndxscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jint secnum = SHN_UNDEF; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - secnum = elf_ndxscn((Elf_Scn*) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_ndxscn()\n"); - } - return secnum; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newehdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint elfClass) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newehdr((Elf*) addr, elfClass)) == 0) { - errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newehdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint phnum) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newphdr((Elf*) addr, phnum)) == 0) { - errx(EX_SOFTWARE, "gelf_newphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newphdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - - -/* File operations */ - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open_1rw -(JNIEnv * env, jclass UNUSED(class), jstring jfileName) { - int flags = O_RDWR | O_CREAT | O_TRUNC; - int mode = 0666; - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2I -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2II -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags, jint mode) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_close -(JNIEnv* UNUSED(env), jclass UNUSED(class), jint fd) { - return close(fd); -} - -/** - * Miscellaneous ELF data structure peek-poke functions in - * shim_functions.c. No corresponding .h file exists yet. - * So each function needs to be declared as extern - */ - -extern int size_of_Sym(int elfclass); -extern int size_of_Rel(int elfclass); -extern int size_of_Rela(int elfclass); - -extern void ehdr_set_data_encoding(void * ehdr, int val); -extern void set_Ehdr_e_machine(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_type(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_version(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_shstrndx(int elfclass, void * structPtr, int val); - -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); - -extern void set_Shdr_sh_name(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_type(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_flags(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_entsize(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_link(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_info(int elfclass, void* structPtr, int val); - -extern void set_Data_d_align(void* structPtr, int val); -extern void set_Data_d_off(void* structPtr, int val); -extern void set_Data_d_buf(void* structPtr, void* val); -extern void set_Data_d_type(void* structPtr, int val); -extern void set_Data_d_size(void* structPtr, int val); -extern void set_Data_d_version(void* structPtr, int val); - -extern void* create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value); -extern void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca); - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Sym -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Sym(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rela -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rela(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rel -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rel(elfClass); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_ehdr_1set_1data_1encoding -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - ehdr_set_data_encoding(ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1machine -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_machine(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_type(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1version -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_version(elfClass, ehdr, val); -} -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1shstrndx -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_shstrndx(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_phdr_1set_1type_1self -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ehdrPtr, jobject phdrPtr) { - void* ehdr = (void*) getNativeAddress(env, ehdrPtr); - void* phdr = (void*) getNativeAddress(env, phdrPtr); - phdr_set_type_self(elfClass, ehdr, phdr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1name -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_name(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_type(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1flags -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_flags(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1entsize -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_entsize(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1info -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_info(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1link -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_link(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1align -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_align(dptr, val); -} - - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1off -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_off(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1buf -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jobject bufPtr) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - void* bptr = (void*) getNativeAddress(env, bufPtr); - set_Data_d_buf(dptr, bptr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1type -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_type(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1size -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_size(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1version -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_version(dptr, val); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1sym_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint index, jint type, - jint bind, jint shndx, jint size, jint value) { - void * retVal = create_sym_entry(elfClass, index, type, bind, - shndx, size, value); - return (jlong)retVal; -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1reloc_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint roffset, - jint symTabIdx, jint relocType, jint raddend, jint reloca) { - void * retVal = create_reloc_entry(elfClass, roffset, symTabIdx, - relocType, raddend, reloca); - return (jlong)retVal; -} - diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c deleted file mode 100644 index e405b0d26c0..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include - -/** - * TODO: This is an intial and crude attempt to access structure - * fields of some ELF structrures. Need to figure out a way to access the - * given field of a given structure instead of writing one shim function - * per access of each of the structure field. - **/ - -#define STRINGIFYHELPER(x) #x -#define STRINGIFY(x) STRINGIFYHELPER(x) -#define FUNC_NAME(S, F) set_ ## S ## _ ## F -#define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr) -#define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr) -#define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr) -#define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F -#define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F -#define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F - -/* - Example: - SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(int elfclass, void * strPtr, int val) { -} -*/ - -#define SET_TYPE_BASED_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) { \ - if (elfclass == ELFCLASS32) { \ - ACCESS_FIELD32(S, F) = val; \ - } else if (elfclass == ELFCLASS64) { \ - ACCESS_FIELD64(S, F) = val; \ - } else { \ - printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \ - } \ - return; \ -} - -/* - Example: - SET_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(void * strPtr, int val) { -} -*/ - -#define SET_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(void * structPtr, T val) { \ - ACCESS_FIELD(S, F) = val; \ - return; \ -} - -int size_of_Sym(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Sym); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Sym); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rela(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rela); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rela); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rel(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rel); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rel); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -/* ELF Header field access */ - -void ehdr_set_data_encoding(void * ehdr, int val) { - ((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val; - return; -} - -SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) -SET_TYPE_BASED_FIELD(Ehdr, e_type, int) -SET_TYPE_BASED_FIELD(Ehdr, e_version, int) -SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int) - -/* Data descriptor field access */ -SET_FIELD(Data, d_align, int) -SET_FIELD(Data, d_off, int) -SET_FIELD(Data, d_buf, void*) -SET_FIELD(Data, d_type, int) -SET_FIELD(Data, d_size, int) -SET_FIELD(Data, d_version, int) - -/* Section Header Access functions */ -SET_TYPE_BASED_FIELD(Shdr, sh_name, int) -SET_TYPE_BASED_FIELD(Shdr, sh_type, int) -SET_TYPE_BASED_FIELD(Shdr, sh_flags, int) -SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int) -SET_TYPE_BASED_FIELD(Shdr, sh_link, int) -SET_TYPE_BASED_FIELD(Shdr, sh_info, int) - -/* Set the Program Header to be of PH_PHDR type and initialize other - related fields of the program header. -*/ -void phdr_set_type_self(int elfclass, void * ehdr, void * phdr) { - if (elfclass == ELFCLASS32) { - Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr; - Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr; - phdr32->p_type = PT_PHDR; - phdr32->p_offset = ehdr32->e_phoff; - phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else if (elfclass == ELFCLASS64) { - Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr; - Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr; - phdr64->p_type = PT_PHDR; - phdr64->p_offset = ehdr64->e_phoff; - phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else { - printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass); - } - return; -} - -/* - Create symbol table entry with given type and binding -*/ -void * create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value) { - void * symentry = NULL; - if (elfclass == ELFCLASS32) { - Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym)); - sym32->st_name = index; - sym32->st_value = value; - sym32->st_size = size; - sym32->st_info = ELF32_ST_INFO(bind, type); - sym32->st_other = 0; // TODO: Add an argument to get this value ?? - sym32->st_shndx = shndx; - symentry = sym32; - } else if (elfclass == ELFCLASS64) { - Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym)); - sym64->st_name = index; - sym64->st_value = value; - sym64->st_size = size; - sym64->st_info = ELF64_ST_INFO(bind, type); - sym64->st_other = 0; // TODO: Add an argument to get this value ?? - sym64->st_shndx = shndx; - symentry = sym64; - } else { - printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) symentry; -} - -// Create a reloc (or reloca entry if argument reloca is non-zero) -void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca) { - void * relocentry = NULL; - if (elfclass == ELFCLASS32) { - if (reloca) { - Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela)); - rela32->r_offset = roffset; - rela32->r_info = ELF32_R_INFO(symtabIdx, relocType); - rela32->r_addend = raddend; - relocentry = rela32; - } else { - Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel)); - rel32->r_offset = roffset; - rel32->r_info = ELF32_R_INFO(symtabIdx, relocType); - relocentry = rel32; - } - } else if (elfclass == ELFCLASS64) { - if (reloca) { - Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela)); - rela64->r_offset = roffset; - rela64->r_info = ELF64_R_INFO(symtabIdx, relocType); - rela64->r_addend = raddend; - relocentry = rela64; - } else { - Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel)); - rel64->r_offset = roffset; - rel64->r_info = ELF64_R_INFO(symtabIdx, relocType); - relocentry = rel64; - } - } else { - printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) relocentry; -} diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.cpp b/hotspot/src/share/vm/aot/aotCodeHeap.cpp index 08283a92fbe..97f5c960f68 100644 --- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp +++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -40,7 +40,7 @@ int AOTLib::_narrow_oop_shift = 0; int AOTLib::_narrow_klass_shift = 0; address AOTLib::load_symbol(const char *name) { - address symbol = (address) dlsym(_dl_handle, name); + address symbol = (address) os::dll_lookup(_dl_handle, name); if (symbol == NULL) { tty->print_cr("Shared file %s error: missing %s", _name, name); vm_exit(1); @@ -224,16 +224,15 @@ AOTCodeHeap::AOTCodeHeap(AOTLib* lib) : _method_count = _lib->header()->_method_count; // Collect metaspace info: names -> address in .got section - _metaspace_names = (const char*) _lib->load_symbol("JVM.metaspace.names"); - _method_metadata = (address) _lib->load_symbol("JVM.method.metadata"); + _metaspace_names = (const char*) _lib->load_symbol("JVM.meta.names"); + _method_metadata = (address) _lib->load_symbol("JVM.meth.metadata"); _methods_offsets = (address) _lib->load_symbol("JVM.methods.offsets"); - _klasses_offsets = (address) _lib->load_symbol("JVM.klasses.offsets"); - _dependencies = (address) _lib->load_symbol("JVM.klasses.dependencies"); + _klasses_offsets = (address) _lib->load_symbol("JVM.kls.offsets"); + _dependencies = (address) _lib->load_symbol("JVM.kls.dependencies"); _code_space = (address) _lib->load_symbol("JVM.text"); // First cell is number of elements. - jlong* got_sect; - _metaspace_got = (Metadata**) _lib->load_symbol("JVM.metaspace.got"); + _metaspace_got = (Metadata**) _lib->load_symbol("JVM.meta.got"); _metaspace_got_size = _lib->header()->_metaspace_got_size; _metadata_got = (Metadata**) _lib->load_symbol("JVM.metadata.got"); @@ -249,7 +248,7 @@ AOTCodeHeap::AOTCodeHeap(AOTLib* lib) : _code_segments = (address) _lib->load_symbol("JVM.code.segments"); // method state - _method_state = (jlong*) _lib->load_symbol("JVM.method.state"); + _method_state = (jlong*) _lib->load_symbol("JVM.meth.state"); // Create a table for mapping classes _classes = NEW_C_HEAP_ARRAY(AOTClass, _class_count, mtCode); @@ -338,7 +337,7 @@ void AOTCodeHeap::link_primitive_array_klasses() { BasicType t = (BasicType)i; if (is_java_primitive(t)) { const Klass* arr_klass = Universe::typeArrayKlassObj(t); - AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), arr_klass->signature_name()); + AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), arr_klass->signature_name()); if (klass_data != NULL) { // Set both GOT cells, resolved and initialized klass pointers. // _got_index points to second cell - resolved klass pointer. @@ -391,13 +390,9 @@ void AOTCodeHeap::register_stubs() { #define SET_AOT_GLOBAL_SYMBOL_VALUE(AOTSYMNAME, AOTSYMTYPE, VMSYMVAL) \ { \ - char* error; \ - /* Clear any existing error */ \ - dlerror(); \ - AOTSYMTYPE * adr = (AOTSYMTYPE *) dlsym(_lib->dl_handle(), AOTSYMNAME); \ - /* Check for any dlsym lookup error */ \ - error = dlerror(); \ - guarantee(error == NULL, "%s", error); \ + AOTSYMTYPE * adr = (AOTSYMTYPE *) os::dll_lookup(_lib->dl_handle(), AOTSYMNAME); \ + /* Check for a lookup error */ \ + guarantee(adr != NULL, "AOT Symbol not found %s", AOTSYMNAME); \ *adr = (AOTSYMTYPE) VMSYMVAL; \ } @@ -612,7 +607,7 @@ Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char* AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) { ResourceMark rm; - AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), ik->signature_name()); + AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), ik->signature_name()); return klass_data; } diff --git a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp index 1f40284da7e..2dbe3a9e05b 100644 --- a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp +++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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,7 +42,6 @@ #include "utilities/array.hpp" #include "utilities/xmlstream.hpp" -#include #include #if 0 diff --git a/hotspot/src/share/vm/aot/aotLoader.cpp b/hotspot/src/share/vm/aot/aotLoader.cpp index 0dbf9ff72e4..7e7668eed12 100644 --- a/hotspot/src/share/vm/aot/aotLoader.cpp +++ b/hotspot/src/share/vm/aot/aotLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "aot/aotLoader.inline.hpp" #include "jvmci/jvmciRuntime.hpp" #include "oops/method.hpp" +#include "runtime/os.hpp" GrowableArray* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (2, true); GrowableArray* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray (2, true); @@ -146,13 +147,13 @@ void AOTLoader::initialize() { for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) { char library[JVM_MAXPATHLEN]; - jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s.so", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1"); + jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1", os::dll_file_extension()); load_library(library, false); } // Scan the AOTLibrary option. if (AOTLibrary != NULL) { - const int len = strlen(AOTLibrary); + const int len = (int)strlen(AOTLibrary); char* cp = NEW_C_HEAP_ARRAY(char, len+1, mtCode); if (cp != NULL) { // No memory? memcpy(cp, AOTLibrary, len); @@ -234,10 +235,11 @@ void AOTLoader::set_narrow_klass_shift() { } void AOTLoader::load_library(const char* name, bool exit_on_error) { - void* handle = dlopen(name, RTLD_LAZY); + char ebuf[1024]; + void* handle = os::dll_load(name, ebuf, sizeof ebuf); if (handle == NULL) { if (exit_on_error) { - tty->print_cr("error opening file: %s", dlerror()); + tty->print_cr("error opening file: %s", ebuf); vm_exit(1); } return; @@ -246,7 +248,7 @@ void AOTLoader::load_library(const char* name, bool exit_on_error) { AOTLib* lib = new AOTLib(handle, name, dso_id); if (!lib->is_valid()) { delete lib; - dlclose(handle); + os::dll_unload(handle); return; } add_library(lib); diff --git a/hotspot/src/share/vm/aot/compiledIC_aot.cpp b/hotspot/src/share/vm/aot/compiledIC_aot.cpp index f8410303901..5961298e7be 100644 --- a/hotspot/src/share/vm/aot/compiledIC_aot.cpp +++ b/hotspot/src/share/vm/aot/compiledIC_aot.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,6 +21,8 @@ * questions. */ +#include "precompiled.hpp" + #include "aot/compiledIC_aot.hpp" bool CompiledPltStaticCall::is_call_to_interpreted() const { diff --git a/hotspot/test/compiler/aot/DeoptimizationTest.java b/hotspot/test/compiler/aot/DeoptimizationTest.java index f027500a302..d74681514fa 100644 --- a/hotspot/test/compiler/aot/DeoptimizationTest.java +++ b/hotspot/test/compiler/aot/DeoptimizationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.aot.DeoptimizationTest * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/RecompilationTest.java b/hotspot/test/compiler/aot/RecompilationTest.java index 466c8348e7e..e2dc3a1f3f7 100644 --- a/hotspot/test/compiler/aot/RecompilationTest.java +++ b/hotspot/test/compiler/aot/RecompilationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.aot.RecompilationTest * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/SharedUsageTest.java b/hotspot/test/compiler/aot/SharedUsageTest.java index 829f63d1866..ce104201675 100644 --- a/hotspot/test/compiler/aot/SharedUsageTest.java +++ b/hotspot/test/compiler/aot/SharedUsageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.SharedUsageTest * compiler.aot.AotCompiler * @run main compiler.aot.AotCompiler -libname libSharedUsageTest.so diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java index 2abd5b459a2..767687a18a3 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java index ec0966208fd..aa05ac5a560 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java index 96dfd19fd2d..80ee4fe0142 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java index c1c9a448777..099d5e3d0e3 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java index 9a739a6b280..f760bb0c04e 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java index e9bcdeff5f4..55b93dd5844 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java index ad1b0f9e13f..190a91107cc 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java index 89afb389661..a172aafe9ef 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java index 5b9ca4722bc..333b1179b62 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java index 5a338c116ad..171ad13c0e5 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java index a011eee012f..c1244da13e2 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java index 9c5207145f4..00aa7f6fac8 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java index 28928e1bead..52e41d6b151 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java index 9bdc0b90bf8..887e78e7ea7 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java index d06930f8d38..61f6d77addc 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java index a40134013db..72dd71f2da8 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java index 515d2b02986..10f2e373f0e 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java index 90709cfe4c2..0d903d79333 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java index 3a9b881fef2..5f20ebf3d0a 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java index ee163a1b238..dec95c8d6d2 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java index 133e98c5767..a2daaafe247 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java index 3cab0a8c3f4..94c2b4b5c81 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java index daa8f9c2354..49131cff31f 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java index 5dcf91dfad5..0cb0af40d53 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java index 429d60b0791..be34a4dc41d 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java index ecdf79a8e54..132327711ba 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java index 8b7db4e7886..5197f6e107d 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java index 5510136f20a..9585f7b3a4c 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java index 0c2b9db9bbf..8909b69d661 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java index 9738f48ddb2..98250be7421 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java index 4b09209e849..ac73b16982d 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java index 00b75a41cf4..486362ce03a 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java index 6ba1d2363a4..07eb8451e80 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java b/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java index 3a9f2f010a3..5f0f195e76e 100644 --- a/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.DisabledAOTWithLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libDisabledAOTWithLibraryTest.so diff --git a/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java index 89884b4b2e8..3018d8c8a10 100644 --- a/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @run driver ClassFileInstaller ClassFileInstaller * @run driver compiler.aot.cli.IncorrectAOTLibraryTest * @summary check if incorrect aot library is handled properly diff --git a/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java index 7cac002dd4a..09d507530de 100644 --- a/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.MultipleAOTLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java index bd8c021293f..7c19b781acf 100644 --- a/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @run driver compiler.aot.cli.NonExistingAOTLibraryTest * @summary check if non-existing aot library is handled properly */ @@ -38,7 +38,7 @@ public class NonExistingAOTLibraryTest { private static final String PATH = "./NonExisting.so"; private static final String OPTION = "-XX:AOTLibrary=" + PATH; private static final String[] EXPECTED_MESSAGES = new String[] { - "cannot open shared object file" + "error opening file" }; public static void main(String args[]) { diff --git a/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java index 67e2c77208d..298150eb797 100644 --- a/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib / /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.SingleAOTLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libSingleAOTLibraryTest.so diff --git a/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java b/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java index 6e33256ea71..b9af1cbfb4a 100644 --- a/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java +++ b/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.SingleAOTOptionTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libSingleAOTOptionTest.so diff --git a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java index eeee8db6cde..e3b8fa8be19 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.ClasspathOptionTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java index 1b99249abec..97faac789ff 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /testlibrary/ /test/lib * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @compile data/HelloWorldOne.java * @run driver compiler.aot.cli.jaotc.ClasspathOptionUnknownClassTest * @summary check jaotc can't compile class not from classpath diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java index a59e9e52b69..209b7802f74 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.CompileClassTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.CompileClassTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java index 7157294b9ad..8bf32795be3 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.CompileDirectoryTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * compiler.aot.cli.jaotc.data.HelloWorldTwo diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java index b94265a4038..62d7e1e94e3 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.CompileJarTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * compiler.aot.cli.jaotc.data.HelloWorldTwo diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java index 4e0ce885de4..2d51746c633 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @run driver compiler.aot.cli.jaotc.CompileModuleTest * @summary check jaotc can compile module */ diff --git a/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java b/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java index 06bca2a9292..a4375088b99 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java +++ b/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -71,6 +71,6 @@ public class JaotcTestHelper { } public static String getClassAotCompilationName(Class classToCompile) { - return classToCompile.getName().replaceAll("\\.", File.separator) + ".class"; + return classToCompile.getName().replaceAll("\\.", "/") + ".class"; } } diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java index 099554f3e13..1ae48eee35f 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.ListOptionNotExistingTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionNotExistingTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java index e0b52f5799c..e22d39254a5 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.ListOptionTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java index b3f0d1e626f..5549d5e95b4 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.cli.jaotc.ListOptionWrongFileTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionWrongFileTest diff --git a/hotspot/test/compiler/aot/fingerprint/SelfChanged.java b/hotspot/test/compiler/aot/fingerprint/SelfChanged.java index f15370e8cb7..ecd99eba0f0 100644 --- a/hotspot/test/compiler/aot/fingerprint/SelfChanged.java +++ b/hotspot/test/compiler/aot/fingerprint/SelfChanged.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.fingerprint.SelfChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java b/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java index 960c2165f6b..87635511ec0 100644 --- a/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java +++ b/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.fingerprint.SelfChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/fingerprint/SuperChanged.java b/hotspot/test/compiler/aot/fingerprint/SuperChanged.java index 253eee0ce08..969035c2f8b 100644 --- a/hotspot/test/compiler/aot/fingerprint/SuperChanged.java +++ b/hotspot/test/compiler/aot/fingerprint/SuperChanged.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @build compiler.aot.fingerprint.SuperChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java b/hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java deleted file mode 100644 index 9e5707a7906..00000000000 --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf.test; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import jdk.tools.jaotc.jnilibelf.JNIELFContainer; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; - -public class JNILibELFTest { - - public static void main(String[] args) { - // if (args.length != 2) { - // System.out.println("Please provide file-name as argument"); - // return; - // } - createSharedLib(); - } - - private static boolean createSharedLib() { - - int numProgHdrs = 1; - JNIELFContainer elfContainer = new JNIELFContainer("ELF"); - - // Allocate ELF Header - elfContainer.createELFHeader(ELF.ET_DYN); - - // Allocate 'numProgHdrs' program headers - - if (!elfContainer.createProgramHeader(numProgHdrs)) { - System.out.println("Failed to create Program Headers"); - return false; - } - - // Hash table content - int[] bhashWords = {0x01234567, 0x89abcdef, 0xdeadc0de}; - // int[] data = { 100, 200, 300, 400 }; - - ByteBuffer byteBuffer = ByteBuffer.allocate(bhashWords.length * 4); - IntBuffer intBuffer = byteBuffer.asIntBuffer(); - intBuffer.put(bhashWords); - - // byte[] int_hash_array = byteBuffer.array(); - - // Hash Table content - // ByteBuffer hash_words = ByteBuffer.allocate(14).putInt(0x01234567); - // hash_words.putInt(0x89abcdef); - // hash_words.putInt(0xdeadc0de); - - // Create a hash section - // Setting sh_link as 0 since this is just a demo - the value should actually be the section - // header index - // of the symbol table to which the hash table applies. - int index = elfContainer.createSection(".hash", byteBuffer.array(), Elf_Type.ELF_T_WORD, 4, ELF.SHT_HASH, ELF.SHF_ALLOC, 0, 0); - if (index == 0) { - System.out.println("Failed to create hash section"); - return false; - } - - elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, (ELF.SHF_STRINGS | ELF.SHF_ALLOC), ELF.SHN_UNDEF, 0); - // Now, finally, after creating all sections, create shstrtab section - elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); - // Run elf_update - elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL); - - // Set program header type to self - elfContainer.setProgHdrTypeToSelf(); - // Setting pheader to self type also sets it to be dirty. So run elfUpdate again - // to write it out. - elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE); - // Finish ELF processing - elfContainer.elfEnd(); - return true; - } -} diff --git a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java index 1b9a1a45ff0..bee78970083 100644 --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @requires os.family == "linux" & vm.bits == "64" & os.arch == "amd64" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules jdk.aot/jdk.tools.jaotc.utils * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.tools.jaotc.test.NativeOrderOutputStreamTest */ diff --git a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java index b2741387fa7..76c72b062db 100644 --- a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java +++ b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.ClassAndLibraryNotMatchTest * @run driver compiler.aot.verification.ClassAndLibraryNotMatchTest diff --git a/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java b/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java index 203bd32eabb..7ced6606309 100644 --- a/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java +++ b/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.vmflags.BasicFlagsChange * @run driver compiler.aot.verification.vmflags.BasicFlagsChange diff --git a/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java b/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java index 4f6bb01d1dd..b374ca6b3ea 100644 --- a/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java +++ b/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux" + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.vmflags.BasicFlagsChange * @run driver compiler.aot.verification.vmflags.BasicFlagsChange From 6e88661a898fbf36ac74c721831d287a08c6cec5 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 10 Feb 2017 07:46:07 -0500 Subject: [PATCH 14/86] 8174092: Remove array-related access checks from Reflection::verify_class_access() Change the parameter type to InstanceKlass* and fix the method's callers Reviewed-by: acorn, coleenp, gtriantafill, lfoltan --- hotspot/src/share/vm/ci/ciEnv.cpp | 4 ++-- hotspot/src/share/vm/classfile/classFileParser.cpp | 14 +++++++++----- hotspot/src/share/vm/interpreter/linkResolver.cpp | 8 +++++--- hotspot/src/share/vm/jvmci/jvmciEnv.cpp | 4 ++-- hotspot/src/share/vm/prims/methodHandles.cpp | 4 ++-- hotspot/src/share/vm/runtime/reflection.cpp | 13 +++---------- hotspot/src/share/vm/runtime/reflection.hpp | 6 +++--- 7 files changed, 26 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 024909b1cbc..fce88ba51c4 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -374,7 +374,7 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass, } if (resolved_klass->is_instance_klass()) { return (Reflection::verify_class_access(accessing_klass->get_Klass(), - resolved_klass, + InstanceKlass::cast(resolved_klass), true) == Reflection::ACCESS_OK); } return true; diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index f1eace4eb65..87b593eb690 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -4374,10 +4374,12 @@ static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) { } Reflection::VerifyClassAccessResults vca_result = - Reflection::verify_class_access(this_klass, super, false); + Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false); if (vca_result != Reflection::ACCESS_OK) { ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(this_klass, super, vca_result); + char* msg = Reflection::verify_class_access_msg(this_klass, + InstanceKlass::cast(super), + vca_result); if (msg == NULL) { Exceptions::fthrow( THREAD_AND_LOCATION, @@ -4406,10 +4408,12 @@ static void check_super_interface_access(const InstanceKlass* this_klass, TRAPS) Klass* const k = local_interfaces->at(i); assert (k != NULL && k->is_interface(), "invalid interface"); Reflection::VerifyClassAccessResults vca_result = - Reflection::verify_class_access(this_klass, k, false); + Reflection::verify_class_access(this_klass, InstanceKlass::cast(k), false); if (vca_result != Reflection::ACCESS_OK) { ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(this_klass, k, vca_result); + char* msg = Reflection::verify_class_access_msg(this_klass, + InstanceKlass::cast(k), + vca_result); if (msg == NULL) { Exceptions::fthrow( THREAD_AND_LOCATION, diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index b062f2cc4bd..ce452bfe1f4 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -275,10 +275,12 @@ void LinkInfo::print() { void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) { Reflection::VerifyClassAccessResults vca_result = - Reflection::verify_class_access(ref_klass(), sel_klass(), true); + Reflection::verify_class_access(ref_klass(), InstanceKlass::cast(sel_klass()), true); if (vca_result != Reflection::ACCESS_OK) { ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(ref_klass(), sel_klass(), vca_result); + char* msg = Reflection::verify_class_access_msg(ref_klass(), + InstanceKlass::cast(sel_klass()), + vca_result); if (msg == NULL) { Exceptions::fthrow( THREAD_AND_LOCATION, diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp index 9c5d98361e0..65f69d7c602 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -79,7 +79,7 @@ bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandl } if (resolved_klass->is_instance_klass()) { Reflection::VerifyClassAccessResults result = - Reflection::verify_class_access(accessing_klass(), resolved_klass(), true); + Reflection::verify_class_access(accessing_klass(), InstanceKlass::cast(resolved_klass()), true); return result == Reflection::ACCESS_OK; } return true; diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 717c1fe00ad..96ccab1071c 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -1209,7 +1209,7 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, // Emulate LinkResolver::check_klass_accessability. Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)); if (Reflection::verify_class_access(caller, - reference_klass, + InstanceKlass::cast(reference_klass), true) != Reflection::ACCESS_OK) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name()); } diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index b2fc1018828..13909417ceb 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -477,7 +477,7 @@ static bool can_relax_access_check_for(const Klass* accessor, Note: a loose module is a module that can read all current and future unnamed modules. */ Reflection::VerifyClassAccessResults Reflection::verify_class_access( - const Klass* current_class, const Klass* new_class, bool classloader_only) { + const Klass* current_class, const InstanceKlass* new_class, bool classloader_only) { // Verify that current_class can access new_class. If the classloader_only // flag is set, we automatically allow any accesses in which current_class @@ -504,13 +504,6 @@ Reflection::VerifyClassAccessResults Reflection::verify_class_access( // Find the module entry for current_class, the accessor ModuleEntry* module_from = current_class->module(); // Find the module entry for new_class, the accessee - if (new_class->is_objArray_klass()) { - new_class = ObjArrayKlass::cast(new_class)->bottom_klass(); - } - if (new_class->is_typeArray_klass()) { - // A TypeArray's defining module is java.base, access to the TypeArray is allowed - return ACCESS_OK; - } ModuleEntry* module_to = new_class->module(); // both in same (possibly unnamed) module @@ -563,7 +556,7 @@ Reflection::VerifyClassAccessResults Reflection::verify_class_access( // Return an error message specific to the specified Klass*'s and result. // This function must be called from within a block containing a ResourceMark. char* Reflection::verify_class_access_msg(const Klass* current_class, - const Klass* new_class, + const InstanceKlass* new_class, VerifyClassAccessResults result) { assert(result != ACCESS_OK, "must be failure result"); char * msg = NULL; diff --git a/hotspot/src/share/vm/runtime/reflection.hpp b/hotspot/src/share/vm/runtime/reflection.hpp index 736e21f9f6b..75ba5d77820 100644 --- a/hotspot/src/share/vm/runtime/reflection.hpp +++ b/hotspot/src/share/vm/runtime/reflection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,12 +82,12 @@ class Reflection: public AllStatic { // Verification static VerifyClassAccessResults verify_class_access(const Klass* current_class, - const Klass* new_class, + const InstanceKlass* new_class, bool classloader_only); // Return an error message specific to the specified Klass*'s and result. // This function must be called from within a block containing a ResourceMark. static char* verify_class_access_msg(const Klass* current_class, - const Klass* new_class, + const InstanceKlass* new_class, const VerifyClassAccessResults result); static bool verify_field_access(const Klass* current_class, From 697bec6baf00bf28cae6efb41936c7b093fd4c5c Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 13 Feb 2017 10:37:33 -0500 Subject: [PATCH 15/86] 8169206: TemplateInterpreter::_continuation_entry is never referenced TemplateInterpreter::_continuation_entry has been removed. Reviewed-by: coleenp, dholmes, fparain --- .../vm/templateInterpreterGenerator_aarch64.cpp | 8 -------- .../arm/vm/templateInterpreterGenerator_arm.cpp | 6 ------ .../ppc/vm/templateInterpreterGenerator_ppc.cpp | 6 ------ .../s390/vm/templateInterpreterGenerator_s390.cpp | 7 ------- .../vm/templateInterpreterGenerator_sparc.cpp | 6 ------ .../x86/vm/templateInterpreterGenerator_x86.cpp | 10 ---------- .../share/vm/interpreter/templateInterpreter.cpp | 1 - .../share/vm/interpreter/templateInterpreter.hpp | 2 -- .../interpreter/templateInterpreterGenerator.cpp | 15 --------------- .../interpreter/templateInterpreterGenerator.hpp | 1 - 10 files changed, 62 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index 90dcd6c1a2c..0a4c7035c8a 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -402,14 +402,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ dispatch_next(state); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); diff --git a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp index 743510e09a7..036ae4cc7d8 100644 --- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -270,12 +270,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - // Not used. - STOP("generate_continuation_for"); - return NULL; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 56810938a53..cccc1bca650 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -646,12 +646,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ unimplemented("generate_continuation_for"); - return entry; -} - // This entry is returned to when a call returns to the interpreter. // When we arrive here, we expect that the callee stack frame is already popped. address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp index de266db04fc..9ecba106fae 100644 --- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -642,13 +642,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -// Unused, should never pass by. -address TemplateInterpreterGenerator::generate_continuation_for (TosState state) { - address entry = __ pc(); - __ should_not_reach_here(); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, int step, size_t index_size) { address entry = __ pc(); diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index b677a1dd662..c3645539903 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -466,12 +466,6 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ dispatch_next(state); - return entry; -} - // // Helpers for commoning out cases in the various type of method entries. // diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp index eb5661bee00..d9a5a1c9b1a 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -171,16 +171,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } - -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - __ dispatch_next(state); - return entry; -} - - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index 33e8aecf82e..b8feaa786f7 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -193,7 +193,6 @@ EntryPoint TemplateInterpreter::_trace_code; EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; EntryPoint TemplateInterpreter::_earlyret_entry; EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; -EntryPoint TemplateInterpreter::_continuation_entry; EntryPoint TemplateInterpreter::_safept_entry; address TemplateInterpreter::_invoke_return_entry[TemplateInterpreter::number_of_return_addrs]; diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp index f9d008d5c92..d2f808d558e 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp @@ -119,7 +119,6 @@ class TemplateInterpreter: public AbstractInterpreter { static EntryPoint _return_entry[number_of_return_entries]; // entry points to return to from a call static EntryPoint _earlyret_entry; // entry point to return early from a call static EntryPoint _deopt_entry[number_of_deopt_entries]; // entry points to return to from a deoptimization - static EntryPoint _continuation_entry; static EntryPoint _safept_entry; static address _invoke_return_entry[number_of_return_addrs]; // for invokestatic, invokespecial, invokevirtual return entries @@ -158,7 +157,6 @@ class TemplateInterpreter: public AbstractInterpreter { #ifndef PRODUCT static address trace_code (TosState state) { return _trace_code.entry(state); } #endif // !PRODUCT - static address continuation (TosState state) { return _continuation_entry.entry(state); } static address* dispatch_table(TosState state) { return _active_table.table_for(state); } static address* dispatch_table() { return _active_table.table_for(); } static int distance_from_dispatch_table(TosState state){ return _active_table.distance_from(state); } diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index 45ad899a4c3..22fe054f4f0 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -165,21 +165,6 @@ void TemplateInterpreterGenerator::generate_all() { } } - { CodeletMark cm(_masm, "continuation entry points"); - Interpreter::_continuation_entry = - EntryPoint( - generate_continuation_for(btos), - generate_continuation_for(ztos), - generate_continuation_for(ctos), - generate_continuation_for(stos), - generate_continuation_for(atos), - generate_continuation_for(itos), - generate_continuation_for(ltos), - generate_continuation_for(ftos), - generate_continuation_for(dtos), - generate_continuation_for(vtos) - ); - } { CodeletMark cm(_masm, "safepoint entry points"); Interpreter::_safept_entry = diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp index 6f8972e38ac..3261210575a 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp @@ -52,7 +52,6 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { address generate_exception_handler_common(const char* name, const char* message, bool pass_oop); address generate_ClassCastException_handler(); address generate_ArrayIndexOutOfBounds_handler(const char* name); - address generate_continuation_for(TosState state); address generate_return_entry_for(TosState state, int step, size_t index_size); address generate_earlyret_entry_for(TosState state); address generate_deopt_entry_for(TosState state, int step); From 861eef035c00553a06f446568aa387f43f922639 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 13 Feb 2017 12:00:40 -0500 Subject: [PATCH 16/86] 8157271: Avoid extra copy of NativeCallStack Now pass reference to NativeCallStack instead of copy. Reviewed-by: zgu, sspitsyn --- hotspot/src/share/vm/services/mallocSiteTable.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/services/mallocSiteTable.hpp b/hotspot/src/share/vm/services/mallocSiteTable.hpp index 7ded2d2b74a..1081ef00014 100644 --- a/hotspot/src/share/vm/services/mallocSiteTable.hpp +++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp @@ -62,7 +62,7 @@ class MallocSiteHashtableEntry : public CHeapObj { public: MallocSiteHashtableEntry() : _next(NULL) { } - MallocSiteHashtableEntry(NativeCallStack stack): + MallocSiteHashtableEntry(const NativeCallStack& stack): _malloc_site(stack), _next(NULL) { } inline const MallocSiteHashtableEntry* next() const { From ec7aacc831a1117a3791e176e51008ae9cc79b80 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 13 Feb 2017 19:10:55 -0500 Subject: [PATCH 17/86] 8157709: NMT should use size_t version of Atomic::add Reviewed-by: kbarrett, sspitsyn --- hotspot/src/share/vm/runtime/atomic.hpp | 14 +----------- .../src/share/vm/services/mallocTracker.hpp | 22 ++++++++++--------- hotspot/src/share/vm/services/nmtCommon.hpp | 9 +------- 3 files changed, 14 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/runtime/atomic.hpp b/hotspot/src/share/vm/runtime/atomic.hpp index ccf24669fa1..51800788e3c 100644 --- a/hotspot/src/share/vm/runtime/atomic.hpp +++ b/hotspot/src/share/vm/runtime/atomic.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -81,8 +81,6 @@ class Atomic : AllStatic { inline static size_t add (size_t add_value, volatile size_t* dest); inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); inline static void* add_ptr(intptr_t add_value, volatile void* dest); - // See comment above about using jlong atomics on 32-bit platforms - inline static jlong add (jlong add_value, volatile jlong* dest); // Atomically increment location. inc*() provide: // increment-dest @@ -199,16 +197,6 @@ inline unsigned Atomic::cmpxchg(unsigned int exchange_value, (jint)compare_value, order); } -inline jlong Atomic::add(jlong add_value, volatile jlong* dest) { - jlong old = load(dest); - jlong new_value = old + add_value; - while (old != cmpxchg(new_value, dest, old)) { - old = load(dest); - new_value = old + add_value; - } - return old; -} - inline jshort Atomic::add(jshort add_value, volatile jshort* dest) { // Most platforms do not support atomic add on a 2-byte value. However, // if the value occupies the most significant 16 bits of an aligned 32-bit diff --git a/hotspot/src/share/vm/services/mallocTracker.hpp b/hotspot/src/share/vm/services/mallocTracker.hpp index 3020b3148fe..329d2ea9dfc 100644 --- a/hotspot/src/share/vm/services/mallocTracker.hpp +++ b/hotspot/src/share/vm/services/mallocTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -40,8 +40,8 @@ */ class MemoryCounter VALUE_OBJ_CLASS_SPEC { private: - size_t _count; - size_t _size; + volatile size_t _count; + volatile size_t _size; DEBUG_ONLY(size_t _peak_count;) DEBUG_ONLY(size_t _peak_size; ) @@ -53,26 +53,28 @@ class MemoryCounter VALUE_OBJ_CLASS_SPEC { } inline void allocate(size_t sz) { - Atomic::add(1, (volatile MemoryCounterType*)&_count); + Atomic::add(1, &_count); if (sz > 0) { - Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + Atomic::add(sz, &_size); DEBUG_ONLY(_peak_size = MAX2(_peak_size, _size)); } DEBUG_ONLY(_peak_count = MAX2(_peak_count, _count);) } inline void deallocate(size_t sz) { - assert(_count > 0, "Negative counter"); - assert(_size >= sz, "Negative size"); - Atomic::add(-1, (volatile MemoryCounterType*)&_count); + assert(_count > 0, "Nothing allocated yet"); + assert(_size >= sz, "deallocation > allocated"); + Atomic::add(-1, &_count); if (sz > 0) { - Atomic::add(-(MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + // unary minus operator applied to unsigned type, result still unsigned + #pragma warning(suppress: 4146) + Atomic::add(-sz, &_size); } } inline void resize(long sz) { if (sz != 0) { - Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + Atomic::add(sz, &_size); DEBUG_ONLY(_peak_size = MAX2(_size, _peak_size);) } } diff --git a/hotspot/src/share/vm/services/nmtCommon.hpp b/hotspot/src/share/vm/services/nmtCommon.hpp index 2864ff2cfa0..3fd4723c4e7 100644 --- a/hotspot/src/share/vm/services/nmtCommon.hpp +++ b/hotspot/src/share/vm/services/nmtCommon.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,6 @@ #define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_size_up_(sizeof(obj), sizeof(type))/sizeof(type)) -// Data type for memory counters -#ifdef _LP64 - typedef jlong MemoryCounterType; -#else - typedef jint MemoryCounterType; -#endif - // Native memory tracking level enum NMT_TrackingLevel { NMT_unknown = 0xFF, From b6eb59739d997310487126fc560cb0e2d37b633e Mon Sep 17 00:00:00 2001 From: Bob Vandette Date: Tue, 14 Feb 2017 11:24:35 -0500 Subject: [PATCH 18/86] 8174203: Enable AOT Jtreg tests on Windows x86_64 Reviewed-by: kvn, dholmes --- .../src/jdk/tools/jaotc/Main.java | 55 ++++++++++++++++--- .../test/compiler/aot/DeoptimizationTest.java | 2 +- .../test/compiler/aot/RecompilationTest.java | 2 +- .../test/compiler/aot/SharedUsageTest.java | 2 +- .../fromAot/AotInvokeDynamic2AotTest.java | 2 +- .../AotInvokeDynamic2CompiledTest.java | 2 +- .../AotInvokeDynamic2InterpretedTest.java | 2 +- .../fromAot/AotInvokeDynamic2NativeTest.java | 2 +- .../fromAot/AotInvokeInterface2AotTest.java | 2 +- .../AotInvokeInterface2CompiledTest.java | 2 +- .../AotInvokeInterface2InterpretedTest.java | 2 +- .../AotInvokeInterface2NativeTest.java | 2 +- .../fromAot/AotInvokeSpecial2AotTest.java | 2 +- .../AotInvokeSpecial2CompiledTest.java | 2 +- .../AotInvokeSpecial2InterpretedTest.java | 2 +- .../fromAot/AotInvokeSpecial2NativeTest.java | 2 +- .../fromAot/AotInvokeStatic2AotTest.java | 2 +- .../fromAot/AotInvokeStatic2CompiledTest.java | 2 +- .../AotInvokeStatic2InterpretedTest.java | 2 +- .../fromAot/AotInvokeStatic2NativeTest.java | 2 +- .../fromAot/AotInvokeVirtual2AotTest.java | 2 +- .../AotInvokeVirtual2CompiledTest.java | 2 +- .../AotInvokeVirtual2InterpretedTest.java | 2 +- .../fromAot/AotInvokeVirtual2NativeTest.java | 2 +- .../CompiledInvokeDynamic2AotTest.java | 2 +- .../CompiledInvokeInterface2AotTest.java | 2 +- .../CompiledInvokeSpecial2AotTest.java | 2 +- .../CompiledInvokeStatic2AotTest.java | 2 +- .../CompiledInvokeVirtual2AotTest.java | 2 +- .../InterpretedInvokeDynamic2AotTest.java | 2 +- .../InterpretedInvokeInterface2AotTest.java | 2 +- .../InterpretedInvokeSpecial2AotTest.java | 2 +- .../InterpretedInvokeStatic2AotTest.java | 2 +- .../InterpretedInvokeVirtual2AotTest.java | 2 +- .../NativeInvokeSpecial2AotTest.java | 2 +- .../NativeInvokeStatic2AotTest.java | 2 +- .../NativeInvokeVirtual2AotTest.java | 2 +- .../aot/cli/DisabledAOTWithLibraryTest.java | 2 +- .../aot/cli/IncorrectAOTLibraryTest.java | 2 +- .../aot/cli/MultipleAOTLibraryTest.java | 2 +- .../aot/cli/NonExistingAOTLibraryTest.java | 2 +- .../aot/cli/SingleAOTLibraryTest.java | 2 +- .../compiler/aot/cli/SingleAOTOptionTest.java | 2 +- .../aot/cli/jaotc/ClasspathOptionTest.java | 2 +- .../ClasspathOptionUnknownClassTest.java | 2 +- .../aot/cli/jaotc/CompileClassTest.java | 2 +- .../aot/cli/jaotc/CompileDirectoryTest.java | 2 +- .../aot/cli/jaotc/CompileJarTest.java | 2 +- .../aot/cli/jaotc/CompileModuleTest.java | 2 +- .../cli/jaotc/ListOptionNotExistingTest.java | 2 +- .../aot/cli/jaotc/ListOptionTest.java | 2 +- .../cli/jaotc/ListOptionWrongFileTest.java | 2 +- .../compiler/aot/fingerprint/SelfChanged.java | 2 +- .../aot/fingerprint/SelfChangedCDS.java | 2 +- .../aot/fingerprint/SuperChanged.java | 2 +- .../test/NativeOrderOutputStreamTest.java | 2 +- .../ClassAndLibraryNotMatchTest.java | 2 +- .../vmflags/NotTrackedFlagTest.java | 2 +- .../verification/vmflags/TrackedFlagTest.java | 2 +- 59 files changed, 106 insertions(+), 65 deletions(-) diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index fb23bdb96ba..792a9e83dd1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -314,18 +314,59 @@ public class Main implements LogPrinter { } } + /** + * Visual Studio supported versions + * Search Order is: VS2013, VS2015, VS2012 + */ + public enum VSVERSIONS { + VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), + VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"), + VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe"); + + private final String envvariable; + private final String wkp; + + VSVERSIONS(String envvariable, String wellknownpath) { + this.envvariable = envvariable; + this.wkp = wellknownpath; + } + + String EnvVariable() { return envvariable; } + String WellKnownPath() { return wkp; } + } + /** * Search for Visual Studio link.exe * Search Order is: VS2013, VS2015, VS2012 */ - private String getWindowsLinkPath() { - String vs2013 = "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"; - String vs2015 = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"; - String vs2012 = "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe"; + private static String getWindowsLinkPath() { + String link = "\\VC\\bin\\amd64\\link.exe"; + + /** + * First try searching the paths pointed to by + * the VS environment variables. + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String vspath = System.getenv(vs.EnvVariable()); + if (vspath != null) { + File commonTools = new File(vspath); + File vsRoot = commonTools.getParentFile().getParentFile(); + File linkPath = new File(vsRoot, link); + if (linkPath.exists()) return linkPath.getPath(); + } + } + + /** + * If we didn't find via the VS environment variables, + * try the well known paths + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String wkp = vs.WellKnownPath(); + if (new File(wkp).exists()) { + return wkp; + } + } - if (new File(vs2015).exists()) return vs2015; - if (new File(vs2013).exists()) return vs2013; - if (new File(vs2012).exists()) return vs2012; return null; } diff --git a/hotspot/test/compiler/aot/DeoptimizationTest.java b/hotspot/test/compiler/aot/DeoptimizationTest.java index d74681514fa..8dd4db00bac 100644 --- a/hotspot/test/compiler/aot/DeoptimizationTest.java +++ b/hotspot/test/compiler/aot/DeoptimizationTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.aot.DeoptimizationTest * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/RecompilationTest.java b/hotspot/test/compiler/aot/RecompilationTest.java index e2dc3a1f3f7..3a76739d287 100644 --- a/hotspot/test/compiler/aot/RecompilationTest.java +++ b/hotspot/test/compiler/aot/RecompilationTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.aot.RecompilationTest * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/SharedUsageTest.java b/hotspot/test/compiler/aot/SharedUsageTest.java index ce104201675..3966d14ad93 100644 --- a/hotspot/test/compiler/aot/SharedUsageTest.java +++ b/hotspot/test/compiler/aot/SharedUsageTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.SharedUsageTest * compiler.aot.AotCompiler * @run main compiler.aot.AotCompiler -libname libSharedUsageTest.so diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java index 767687a18a3..df9088cdc70 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java index aa05ac5a560..e3bbe934e2c 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java index 80ee4fe0142..10ff13db86e 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java index 099d5e3d0e3..da396c8a671 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @ignore 8132547 - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java index f760bb0c04e..6f8fd35f3da 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java index 55b93dd5844..4ca3feebe4a 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java index 190a91107cc..a26167e640a 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java index a172aafe9ef..a57ad128379 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java index 333b1179b62..2c39cf1556c 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java index 171ad13c0e5..f2f36c99950 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java index c1244da13e2..8a33237a2f2 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java index 00aa7f6fac8..b63f3fb32a2 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java index 52e41d6b151..c8b121b67d3 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java index 887e78e7ea7..376f43927e3 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java index 61f6d77addc..351c10ce734 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java index 72dd71f2da8..d4f1b30d964 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java index 10f2e373f0e..c1bfda72ce3 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java index 0d903d79333..975fc029f4a 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java index 5f20ebf3d0a..a2cc727cd36 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java index dec95c8d6d2..091215cd6c6 100644 --- a/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java +++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java index a2daaafe247..104505b1afb 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java index 94c2b4b5c81..a46e51ad65a 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java index 49131cff31f..7fad78d2f5f 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java index 0cb0af40d53..579cc83a580 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java index be34a4dc41d..6c41cb47f57 100644 --- a/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java index 132327711ba..1f44eb2cb21 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc * @build compiler.calls.common.InvokeDynamic diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java index 5197f6e107d..e494ca6a1a9 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeInterface * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java index 9585f7b3a4c..fca27ff9932 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java index 8909b69d661..ced2f0bdd91 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java index 98250be7421..9af0f474833 100644 --- a/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java index ac73b16982d..77f810d8d8b 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeSpecial * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java index 486362ce03a..a7e99878cae 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeStatic * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java index 07eb8451e80..7eebd5a3b06 100644 --- a/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java +++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.calls.common.InvokeVirtual * compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java b/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java index 5f0f195e76e..f78e9a39c96 100644 --- a/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib /testlibrary / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.DisabledAOTWithLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libDisabledAOTWithLibraryTest.so diff --git a/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java index 3018d8c8a10..08079c51527 100644 --- a/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @run driver ClassFileInstaller ClassFileInstaller * @run driver compiler.aot.cli.IncorrectAOTLibraryTest * @summary check if incorrect aot library is handled properly diff --git a/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java index 09d507530de..8064af69762 100644 --- a/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.MultipleAOTLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler diff --git a/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java index 7c19b781acf..f9dd4f3a802 100644 --- a/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @run driver compiler.aot.cli.NonExistingAOTLibraryTest * @summary check if non-existing aot library is handled properly */ diff --git a/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java b/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java index 298150eb797..47c9219c2f6 100644 --- a/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java +++ b/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib / /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.SingleAOTLibraryTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libSingleAOTLibraryTest.so diff --git a/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java b/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java index b9af1cbfb4a..6cc580663fd 100644 --- a/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java +++ b/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java @@ -25,7 +25,7 @@ * @test * @library /test/lib /testlibrary / * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.SingleAOTOptionTest * compiler.aot.AotCompiler * @run driver compiler.aot.AotCompiler -libname libSingleAOTOptionTest.so diff --git a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java index e3b8fa8be19..0f834d86eaa 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.ClasspathOptionTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java index 97faac789ff..89b110836b7 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java @@ -25,7 +25,7 @@ * @test * @library / /testlibrary/ /test/lib * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @compile data/HelloWorldOne.java * @run driver compiler.aot.cli.jaotc.ClasspathOptionUnknownClassTest * @summary check jaotc can't compile class not from classpath diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java index 209b7802f74..008f4aa5e92 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.CompileClassTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.CompileClassTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java index 8bf32795be3..971e684d06f 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.CompileDirectoryTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * compiler.aot.cli.jaotc.data.HelloWorldTwo diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java index 62d7e1e94e3..0dcabd16737 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.CompileJarTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * compiler.aot.cli.jaotc.data.HelloWorldTwo diff --git a/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java b/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java index 2d51746c633..09bb6c8150f 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @run driver compiler.aot.cli.jaotc.CompileModuleTest * @summary check jaotc can compile module */ diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java index 1ae48eee35f..a814157678e 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.ListOptionNotExistingTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionNotExistingTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java index e22d39254a5..fb875995582 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.ListOptionTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionTest diff --git a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java index 5549d5e95b4..2da6793bae9 100644 --- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java +++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java @@ -25,7 +25,7 @@ * @test * @library / /test/lib /testlibrary * @modules java.base/jdk.internal.misc - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.cli.jaotc.ListOptionWrongFileTest * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne * @run driver compiler.aot.cli.jaotc.ListOptionWrongFileTest diff --git a/hotspot/test/compiler/aot/fingerprint/SelfChanged.java b/hotspot/test/compiler/aot/fingerprint/SelfChanged.java index ecd99eba0f0..bc32ff4de60 100644 --- a/hotspot/test/compiler/aot/fingerprint/SelfChanged.java +++ b/hotspot/test/compiler/aot/fingerprint/SelfChanged.java @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.fingerprint.SelfChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java b/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java index 87635511ec0..fed4465ee82 100644 --- a/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java +++ b/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.fingerprint.SelfChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/fingerprint/SuperChanged.java b/hotspot/test/compiler/aot/fingerprint/SuperChanged.java index 969035c2f8b..f7d9490ccab 100644 --- a/hotspot/test/compiler/aot/fingerprint/SuperChanged.java +++ b/hotspot/test/compiler/aot/fingerprint/SuperChanged.java @@ -27,7 +27,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @build compiler.aot.fingerprint.SuperChanged * compiler.aot.AotCompiler * diff --git a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java index bee78970083..b63e4bbab4a 100644 --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java @@ -23,7 +23,7 @@ /** * @test - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules jdk.aot/jdk.tools.jaotc.utils * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.tools.jaotc.test.NativeOrderOutputStreamTest */ diff --git a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java index 76c72b062db..6e39a1aa89d 100644 --- a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java +++ b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.ClassAndLibraryNotMatchTest * @run driver compiler.aot.verification.ClassAndLibraryNotMatchTest diff --git a/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java b/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java index 7ced6606309..b27743aa913 100644 --- a/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java +++ b/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.vmflags.BasicFlagsChange * @run driver compiler.aot.verification.vmflags.BasicFlagsChange diff --git a/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java b/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java index b374ca6b3ea..8f2cfe02ed8 100644 --- a/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java +++ b/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java @@ -24,7 +24,7 @@ /* * @test * @library /test/lib / - * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") & !(os.family == "windows") + * @requires vm.bits == "64" & (os.arch == "amd64" | os.arch == "x86_64") * @modules java.base/jdk.internal.misc * @build compiler.aot.verification.vmflags.BasicFlagsChange * @run driver compiler.aot.verification.vmflags.BasicFlagsChange From bf9a4cd8fb5ea0b14f4b3b77f15f3e86feabb8c9 Mon Sep 17 00:00:00 2001 From: Vladimir Kempik Date: Fri, 17 Feb 2017 02:31:12 +0000 Subject: [PATCH 19/86] 8165753: Custom security manager, crashing wth 'java/security/AccessControlException' Reviewed-by: dholmes, dcubed --- hotspot/src/share/vm/runtime/os.cpp | 5 ++--- hotspot/src/share/vm/runtime/os.hpp | 4 ++-- hotspot/src/share/vm/runtime/thread.cpp | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 18359effe52..e3f97c84c42 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -347,10 +347,9 @@ void os::init_before_ergo() { VM_Version::init_before_ergo(); } -void os::signal_init() { +void os::signal_init(TRAPS) { if (!ReduceSignalUsage) { // Setup JavaThread for processing signals - EXCEPTION_MARK; Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK); instanceKlassHandle klass (THREAD, k); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index ac5919a255d..329cf6de53a 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -731,7 +731,7 @@ class os: AllStatic { static struct hostent* get_host_by_name(char* name); // Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal) - static void signal_init(); + static void signal_init(TRAPS); static void signal_init_pd(); static void signal_notify(int signal_number); static void* signal(int signal_number, void* handler); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index abdcab5684c..ef353659d06 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -3717,7 +3717,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { #endif // INCLUDE_MANAGEMENT // Signal Dispatcher needs to be started before VMInit event is posted - os::signal_init(); + os::signal_init(CHECK_JNI_ERR); // Start Attach Listener if +StartAttachListener or it can't be started lazily if (!DisableAttachMechanism) { From fcc96991328bfbc7a928d441b07d7c05ee8fe044 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 17 Feb 2017 14:47:46 -0500 Subject: [PATCH 20/86] 8175104: Unhandled oop in ProtectionDomainCacheTable::compute_hash Pass Handle for protection_domain as it is mostly a Handle up the call stack Reviewed-by: hseigel, jiangli, dcubed --- hotspot/src/share/vm/classfile/dictionary.cpp | 23 ++++++++++--------- hotspot/src/share/vm/classfile/dictionary.hpp | 20 ++++++++-------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index eda1531ee74..338e9229068 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -61,7 +61,7 @@ Dictionary::Dictionary(int table_size, HashtableBucket* t, _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize); }; -ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) { +ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) { return _pd_cache_table->get(protection_domain); } @@ -123,9 +123,9 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { } -void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) { +void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) { assert_locked_or_safepoint(SystemDictionary_lock); - if (!contains_protection_domain(protection_domain)) { + if (!contains_protection_domain(protection_domain())) { ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain); ProtectionDomainEntry* new_head = new ProtectionDomainEntry(entry, _pd_set); @@ -454,7 +454,7 @@ void Dictionary::add_protection_domain(int index, unsigned int hash, assert(protection_domain() != NULL, "real protection domain should be present"); - entry->add_protection_domain(this, protection_domain()); + entry->add_protection_domain(this, protection_domain); assert(entry->contains_protection_domain(protection_domain()), "now protection domain should be present"); @@ -505,11 +505,12 @@ void Dictionary::reorder_dictionary() { } -unsigned int ProtectionDomainCacheTable::compute_hash(oop protection_domain) { +unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) { + // Identity hash can safepoint, so keep protection domain in a Handle. return (unsigned int)(protection_domain->identity_hash()); } -int ProtectionDomainCacheTable::index_for(oop protection_domain) { +int ProtectionDomainCacheTable::index_for(Handle protection_domain) { return hash_to_index(compute_hash(protection_domain)); } @@ -619,7 +620,7 @@ void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) { } } -ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) { +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(Handle protection_domain) { unsigned int hash = compute_hash(protection_domain); int index = hash_to_index(hash); @@ -630,9 +631,9 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domai return entry; } -ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) { +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, Handle protection_domain) { for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) { - if (e->protection_domain() == protection_domain) { + if (e->protection_domain() == protection_domain()) { return e; } } @@ -640,7 +641,7 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oo return NULL; } -ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) { +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, Handle protection_domain) { assert_locked_or_safepoint(SystemDictionary_lock); assert(index == index_for(protection_domain), "incorrect index?"); assert(find_entry(index, protection_domain) == NULL, "no double entry"); @@ -651,7 +652,7 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, uns } void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) { - unsigned int hash = compute_hash(to_delete->protection_domain()); + unsigned int hash = compute_hash(Handle(Thread::current(), to_delete->protection_domain())); int index = hash_to_index(hash); ProtectionDomainCacheEntry** p = bucket_addr(index); diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index e0280441bd3..f1c11d68cdb 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ public: // Sharing support void reorder_dictionary(); - ProtectionDomainCacheEntry* cache_get(oop protection_domain); + ProtectionDomainCacheEntry* cache_get(Handle protection_domain); void print(bool details = true); #ifdef ASSERT @@ -194,23 +194,23 @@ private: return (ProtectionDomainCacheEntry**) Hashtable::bucket_addr(i); } - ProtectionDomainCacheEntry* new_entry(unsigned int hash, oop protection_domain) { - ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable::new_entry(hash, protection_domain); + ProtectionDomainCacheEntry* new_entry(unsigned int hash, Handle protection_domain) { + ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable::new_entry(hash, protection_domain()); entry->init(); return entry; } - static unsigned int compute_hash(oop protection_domain); + static unsigned int compute_hash(Handle protection_domain); - int index_for(oop protection_domain); - ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, oop protection_domain); - ProtectionDomainCacheEntry* find_entry(int index, oop protection_domain); + int index_for(Handle protection_domain); + ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, Handle protection_domain); + ProtectionDomainCacheEntry* find_entry(int index, Handle protection_domain); public: ProtectionDomainCacheTable(int table_size); - ProtectionDomainCacheEntry* get(oop protection_domain); + ProtectionDomainCacheEntry* get(Handle protection_domain); void free(ProtectionDomainCacheEntry* entry); void unlink(BoolObjectClosure* cl); @@ -275,7 +275,7 @@ class DictionaryEntry : public HashtableEntry { // Tells whether a protection is in the approved set. bool contains_protection_domain(oop protection_domain) const; // Adds a protection domain to the approved set. - void add_protection_domain(Dictionary* dict, oop protection_domain); + void add_protection_domain(Dictionary* dict, Handle protection_domain); Klass* klass() const { return (Klass*)literal(); } Klass** klass_addr() { return (Klass**)literal_addr(); } From be6bbf5834e9a87da27026fbf78bce6df725545c Mon Sep 17 00:00:00 2001 From: Bob Vandette Date: Wed, 22 Feb 2017 12:33:36 -0500 Subject: [PATCH 21/86] 8174863: AOT: jaotc should provide an option to specify the path to the platform linker Reviewed-by: kvn --- .../src/jdk/tools/jaotc/Main.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index 792a9e83dd1..ae002cd1bbc 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -203,6 +203,11 @@ public class Main implements LogPrinter { void process(Main task, String opt, String arg) { task.options.version = true; } + }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { + @Override + void process(Main task, String opt, String arg) { + task.options.linkerpath = arg; + } }, new Option(" -J Pass directly to the runtime system", false, "-J") { @Override void process(Main task, String opt, String arg) { @@ -216,6 +221,7 @@ public class Main implements LogPrinter { public String outputName = "unnamed.so"; public String methodList; public String classpath = "."; + public String linkerpath = null; /** * We don't see scaling beyond 16 threads. @@ -460,7 +466,8 @@ public class Main implements LogPrinter { // tests are fixed. String libraryFileName = name; - String ldCmd; + String linkerCmd; + String linkerPath; String osName = System.getProperty("os.name"); if (name.endsWith(".so")) { @@ -477,27 +484,31 @@ public class Main implements LogPrinter { case "Linux": // libraryFileName = options.outputName + ".so"; objectFileName = objectFileName + ".o"; - ldCmd = "ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; break; case "SunOS": // libraryFileName = options.outputName + ".so"; objectFileName = objectFileName + ".o"; - ldCmd = "ld -shared -o " + libraryFileName + " " + objectFileName; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName; break; case "Mac OS X": // libraryFileName = options.outputName + ".dylib"; objectFileName = objectFileName + ".o"; - ldCmd = "ld -dylib -o " + libraryFileName + " " + objectFileName; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName; break; default: if (osName.startsWith("Windows")) { // libraryFileName = options.outputName + ".dll"; objectFileName = objectFileName + ".obj"; - String linkpath = getWindowsLinkPath(); - if (linkpath == null) { + linkerPath = (options.linkerpath != null) ? + options.linkerpath : getWindowsLinkPath(); + if (linkerPath == null) { throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe"); } - ldCmd = linkpath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; + linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; break; } else @@ -516,7 +527,7 @@ public class Main implements LogPrinter { } try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) { - Process p = Runtime.getRuntime().exec(ldCmd); + Process p = Runtime.getRuntime().exec(linkerCmd); final int exitCode = p.waitFor(); if (exitCode != 0) { InputStream stderr = p.getErrorStream(); From 342c0bc788bd8e6288c8c1d1360b8677a8ae7380 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 23 Feb 2017 10:18:21 +0100 Subject: [PATCH 22/86] 8160874: Remove typo in G1InitalMarkClosures Reviewed-by: stefank, sjohanss --- hotspot/src/share/vm/gc/g1/g1RootClosures.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp b/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp index 5ecdade929a..b60fc136730 100644 --- a/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -59,7 +59,7 @@ public: // The treatment of "weak" roots is selectable through the template parameter, // this is usually used to control unloading of classes and interned strings. template -class G1InitalMarkClosures : public G1EvacuationRootClosures { +class G1InitialMarkClosures : public G1EvacuationRootClosures { G1SharedClosures _strong; G1SharedClosures _weak; @@ -74,8 +74,8 @@ class G1InitalMarkClosures : public G1EvacuationRootClosures { } public: - G1InitalMarkClosures(G1CollectedHeap* g1h, - G1ParScanThreadState* pss) : + G1InitialMarkClosures(G1CollectedHeap* g1h, + G1ParScanThreadState* pss) : _strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true), _weak(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true) {} @@ -118,9 +118,9 @@ G1EvacuationRootClosures* G1EvacuationRootClosures::create_root_closures(G1ParSc if (g1h->collector_state()->during_initial_mark_pause()) { if (ClassUnloadingWithConcurrentMark) { - res = new G1InitalMarkClosures(g1h, pss); + res = new G1InitialMarkClosures(g1h, pss); } else { - res = new G1InitalMarkClosures(g1h, pss); + res = new G1InitialMarkClosures(g1h, pss); } } else { res = new G1EvacuationClosures(g1h, pss, g1h->collector_state()->gcs_are_young()); From 3b93aefe93d24bd8761a346711e7cb6af9ab16ff Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 23 Feb 2017 10:19:05 +0100 Subject: [PATCH 23/86] 8162104: Use in_cset() instead of obj_in_cs() Reviewed-by: ehelin, sjohanss --- hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 7 +------ hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp | 6 ++---- .../src/share/vm/gc/g1/g1CollectedHeap.inline.hpp | 12 ++---------- hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp | 8 ++++---- 7 files changed, 15 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp index c0ac7a8d557..633b71b96a3 100644 --- a/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -37,7 +37,7 @@ void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop_work(T* p) { if (!oopDesc::is_null(oop_or_narrowoop)) { oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop); HeapRegion* hr = _g1h->heap_region_containing(o); - assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset"); + assert(!_g1h->is_in_cset(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset"); hr->add_strong_code_root(_nm); } } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index fce91a80ad3..ba6b9fc0867 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -2364,11 +2364,6 @@ bool G1CollectedHeap::is_in_exact(const void* p) const { } #endif -bool G1CollectedHeap::obj_in_cs(oop obj) { - HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj); - return r != NULL && r->in_collection_set(); -} - // Iteration functions. // Applies an ExtendedOopClosure onto all references of objects within a HeapRegion. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index d1e8dcafb14..9851dca97fb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -1129,9 +1129,7 @@ public: #endif // Return "TRUE" iff the given object address is within the collection - // set. Slow implementation. - bool obj_in_cs(oop obj); - + // set. Assumes that the reference points into the heap. inline bool is_in_cset(const HeapRegion *hr); inline bool is_in_cset(oop obj); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index ef847a80a7a..2492e4c3596 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,16 +142,8 @@ inline bool G1CollectedHeap::isMarkedNext(oop obj) const { return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj); } -// This is a fast test on whether a reference points into the -// collection set or not. Assume that the reference -// points into the heap. inline bool G1CollectedHeap::is_in_cset(oop obj) { - bool ret = _in_cset_fast_test.is_in_cset((HeapWord*)obj); - // let's make sure the result is consistent with what the slower - // test returns - assert( ret || !obj_in_cs(obj), "sanity"); - assert(!ret || obj_in_cs(obj), "sanity"); - return ret; + return _in_cset_fast_test.is_in_cset((HeapWord*)obj); } bool G1CollectedHeap::is_in_cset(const HeapRegion* hr) { diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index bf507f20c39..6a5dedbdbda 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -2012,7 +2012,7 @@ public: guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || obj->is_oop(), "Non-oop " PTR_FORMAT ", phase: %s, info: %d", p2i(obj), _phase, _info); - guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->obj_in_cs(obj), + guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_in_cset(obj), "obj: " PTR_FORMAT " in CSet, phase: %s, info: %d", p2i(obj), _phase, _info); } diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index 34db8d6c207..054aefbdedd 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -114,7 +114,7 @@ inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { } else if (state.is_ext()) { _par_scan_state->do_oop_ext(p); } else { - assert(!_g1->obj_in_cs(obj), "checking"); + assert(!_g1->is_in_cset(obj), "checking"); } } } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index 5caeb3abaa2..11c220ab202 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -113,7 +113,7 @@ bool G1ParScanThreadState::verify_ref(oop* ref) const { if (has_partial_array_mask(ref)) { // Must be in the collection set--it's already been copied. oop p = clear_partial_array_mask(ref); - assert(_g1h->obj_in_cs(p), + assert(_g1h->is_in_cset(p), "ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)); } else { oop p = oopDesc::load_decode_heap_oop(ref); @@ -372,7 +372,7 @@ void G1ParScanThreadStateSet::flush() { } oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) { - assert(_g1h->obj_in_cs(old), "Object " PTR_FORMAT " should be in the CSet", p2i(old)); + assert(_g1h->is_in_cset(old), "Object " PTR_FORMAT " should be in the CSet", p2i(old)); oop forward_ptr = old->forward_to_atomic(old); if (forward_ptr == NULL) { @@ -394,7 +394,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) { // Forward-to-self failed. Either someone else managed to allocate // space for this object (old != forward_ptr) or they beat us in // self-forwarding it (old == forward_ptr). - assert(old == forward_ptr || !_g1h->obj_in_cs(forward_ptr), + assert(old == forward_ptr || !_g1h->is_in_cset(forward_ptr), "Object " PTR_FORMAT " forwarded to: " PTR_FORMAT " " "should not be in the CSet", p2i(old), p2i(forward_ptr)); From 8f9584260ec4d679a0bc15e391ba42a40db49d19 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 23 Feb 2017 15:59:14 -0500 Subject: [PATCH 24/86] 8166944: Hanging Error Reporting steps may lead to torn error logs Interupt error reporting if reporting steps hang to enable subsequent reporting steps to run. Reviewed-by: cjplummer, dholmes --- hotspot/src/os/posix/vm/vmError_posix.cpp | 17 ++- hotspot/src/os/windows/vm/vmError_windows.cpp | 9 +- hotspot/src/share/vm/runtime/globals.hpp | 3 + hotspot/src/share/vm/runtime/thread.cpp | 24 ++-- hotspot/src/share/vm/utilities/vmError.cpp | 132 +++++++++++++++-- hotspot/src/share/vm/utilities/vmError.hpp | 31 +++- hotspot/test/TEST.groups | 1 + .../TimeoutInErrorHandlingTest.java | 135 ++++++++++++++++++ 8 files changed, 327 insertions(+), 25 deletions(-) create mode 100644 hotspot/test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java diff --git a/hotspot/src/os/posix/vm/vmError_posix.cpp b/hotspot/src/os/posix/vm/vmError_posix.cpp index 3c61a8b41ea..26982f28256 100644 --- a/hotspot/src/os/posix/vm/vmError_posix.cpp +++ b/hotspot/src/os/posix/vm/vmError_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -59,6 +59,21 @@ static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int); static int resettedSigflags[NUM_SIGNALS]; static address resettedSighandler[NUM_SIGNALS]; +// Needed for cancelable steps. +static volatile pthread_t reporter_thread_id; + +void VMError::reporting_started() { + // record pthread id of reporter thread. + reporter_thread_id = ::pthread_self(); +} + +void VMError::interrupt_reporting_thread() { + // We misuse SIGILL here, but it does not really matter. We need + // a signal which is handled by crash_handler and not likely to + // occurr during error reporting itself. + ::pthread_kill(reporter_thread_id, SIGILL); +} + static void save_signal(int idx, int sig) { struct sigaction sa; diff --git a/hotspot/src/os/windows/vm/vmError_windows.cpp b/hotspot/src/os/windows/vm/vmError_windows.cpp index ea6821be344..4a3ddee1df4 100644 --- a/hotspot/src/os/windows/vm/vmError_windows.cpp +++ b/hotspot/src/os/windows/vm/vmError_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -66,3 +66,10 @@ void VMError::check_failing_cds_access(outputStream* st, const void* siginfo) { } } } + +// Error reporting cancellation: there is no easy way to implement this on Windows, because we do +// not have an easy way to send signals to threads (aka to cause a win32 Exception in another +// thread). We would need something like "RaiseException(HANDLE thread)"... +void VMError::reporting_started() {} +void VMError::interrupt_reporting_thread() {} + diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index a6c23d02542..317907b8bb6 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -935,6 +935,9 @@ public: notproduct(bool, TestSafeFetchInErrorHandler, false, \ "If true, tests SafeFetch inside error handler.") \ \ + notproduct(bool, TestUnresponsiveErrorHandler, false, \ + "If true, simulates an unresponsive error handler.") \ + \ develop(bool, Verbose, false, \ "Print additional debugging information from other modes") \ \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ef353659d06..9c073eb543b 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1289,28 +1289,32 @@ void WatcherThread::run() { if (is_error_reported()) { // A fatal error has happened, the error handler(VMError::report_and_die) // should abort JVM after creating an error log file. However in some - // rare cases, the error handler itself might deadlock. Here we try to - // kill JVM if the fatal error handler fails to abort in 2 minutes. - // + // rare cases, the error handler itself might deadlock. Here periodically + // check for error reporting timeouts, and if it happens, just proceed to + // abort the VM. + // This code is in WatcherThread because WatcherThread wakes up // periodically so the fatal error handler doesn't need to do anything; // also because the WatcherThread is less likely to crash than other // threads. for (;;) { - if (!ShowMessageBoxOnError - && (OnError == NULL || OnError[0] == '\0') - && Arguments::abort_hook() == NULL) { - os::sleep(this, (jlong)ErrorLogTimeout * 1000, false); // in seconds + // Note: we use naked sleep in this loop because we want to avoid using + // any kind of VM infrastructure which may be broken at this point. + if (VMError::check_timeout()) { + // We hit error reporting timeout. Error reporting was interrupted and + // will be wrapping things up now (closing files etc). Give it some more + // time, then quit the VM. + os::naked_short_sleep(200); + // Print a message to stderr. fdStream err(defaultStream::output_fd()); err.print_raw_cr("# [ timer expired, abort... ]"); // skip atexit/vm_exit/vm_abort hooks os::die(); } - // Wake up 5 seconds later, the fatal handler may reset OnError or - // ShowMessageBoxOnError when it is ready to abort. - os::sleep(this, 5 * 1000, false); + // Wait a second, then recheck for timeout. + os::naked_short_sleep(999); } } diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 8ae3d5222e3..ee8d028f97c 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -38,6 +38,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" +#include "runtime/vm_version.hpp" #include "services/memTracker.hpp" #include "trace/traceMacros.hpp" #include "utilities/debug.hpp" @@ -312,10 +313,41 @@ static void report_vm_version(outputStream* st, char* buf, int buflen) { int VMError::_current_step; const char* VMError::_current_step_info; +volatile jlong VMError::_reporting_start_time = -1; +volatile bool VMError::_reporting_did_timeout = false; +volatile jlong VMError::_step_start_time = -1; +volatile bool VMError::_step_did_timeout = false; + +// Helper, return current timestamp for timeout handling. +jlong VMError::get_current_timestamp() { + return os::javaTimeNanos(); +} +// Factor to translate the timestamp to seconds. +#define TIMESTAMP_TO_SECONDS_FACTOR (1000 * 1000 * 1000) + +void VMError::record_reporting_start_time() { + const jlong now = get_current_timestamp(); + Atomic::store(now, &_reporting_start_time); +} + +jlong VMError::get_reporting_start_time() { + return Atomic::load(&_reporting_start_time); +} + +void VMError::record_step_start_time() { + const jlong now = get_current_timestamp(); + Atomic::store(now, &_step_start_time); +} + +jlong VMError::get_step_start_time() { + return Atomic::load(&_step_start_time); +} + void VMError::report(outputStream* st, bool _verbose) { # define BEGIN if (_current_step == 0) { _current_step = __LINE__; -# define STEP(s) } if (_current_step < __LINE__) { _current_step = __LINE__; _current_step_info = s; +# define STEP(s) } if (_current_step < __LINE__) { _current_step = __LINE__; _current_step_info = s; \ + record_step_start_time(); _step_did_timeout = false; # define END } // don't allocate large buffer on stack @@ -352,6 +384,18 @@ void VMError::report(outputStream* st, bool _verbose) { controlled_crash(TestCrashInErrorHandler); } + // TestUnresponsiveErrorHandler: We want to test both step timeouts and global timeout. + // Step to global timeout ratio is 4:1, so in order to be absolutely sure we hit the + // global timeout, let's execute the timeout step five times. + // See corresponding test in test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java + #define TIMEOUT_TEST_STEP STEP("test unresponsive error reporting step") \ + if (_verbose && TestUnresponsiveErrorHandler) { os::infinite_sleep(); } + TIMEOUT_TEST_STEP + TIMEOUT_TEST_STEP + TIMEOUT_TEST_STEP + TIMEOUT_TEST_STEP + TIMEOUT_TEST_STEP + STEP("test safefetch in error handler") // test whether it is safe to use SafeFetch32 in Crash Handler. Test twice // to test that resetting the signal handler works correctly. @@ -1176,6 +1220,9 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt // first time set_error_reported(); + reporting_started(); + record_reporting_start_time(); + if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); @@ -1216,17 +1263,31 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt os::die(); } - jio_snprintf(buffer, sizeof(buffer), - "[error occurred during error reporting (%s), id 0x%x]", - _current_step_info, _id); - if (log.is_open()) { - log.cr(); - log.print_raw_cr(buffer); - log.cr(); + outputStream* const st = log.is_open() ? &log : &out; + st->cr(); + + // Timeout handling. + if (_step_did_timeout) { + // The current step had a timeout. Lets continue reporting with the next step. + st->print_raw("[timeout occurred during error reporting in step \""); + st->print_raw(_current_step_info); + st->print_cr("\"] after " INT64_FORMAT " s.", + (get_current_timestamp() - _step_start_time) / TIMESTAMP_TO_SECONDS_FACTOR); + } else if (_reporting_did_timeout) { + // We hit ErrorLogTimeout. Reporting will stop altogether. Let's wrap things + // up, the process is about to be stopped by the WatcherThread. + st->print_cr("------ Timeout during error reporting after " INT64_FORMAT " s. ------", + (get_current_timestamp() - _reporting_start_time) / TIMESTAMP_TO_SECONDS_FACTOR); + st->flush(); + // Watcherthread is about to call os::die. Lets just wait. + os::infinite_sleep(); } else { - out.cr(); - out.print_raw_cr(buffer); - out.cr(); + // Crash or assert during error reporting. Lets continue reporting with the next step. + jio_snprintf(buffer, sizeof(buffer), + "[error occurred during error reporting (%s), id 0x%x]", + _current_step_info, _id); + st->print_raw_cr(buffer); + st->cr(); } } } @@ -1421,3 +1482,50 @@ void VMError::show_message_box(char *buf, int buflen) { yes = os::start_debugging(buf,buflen); } while (yes); } + +// Timeout handling: check if a timeout happened (either a single step did +// timeout or the whole of error reporting hit ErrorLogTimeout). Interrupt +// the reporting thread if that is the case. +bool VMError::check_timeout() { + + if (ErrorLogTimeout == 0) { + return false; + } + + // Do not check for timeouts if we still have a message box to show to the + // user or if there are OnError handlers to be run. + if (ShowMessageBoxOnError + || (OnError != NULL && OnError[0] != '\0') + || Arguments::abort_hook() != NULL) { + return false; + } + + const jlong reporting_start_time_l = get_reporting_start_time(); + const jlong now = get_current_timestamp(); + // Timestamp is stored in nanos. + if (reporting_start_time_l > 0) { + const jlong end = reporting_start_time_l + (jlong)ErrorLogTimeout * TIMESTAMP_TO_SECONDS_FACTOR; + if (end <= now) { + _reporting_did_timeout = true; + interrupt_reporting_thread(); + return true; // global timeout + } + } + + const jlong step_start_time_l = get_step_start_time(); + if (step_start_time_l > 0) { + // A step times out after a quarter of the total timeout. Steps are mostly fast unless they + // hang for some reason, so this simple rule allows for three hanging step and still + // hopefully leaves time enough for the rest of the steps to finish. + const jlong end = step_start_time_l + (jlong)ErrorLogTimeout * TIMESTAMP_TO_SECONDS_FACTOR / 4; + if (end <= now) { + _step_did_timeout = true; + interrupt_reporting_thread(); + return false; // (Not a global timeout) + } + } + + return false; + +} + diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp index 23f973b27fb..3b5349e7637 100644 --- a/hotspot/src/share/vm/utilities/vmError.hpp +++ b/hotspot/src/share/vm/utilities/vmError.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -74,6 +74,16 @@ class VMError : public AllStatic { // no core/minidump has been written to disk static char coredump_message[O_BUFLEN]; + // Timeout handling: + // Timestamp at which error reporting started; -1 if no error reporting in progress. + static volatile jlong _reporting_start_time; + // Whether or not error reporting did timeout. + static volatile bool _reporting_did_timeout; + // Timestamp at which the last error reporting step started; -1 if no error reporting + // in progress. + static volatile jlong _step_start_time; + // Whether or not the last error reporting step did timeout. + static volatile bool _step_did_timeout; // set signal handlers on Solaris/Linux or the default exception filter // on Windows, to handle recursive crashes. @@ -104,6 +114,20 @@ class VMError : public AllStatic { static fdStream out; static fdStream log; // error log used by VMError::report_and_die() + // Timeout handling. + // Hook functions for platform dependend functionality: + static void reporting_started(); + static void interrupt_reporting_thread(); + + // Helper function to get the current timestamp. + static jlong get_current_timestamp(); + + // Accessors to get/set the start times for step and total timeout. + static void record_reporting_start_time(); + static jlong get_reporting_start_time(); + static void record_step_start_time(); + static jlong get_step_start_time(); + public: // return a string to describe the error @@ -147,6 +171,11 @@ public: static bool fatal_error_in_progress() { return first_error_tid != -1; } static intptr_t get_first_error_tid() { return first_error_tid; } + + // Called by the WatcherThread to check if error reporting has timed-out. + // Returns true if error reporting has not completed within the ErrorLogTimeout limit. + static bool check_timeout(); + }; #endif // SHARE_VM_UTILITIES_VMERROR_HPP diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 8953467a9b2..f3a0d90a291 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -371,6 +371,7 @@ hotspot_fast_runtime = \ -runtime/ConstantPool/IntfMethod.java \ -runtime/ErrorHandling/CreateCoredumpOnCrash.java \ -runtime/ErrorHandling/ErrorHandler.java \ + -runtime/ErrorHandling/TimeoutInErrorHandlingTest.java \ -runtime/logging/MonitorMismatchTest.java \ -runtime/memory/ReserveMemory.java \ -runtime/memory/RunUnitTestsConcurrently.java \ diff --git a/hotspot/test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java b/hotspot/test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java new file mode 100644 index 00000000000..91c306237f7 --- /dev/null +++ b/hotspot/test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8166944 + * @summary Hanging Error Reporting steps may lead to torn error logs + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @requires (vm.debug == true) & (os.family != "windows") + * @author Thomas Stuefe (SAP) + */ + +public class TimeoutInErrorHandlingTest { + + + public static void main(String[] args) throws Exception { + + /* Start the VM and let it crash. Specify TestUnresponsiveErrorHandler which will + * let five subsequent error reporting steps hang. The Timeout handling triggered + * by the WatcherThread should kick in and interrupt those steps. In theory, the + * text "timeout occurred during error reporting in step .." (the little timeouts) + * should occur in the error log up to four times, followed by the final big timeout + * "------ Timeout during error reporting after xx s. ------" + * + * Note that there are a number of uncertainties which make writing a 100% foolproof + * test challenging. The time the error reporting thread takes to react to the + * timeout triggers is unknown. So it is difficult to predict how many little timeouts + * will be visible before the big timeout kicks in. Also, once the big timeout hits, + * error reporting thread and Watcherthread will race. The former writes his last + * message to the error logs and flushes, the latter waits 200ms and then exits the + * process without further synchronization with the error reporting thread. + * + * Because of all this and the desire to write a bullet proof test which does + * not fail sporadically, we will not test for the final timeout message nor for all + * of the optimally expected little timeout messages. We just test for two of the + * little timeout messages to see that repeated timeout handling is basically working. + */ + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx100M", + "-XX:ErrorHandlerTest=14", + "-XX:+TestUnresponsiveErrorHandler", + "-XX:ErrorLogTimeout=16", // 16 seconds big timeout = 4 seconds per little timeout + "-XX:-CreateCoredumpOnCrash", + "-version"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // we should have crashed with a SIGSEGV + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*"); + + // VM should have been aborted by WatcherThread + output_detail.shouldMatch(".*timer expired, abort.*"); + + // extract hs-err file + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs-err file in output.\n"); + } + + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs-err file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + + + Pattern [] pattern = new Pattern[] { + Pattern.compile(".*timeout occurred during error reporting in step.*"), + Pattern.compile(".*timeout occurred during error reporting in step.*") + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern ++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs-err file incomplete (first missing pattern: " + currentPattern + ")"); + } + + System.out.println("OK."); + + } + +} + From ae38e65467fb7819b65901774059780ab0504e12 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Fri, 24 Feb 2017 10:41:56 +0100 Subject: [PATCH 25/86] 8173764: G1 BOT wrongly assumes that objects must always begin at the start of G1BlockOffsetTablePart Reviewed-by: tschatzl, kbarrett --- hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp | 12 ++++++++++-- hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp | 6 +++++- .../src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp | 6 ++++-- hotspot/src/share/vm/gc/g1/heapRegion.cpp | 6 +++++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp index 435bd5a6116..c0e6a480ac8 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -79,7 +79,9 @@ G1BlockOffsetTablePart::G1BlockOffsetTablePart(G1BlockOffsetTable* array, G1Cont _space(gsp), _next_offset_threshold(NULL), _next_offset_index(0) -{ } +{ + debug_only(_object_can_span = false;) +} // The arguments follow the normal convention of denoting // a right-open interval: [start, end) @@ -364,6 +366,12 @@ void G1BlockOffsetTablePart::verify() const { } } +#ifdef ASSERT +void G1BlockOffsetTablePart::set_object_can_span(bool can_span) { + _object_can_span = can_span; +} +#endif + #ifndef PRODUCT void G1BlockOffsetTablePart::print_on(outputStream* out) { diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp index 8ee1e6d8b56..40df9ad5fc1 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -117,6 +117,9 @@ private: HeapWord* _next_offset_threshold; size_t _next_offset_index; // index corresponding to that boundary + // Indicates if an object can span into this G1BlockOffsetTablePart. + debug_only(bool _object_can_span;) + // This is the global BlockOffsetTable. G1BlockOffsetTable* _bot; @@ -224,6 +227,7 @@ public: } void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size); + void set_object_can_span(bool can_span) NOT_DEBUG_RETURN; void print_on(outputStream* out) PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp index 9788eed0bfe..d845c02c36c 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -107,7 +107,9 @@ inline size_t G1BlockOffsetTablePart::block_size(const HeapWord* p) const { inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr, bool has_max_index, size_t max_index) const { - assert(_bot->offset_array(0) == 0, "objects can't cross covered areas"); + assert(_object_can_span || _bot->offset_array(_bot->index_for(_space->bottom())) == 0, + "Object crossed region boundary, found offset %u instead of 0", + (uint) _bot->offset_array(_bot->index_for(_space->bottom()))); size_t index = _bot->index_for(addr); // We must make sure that the offset table entry we use is valid. If // "addr" is past the end, start at the last known one and go forward. diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 2bd451fc700..38273660b62 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -267,6 +267,8 @@ void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous); _type.set_continues_humongous(); _humongous_start_region = first_hr; + + _bot_part.set_object_can_span(true); } void HeapRegion::clear_humongous() { @@ -274,6 +276,8 @@ void HeapRegion::clear_humongous() { assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_start_region = NULL; + + _bot_part.set_object_can_span(false); } HeapRegion::HeapRegion(uint hrm_index, From 52ad33bebba56cd5415bc4e46cde942d3ed7f8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rickard=20B=C3=A4ckman?= Date: Fri, 24 Feb 2017 13:48:16 +0100 Subject: [PATCH 26/86] 8175815: Quarantine AOT tests on windows Reviewed-by: thartmann --- hotspot/test/ProblemList.txt | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/hotspot/test/ProblemList.txt b/hotspot/test/ProblemList.txt index 907597bd228..191b59f08dc 100644 --- a/hotspot/test/ProblemList.txt +++ b/hotspot/test/ProblemList.txt @@ -49,6 +49,64 @@ compiler/tiered/LevelTransitionTest.java 8067651 generic-all compiler/types/correctness/CorrectnessTest.java 8066173 generic-all compiler/types/correctness/OffTest.java 8066173 generic-all +# aot tests intermittently failing in jprt 8175791 + +compiler/aot/RecompilationTest.java 8175791 windows-all +compiler/aot/SharedUsageTest.java 8175791 windows-all +compiler/aot/cli/MultipleAOTLibraryTest.java 8175791 windows-all +compiler/aot/cli/DisabledAOTWithLibraryTest.java 8175791 windows-all +compiler/aot/cli/SingleAOTLibraryTest.java 8175791 windows-all +compiler/aot/cli/NonExistingAOTLibraryTest.java 8175791 windows-all +compiler/aot/cli/SingleAOTOptionTest.java 8175791 windows-all +compiler/aot/cli/jaotc/ClasspathOptionTest.java 8175791 windows-all +compiler/aot/cli/jaotc/ListOptionTest.java 8175791 windows-all +compiler/aot/cli/jaotc/CompileModuleTest.java 8175791 windows-all +compiler/aot/cli/jaotc/CompileClassTest.java 8175791 windows-all +compiler/aot/cli/jaotc/CompileJarTest.java 8175791 windows-all +compiler/aot/cli/jaotc/ListOptionWrongFileTest.java 8175791 windows-all +compiler/aot/cli/jaotc/CompileDirectoryTest.java 8175791 windows-all +compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java 8175791 windows-all +compiler/aot/cli/jaotc/ListOptionNotExistingTest.java 8175791 windows-all +compiler/aot/cli/IncorrectAOTLibraryTest.java 8175791 windows-all +compiler/aot/verification/vmflags/TrackedFlagTest.java 8175791 windows-all +compiler/aot/verification/vmflags/NotTrackedFlagTest.java 8175791 windows-all +compiler/aot/verification/ClassAndLibraryNotMatchTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java 8175791 windows-all +compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java 8175791 windows-all +compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java 8175791 windows-all +compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java 8175791 windows-all +compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java 8175791 windows-all +compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java 8175791 windows-all +compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java 8175791 windows-all +compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java 8175791 windows-all +compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java 8175791 windows-all +compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java 8175791 windows-all +compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java 8175791 windows-all +compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java 8175791 windows-all +compiler/aot/DeoptimizationTest.java 8175791 windows-all + + ############################################################################# # :hotspot_gc From 725e1cfafe54f5b8195fc6d64ca127ab70ee0392 Mon Sep 17 00:00:00 2001 From: Alexander Harlap Date: Thu, 23 Feb 2017 12:50:49 -0500 Subject: [PATCH 27/86] 8151045: Remove code duplication in PLABStats/G1EvacStats::adjust_desired_plab_sz Move class specific code to the helper method Reviewed-by: kbarrett, tschatzl --- hotspot/src/share/vm/gc/g1/g1EvacStats.cpp | 34 ++--------------- hotspot/src/share/vm/gc/g1/g1EvacStats.hpp | 6 +-- hotspot/src/share/vm/gc/shared/plab.cpp | 43 ++++++++++++---------- hotspot/src/share/vm/gc/shared/plab.hpp | 8 +++- 4 files changed, 35 insertions(+), 56 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp index 2b6c3917800..bdfef475ddf 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -46,29 +46,7 @@ void G1EvacStats::log_plab_allocation() { _failure_waste * HeapWordSize); } -void G1EvacStats::adjust_desired_plab_sz() { - log_plab_allocation(); - - if (!ResizePLAB) { - // Clear accumulators for next round. - reset(); - return; - } - - assert(is_object_aligned(max_size()) && min_size() <= max_size(), - "PLAB clipping computation may be incorrect"); - - if (_allocated == 0) { - assert((_unused == 0), - "Inconsistency in PLAB stats: " - "_allocated: " SIZE_FORMAT ", " - "_wasted: " SIZE_FORMAT ", " - "_region_end_waste: " SIZE_FORMAT ", " - "_unused: " SIZE_FORMAT ", " - "_used : " SIZE_FORMAT, - _allocated, _wasted, _region_end_waste, _unused, used()); - _allocated = 1; - } +size_t G1EvacStats::compute_desired_plab_sz() { // The size of the PLAB caps the amount of space that can be wasted at the // end of the collection. In the worst case the last PLAB could be completely // empty. @@ -109,13 +87,7 @@ void G1EvacStats::adjust_desired_plab_sz() { size_t const total_waste_allowed = used_for_waste_calculation * TargetPLABWastePct; size_t const cur_plab_sz = (size_t)((double)total_waste_allowed / G1LastPLABAverageOccupancy); - // Take historical weighted average - _filter.sample(cur_plab_sz); - _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average()); - - log_sizing(cur_plab_sz, _desired_net_plab_sz); - // Clear accumulators for next round. - reset(); + return cur_plab_sz; } G1EvacStats::G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt) : diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp index b322593e7ea..4ac6fd9f563 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,13 +53,13 @@ class G1EvacStats : public PLABStats { virtual void log_plab_allocation(); + virtual size_t compute_desired_plab_sz(); + public: G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt); ~G1EvacStats(); - virtual void adjust_desired_plab_sz(); - uint regions_filled() const { return _regions_filled; } size_t region_end_waste() const { return _region_end_waste; } size_t direct_allocated() const { return _direct_allocated; } diff --git a/hotspot/src/share/vm/gc/shared/plab.cpp b/hotspot/src/share/vm/gc/shared/plab.cpp index b95260d7f12..6cf1a7cfb27 100644 --- a/hotspot/src/share/vm/gc/shared/plab.cpp +++ b/hotspot/src/share/vm/gc/shared/plab.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -154,30 +154,33 @@ void PLABStats::adjust_desired_plab_sz() { assert(is_object_aligned(max_size()) && min_size() <= max_size(), "PLAB clipping computation may be incorrect"); - if (_allocated == 0) { - assert(_unused == 0, - "Inconsistency in PLAB stats: " - "_allocated: " SIZE_FORMAT ", " - "_wasted: " SIZE_FORMAT ", " - "_unused: " SIZE_FORMAT ", " - "_undo_wasted: " SIZE_FORMAT, - _allocated, _wasted, _unused, _undo_wasted); + assert(_allocated != 0 || _unused == 0, + "Inconsistency in PLAB stats: " + "_allocated: " SIZE_FORMAT ", " + "_wasted: " SIZE_FORMAT ", " + "_unused: " SIZE_FORMAT ", " + "_undo_wasted: " SIZE_FORMAT, + _allocated, _wasted, _unused, _undo_wasted); - _allocated = 1; - } - double wasted_frac = (double)_unused / (double)_allocated; + size_t plab_sz = compute_desired_plab_sz(); + // Take historical weighted average + _filter.sample(plab_sz); + _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average()); + + log_sizing(plab_sz, _desired_net_plab_sz); + // Clear accumulators for next round + reset(); +} + +size_t PLABStats::compute_desired_plab_sz() { + size_t allocated = MAX2(_allocated, size_t(1)); + double wasted_frac = (double)_unused / (double)allocated; size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct); if (target_refills == 0) { target_refills = 1; } - size_t used = _allocated - _wasted - _unused; + size_t used = allocated - _wasted - _unused; // Assumed to have 1 gc worker thread size_t recent_plab_sz = used / target_refills; - // Take historical weighted average - _filter.sample(recent_plab_sz); - _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average()); - - log_sizing(recent_plab_sz, _desired_net_plab_sz); - - reset(); + return recent_plab_sz; } diff --git a/hotspot/src/share/vm/gc/shared/plab.hpp b/hotspot/src/share/vm/gc/shared/plab.hpp index e73562b301f..0f1bf4ebdb0 100644 --- a/hotspot/src/share/vm/gc/shared/plab.hpp +++ b/hotspot/src/share/vm/gc/shared/plab.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -165,6 +165,10 @@ class PLABStats : public CHeapObj { virtual void log_plab_allocation(); virtual void log_sizing(size_t calculated, size_t net_desired); + + // helper for adjust_desired_plab_sz(). + virtual size_t compute_desired_plab_sz(); + public: PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) : _description(description), @@ -197,7 +201,7 @@ class PLABStats : public CHeapObj { // Updates the current desired PLAB size. Computes the new desired PLAB size with one gc worker thread, // updates _desired_plab_sz and clears sensor accumulators. - virtual void adjust_desired_plab_sz(); + void adjust_desired_plab_sz(); inline void add_allocated(size_t v); From 68fa501522b71b9452f8c3136210c136ec60e124 Mon Sep 17 00:00:00 2001 From: Joseph Provino Date: Mon, 27 Feb 2017 12:41:41 -0500 Subject: [PATCH 28/86] 8168038: Some methods in G1RemSet are virtual unnecessarily G1RemSet has a number of virtual functions, yet is derived from CHeapObj and has no subclasses. Reviewed-by: kbarrett, tschatzl --- hotspot/src/share/vm/gc/g1/g1RemSet.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp index 561b3cfe072..bcd75c2e3ab 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -149,18 +149,18 @@ public: // If oops_in_heap_closure is not NULL, a true result is returned // if the given card contains oops that have references into the // current collection set. - virtual bool refine_card(jbyte* card_ptr, - uint worker_i, - G1ParPushHeapRSClosure* oops_in_heap_closure); + bool refine_card(jbyte* card_ptr, + uint worker_i, + G1ParPushHeapRSClosure* oops_in_heap_closure); // Print accumulated summary info from the start of the VM. - virtual void print_summary_info(); + void print_summary_info(); // Print accumulated summary info from the last time called. - virtual void print_periodic_summary_info(const char* header, uint period_count); + void print_periodic_summary_info(const char* header, uint period_count); // Prepare remembered set for verification. - virtual void prepare_for_verify(); + void prepare_for_verify(); size_t conc_refine_cards() const { return _conc_refine_cards; From 0a19790e657728aeb2cb870041e3da70700f4420 Mon Sep 17 00:00:00 2001 From: Shafi Ahmad Date: Thu, 16 Feb 2017 00:50:19 -0800 Subject: [PATCH 29/86] 8167423: Adding return value check and updating index variable Reviewed-by: dholmes, coleenp --- hotspot/src/share/vm/runtime/java.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index f156c698caf..5f3f2c1ac5b 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -719,6 +719,8 @@ void JDK_Version::to_string(char* buffer, size_t buflen) const { index += rc; if (_security > 0) { rc = jio_snprintf(&buffer[index], buflen - index, ".%d", _security); + if (rc == -1) return; + index += rc; } if (_patch > 0) { rc = jio_snprintf(&buffer[index], buflen - index, ".%d", _patch); From 3b086bdbbb6bee48c840d45edbecbe91f0a02d02 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 28 Feb 2017 10:51:47 -0800 Subject: [PATCH 30/86] 8172020: Internal Error (cpu/arm/vm/frame_arm.cpp:571): assert(obj == __null || Universe::heap()->is_in(obj)) failed: sanity check # Do check_and_handle_earlyret() on method return Reviewed-by: sspitsyn, aph, adinn, simonis --- hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp | 8 ++++---- .../src/cpu/aarch64/vm/macroAssembler_aarch64.hpp | 14 +++++++------- .../vm/templateInterpreterGenerator_aarch64.cpp | 6 +++++- hotspot/src/cpu/arm/vm/interp_masm_arm.hpp | 8 ++++---- hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp | 9 ++++----- .../arm/vm/templateInterpreterGenerator_arm.cpp | 5 ++++- hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp | 4 ++-- .../ppc/vm/templateInterpreterGenerator_ppc.cpp | 6 +++++- hotspot/src/cpu/s390/vm/interp_masm_s390.hpp | 8 ++++---- .../s390/vm/templateInterpreterGenerator_s390.cpp | 6 +++++- hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp | 8 ++++---- hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp | 8 ++++---- .../vm/templateInterpreterGenerator_sparc.cpp | 6 +++++- hotspot/src/cpu/x86/vm/interp_masm_x86.hpp | 8 ++++---- hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 14 +++++++------- .../x86/vm/templateInterpreterGenerator_x86.cpp | 13 ++++++++++++- 16 files changed, 80 insertions(+), 51 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp index 925690b0d80..b61278beee4 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -54,9 +54,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -67,6 +64,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Interpreter-specific registers void save_bcp() { str(rbcp, Address(rfp, frame::interpreter_frame_bcp_offset * wordSize)); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 2f17699a262..f11371f24b2 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -77,12 +77,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // Maximum size of class area in Metaspace when compressed @@ -97,6 +91,12 @@ class MacroAssembler: public Assembler { > (1u << log2_intptr(CompressedClassSpaceSize)))); } + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Biased locking support // lock_reg and obj_reg must be loaded up with the appropriate values. // swap_reg is killed. diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index 0a4c7035c8a..098cbba9946 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -436,6 +436,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ notify(Assembler::method_reentry); } #endif + + __ check_and_handle_popframe(rthread); + __ check_and_handle_earlyret(rthread); + __ get_dispatch(); __ dispatch_next(state, step); diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp index 5c753753f95..43f0d54edc4 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,9 +53,6 @@ class InterpreterMacroAssembler: public MacroAssembler { // Template interpreter specific version of call_VM_helper virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(); - virtual void check_and_handle_earlyret(); - // base routine for all dispatches typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode; void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true); @@ -63,6 +60,9 @@ class InterpreterMacroAssembler: public MacroAssembler { public: InterpreterMacroAssembler(CodeBuffer* code); + virtual void check_and_handle_popframe(); + virtual void check_and_handle_earlyret(); + // Interpreter-specific registers #if defined(AARCH64) && defined(ASSERT) diff --git a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp index 770bba6c8a1..c048b10e59e 100644 --- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp +++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -206,6 +206,9 @@ protected: // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); +public: + + MacroAssembler(CodeBuffer* code) : Assembler(code) {} // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, @@ -213,10 +216,6 @@ protected: virtual void check_and_handle_popframe() {} virtual void check_and_handle_earlyret() {} -public: - - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // By default, we do not need relocation information for non // patchable absolute addresses. However, when needed by some // extensions, ignore_non_patchable_relocations can be modified, diff --git a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp index 036ae4cc7d8..aab1fb0aec0 100644 --- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -304,6 +304,9 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ convert_retval_to_tos(state); #endif // !AARCH64 + __ check_and_handle_popframe(); + __ check_and_handle_earlyret(); + __ dispatch_next(state, step); return entry; diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp index d2085ea4e78..4d127857426 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp @@ -45,8 +45,8 @@ class InterpreterMacroAssembler: public MacroAssembler { #define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread #define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); // Base routine for all dispatches. void dispatch_base(TosState state, address* table); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index cccc1bca650..7a0274d6156 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -689,6 +689,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, #endif __ sldi(size, size, Interpreter::logStackElementSize); __ add(R15_esp, R15_esp, size); + + __ check_and_handle_popframe(R11_scratch1); + __ check_and_handle_earlyret(R11_scratch1); + __ dispatch_next(state, step); return entry; } diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp index 5f29a606481..2c5d784477d 100644 --- a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp +++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool allow_relocation, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // Base routine for all dispatches. void dispatch_base(TosState state, address* table); @@ -58,6 +55,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void jump_to_entry(address entry, Register Rscratch); virtual void load_earlyret_value(TosState state); diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp index b773fa20ad2..e4f74df51e3 100644 --- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -676,6 +676,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, __ z_llgc(size, Address(cache, offset, flags_offset+(sizeof(size_t)-1))); __ z_sllg(size, size, Interpreter::logStackElementSize); // Each argument size in bytes. __ z_agr(Z_esp, size); // Pop arguments. + + __ check_and_handle_popframe(Z_thread); + __ check_and_handle_earlyret(Z_thread); + __ dispatch_next(state, step); BLOCK_COMMENT("} return_entry"); diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 1baceb1233c..d78ee494ce0 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,9 +70,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exception=true ); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table); @@ -80,6 +77,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); + void jump_to_entry(address entry); virtual void load_earlyret_value(TosState state); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index a401859e774..a17fd6db740 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -604,15 +604,15 @@ class MacroAssembler : public Assembler { bool check_exception=true // flag which indicates if exception should be checked ); + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, // as only the interpreter handles and ForceEarlyReturn PopFrame requests. virtual void check_and_handle_popframe(Register scratch_reg); virtual void check_and_handle_earlyret(Register scratch_reg); - public: - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index c3645539903..2046813d2bf 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -374,6 +374,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words __ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes __ add(Lesp, parameter_size, Lesp); // pop arguments + + __ check_and_handle_popframe(Gtemp); + __ check_and_handle_earlyret(Gtemp); + __ dispatch_next(state, step); return entry; diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 9ed5c2c9ad3..8419c97eb1c 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -61,6 +58,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void load_earlyret_value(TosState state); // Interpreter-specific registers diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index a3e81e58dc5..2443e6fb302 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -71,12 +71,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // helpers for FPU flag access @@ -87,6 +81,12 @@ class MacroAssembler: public Assembler { public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp index d9a5a1c9b1a..42639c0e1c2 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,6 +220,17 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); + + const Register java_thread = NOT_LP64(rcx) LP64_ONLY(r15_thread); + if (JvmtiExport::can_pop_frame()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_popframe(java_thread); + } + if (JvmtiExport::can_force_early_return()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_earlyret(java_thread); + } + __ dispatch_next(state, step); return entry; From 90c3e97cbd89b84252d7838f7269056f2bde8c85 Mon Sep 17 00:00:00 2001 From: Shafi Ahmad Date: Tue, 28 Feb 2017 20:32:06 -0800 Subject: [PATCH 31/86] 8171194: Exception "Duplicate field name&signature in class file" should report the name and signature of the field Added code to emit name and signature of duplicate field in java.lang.ClassFormatError exception message Reviewed-by: dholmes, coleenp --- .../src/share/vm/classfile/classFileError.cpp | 10 +++++++ .../share/vm/classfile/classFileParser.cpp | 26 ++++++++++++------- .../share/vm/classfile/classFileParser.hpp | 4 +++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileError.cpp b/hotspot/src/share/vm/classfile/classFileError.cpp index c3cde1a5436..f44588efbc4 100644 --- a/hotspot/src/share/vm/classfile/classFileError.cpp +++ b/hotspot/src/share/vm/classfile/classFileError.cpp @@ -68,6 +68,16 @@ void ClassFileParser::classfile_parse_error(const char* msg, msg, index, name, _class_name->as_C_string()); } +void ClassFileParser::classfile_parse_error(const char* msg, + const char* name, + const char* signature, + TRAPS) const { + assert(_class_name != NULL, "invariant"); + ResourceMark rm(THREAD); + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), + msg, name, signature, _class_name->as_C_string()); +} + PRAGMA_DIAG_POP void StackMapStream::stackmap_format_error(const char* msg, TRAPS) { diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index ae36e921723..2b20e83c911 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -863,11 +863,12 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, HASH_ROW_SIZE); initialize_hashtable(interface_names); bool dup = false; + const Symbol* name = NULL; { debug_only(NoSafepointVerifier nsv;) for (index = 0; index < itfs_len; index++) { const Klass* const k = _local_interfaces->at(index); - const Symbol* const name = InstanceKlass::cast(k)->name(); + name = InstanceKlass::cast(k)->name(); // If no duplicates, add (name, NULL) in hashtable interface_names. if (!put_after_lookup(name, NULL, interface_names)) { dup = true; @@ -876,7 +877,8 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, } } if (dup) { - classfile_parse_error("Duplicate interface name in class file %s", CHECK); + classfile_parse_error("Duplicate interface name \"%s\" in class file %s", + name->as_C_string(), CHECK); } } } @@ -1628,11 +1630,13 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs, THREAD, NameSigHash*, HASH_ROW_SIZE); initialize_hashtable(names_and_sigs); bool dup = false; + const Symbol* name = NULL; + const Symbol* sig = NULL; { debug_only(NoSafepointVerifier nsv;) for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) { - const Symbol* const name = fs.name(); - const Symbol* const sig = fs.signature(); + name = fs.name(); + sig = fs.signature(); // If no duplicates, add name/signature in hashtable names_and_sigs. if (!put_after_lookup(name, sig, names_and_sigs)) { dup = true; @@ -1641,8 +1645,8 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs, } } if (dup) { - classfile_parse_error("Duplicate field name&signature in class file %s", - CHECK); + classfile_parse_error("Duplicate field name \"%s\" with signature \"%s\" in class file %s", + name->as_C_string(), sig->as_klass_external_name(), CHECK); } } } @@ -2884,20 +2888,24 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs, THREAD, NameSigHash*, HASH_ROW_SIZE); initialize_hashtable(names_and_sigs); bool dup = false; + const Symbol* name = NULL; + const Symbol* sig = NULL; { debug_only(NoSafepointVerifier nsv;) for (int i = 0; i < length; i++) { const Method* const m = _methods->at(i); + name = m->name(); + sig = m->signature(); // If no duplicates, add name/signature in hashtable names_and_sigs. - if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) { + if (!put_after_lookup(name, sig, names_and_sigs)) { dup = true; break; } } } if (dup) { - classfile_parse_error("Duplicate method name&signature in class file %s", - CHECK); + classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s", + name->as_C_string(), sig->as_klass_external_name(), CHECK); } } } diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index df9ff6848ab..84e23247486 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -301,6 +301,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { int index, const char *name, TRAPS) const; + void classfile_parse_error(const char* msg, + const char* name, + const char* signature, + TRAPS) const; inline void guarantee_property(bool b, const char* msg, TRAPS) const { if (!b) { classfile_parse_error(msg, CHECK); } From 5485a03844c23cc9c8796c059eba90bc75bc52ad Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 1 Mar 2017 07:59:20 -0500 Subject: [PATCH 32/86] 8172307: Remove ununsed JVM API JVM_GetModuleByPackageName() Remove get_module_by_package_name() etc., and unneeded test. Reviewed-by: sspitsyn, gtriantafill --- hotspot/src/share/vm/classfile/modules.cpp | 33 ------- hotspot/src/share/vm/classfile/modules.hpp | 3 +- hotspot/src/share/vm/prims/whitebox.cpp | 11 --- .../modules/JVMGetModuleByPkgName.java | 91 ------------------- .../test/runtime/modules/ModuleHelper.java | 7 +- 5 files changed, 2 insertions(+), 143 deletions(-) delete mode 100644 hotspot/test/runtime/modules/JVMGetModuleByPkgName.java diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp index a0d3b9bdfda..0dbe2fd3cef 100644 --- a/hotspot/src/share/vm/classfile/modules.cpp +++ b/hotspot/src/share/vm/classfile/modules.cpp @@ -649,39 +649,6 @@ jobject Modules::get_module(jclass clazz, TRAPS) { return JNIHandles::make_local(THREAD, module); } - -jobject Modules::get_module_by_package_name(jobject loader, const char* package_name, TRAPS) { - ResourceMark rm(THREAD); - assert(ModuleEntryTable::javabase_defined(), - "Attempt to call get_module_from_pkg before " JAVA_BASE_NAME " is defined"); - - if (package_name == NULL) { - THROW_MSG_(vmSymbols::java_lang_NullPointerException(), - "package is null", JNI_FALSE); - } - - Handle h_loader (THREAD, JNIHandles::resolve(loader)); - // Check that loader is a subclass of java.lang.ClassLoader. - if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) { - THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), - "Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE); - } - - if (strlen(package_name) == 0) { - // Return the unnamed module - ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL); - if (NULL == module_table) return NULL; - const ModuleEntry* const unnamed_module = module_table->unnamed_module(); - return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module())); - - } else { - TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL); - return get_module(package_sym, h_loader, CHECK_NULL); - } - return NULL; -} - - jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) { assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_named_module before " JAVA_BASE_NAME " is defined"); diff --git a/hotspot/src/share/vm/classfile/modules.hpp b/hotspot/src/share/vm/classfile/modules.hpp index 4f5e089a065..1759b9338fc 100644 --- a/hotspot/src/share/vm/classfile/modules.hpp +++ b/hotspot/src/share/vm/classfile/modules.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,6 @@ public: // NullPointerException is thrown if package is null. // IllegalArgumentException is thrown if loader is neither null nor a subtype of // java/lang/ClassLoader. - static jobject get_module_by_package_name(jobject loader, const char* package, TRAPS); static jobject get_named_module(Handle h_loader, const char* package, TRAPS); // If package is defined by loader, return the diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index f780d131c38..35f0f607f2d 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -1466,15 +1466,6 @@ WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstrin Modules::add_module_package(module, package_name, CHECK); WB_END -WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package)) - ResourceMark rm(THREAD); - char* package_name = NULL; - if (package != NULL) { - package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package)); - } - return Modules::get_module_by_package_name(loader, package_name, THREAD); -WB_END - WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc)) if (inc < 0) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), @@ -1912,8 +1903,6 @@ static JNINativeMethod methods[] = { (void*)&WB_AddReadsModule }, {CC"AddModulePackage", CC"(Ljava/lang/Object;Ljava/lang/String;)V", (void*)&WB_AddModulePackage }, - {CC"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", - (void*)&WB_GetModuleByPackageName }, {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V", (void*)&WB_AddModuleExportsToAllUnnamed }, {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V", diff --git a/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java b/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java deleted file mode 100644 index ce94bb19536..00000000000 --- a/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @modules java.base/jdk.internal.misc - * @library /test/lib .. - * @compile p2/c2.java - * @build sun.hotspot.WhiteBox - * @compile/module=java.base java/lang/reflect/ModuleHelper.java - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI JVMGetModuleByPkgName - */ - -import static jdk.test.lib.Asserts.*; -import java.lang.ClassLoader; -import java.lang.reflect.Module; - -public class JVMGetModuleByPkgName { - - public static void main(String args[]) throws Throwable { - - Module javaBase = ModuleHelper.GetModuleByPackageName(null, "java/lang"); - if (!javaBase.getName().equals("java.base")) { - throw new RuntimeException( - "Failed to get module java.base for package java/lang"); - } - - if (ModuleHelper.GetModuleByPackageName(null, "bad.package.name") != null) { - throw new RuntimeException("Failed to get null for bad.package.name"); - } - - ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); - if (ModuleHelper.GetModuleByPackageName(systemLoader, "java/lang") != null) { - throw new RuntimeException( - "Failed to get null for systemClassLoader and java/lang"); - } - - try { - ModuleHelper.GetModuleByPackageName(systemLoader, null); - throw new RuntimeException( - "Failed to throw NullPointerException for null package name"); - } catch(NullPointerException e) { - // Expected - } - - Module unnamedModule = ModuleHelper.GetModuleByPackageName(systemLoader, ""); - if (unnamedModule.isNamed()) { - throw new RuntimeException( - "Unexpected named module returned for unnamed package"); - } - - p2.c2 obj = new p2.c2(); - unnamedModule = ModuleHelper.GetModuleByPackageName(systemLoader, "p2"); - if (unnamedModule.isNamed()) { - throw new RuntimeException( - "Unexpected named module returned for package p2 in unnamed module"); - } - - MyClassLoader cl1 = new MyClassLoader(); - Module module_one = (Module)ModuleHelper.ModuleObject("module_one", cl1, new String[] { "mypackage" }); - assertNotNull(module_one, "Module should not be null"); - ModuleHelper.DefineModule(module_one, "9.0", "module_one/here", new String[] { "mypackage" }); - if (ModuleHelper.GetModuleByPackageName(cl1, "mypackage") != module_one) { - throw new RuntimeException("Wrong module returned for cl1 mypackage"); - } - } - - static class MyClassLoader extends ClassLoader { } -} diff --git a/hotspot/test/runtime/modules/ModuleHelper.java b/hotspot/test/runtime/modules/ModuleHelper.java index 26febc2a75e..dff21f41eca 100644 --- a/hotspot/test/runtime/modules/ModuleHelper.java +++ b/hotspot/test/runtime/modules/ModuleHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -56,11 +56,6 @@ public class ModuleHelper { java.lang.reflect.ModuleHelper.addPackageNoSync((Module)m, pkg); } - public static Module GetModuleByPackageName(Object ldr, String pkg) throws Throwable { - WhiteBox wb = WhiteBox.getWhiteBox(); - return (Module)wb.GetModuleByPackageName(ldr, pkg); - } - public static void AddModuleExportsToAllUnnamed(Object m, String pkg) throws Throwable { WhiteBox wb = WhiteBox.getWhiteBox(); wb.AddModuleExportsToAllUnnamed(m, pkg); From a09caaa6ffcdacdaa5e36ba368b8023b8fe9903e Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Wed, 1 Mar 2017 08:11:29 -0500 Subject: [PATCH 33/86] 8176012: Remove unused groups in hotspot/test/TEST.groups Reviewed-by: iignatyev, gtriantafill --- hotspot/test/TEST.groups | 238 --------------------------------------- 1 file changed, 238 deletions(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index f3a0d90a291..724ed0c9b7c 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -21,35 +21,6 @@ # questions. # -# Profile-based Test Group Definitions -# -# These groups define the tests that cover the different possible runtimes: -# - compact1, compact2, compact3, full JRE, JDK -# -# In addition they support testing of the minimal VM on compact1 and compact2. -# Essentially this defines groups based around the specified API's and VM -# services available in the runtime. -# -# The groups are defined hierarchically in two forms: -# - The need_xxx groups list all the tests that have a dependency on -# a specific profile. This is either because it tests a feature in -# that profile, or the test infrastructure uses a feature in that -# profile. -# - The primary groups are defined in terms of the other primary groups -# combined with the needs_xxx groups (including and excluding them as -# appropriate). For example the jre can run all tests from compact3, plus -# those from needs_jre, but excluding those from need_jdk. -# -# The bottom group defines all the actual tests to be considered, simply -# by listing the top-level test directories. -# -# To use a group simply list it on the jtreg command line eg: -# jtreg :jdk -# runs all tests. While -# jtreg :compact2 -# runs those tests that only require compact1 and compact2 API's. -# - hotspot_all = \ / @@ -72,201 +43,6 @@ hotspot_misc = \ -:hotspot_runtime \ -:hotspot_serviceability -# Full JDK can run all tests -# -jdk = \ - :jre \ - :needs_jdk - -# Tests that require a full JDK to execute. Either they test a feature -# only in the JDK or they use tools that are only in the JDK. The latter -# can be resolved in some cases by using tools from the compile-jdk. -# -needs_jdk = \ - compiler/aot \ - gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \ - gc/metaspace/TestMetaspacePerfCounters.java \ - gc/metaspace/TestPerfCountersAndMemoryPools.java \ - runtime/6819213/TestBootNativeLibraryPath.java \ - runtime/7158988/FieldMonitor.java \ - runtime/Metaspace/FragmentMetaspace.java \ - runtime/NMT/BaselineWithParameter.java \ - runtime/NMT/JcmdBaselineDetail.java \ - runtime/NMT/JcmdDetailDiff.java \ - runtime/NMT/JcmdScaleDetail.java \ - runtime/NMT/JcmdScale.java \ - runtime/NMT/JcmdSummaryDiff.java \ - runtime/NMT/JcmdWithNMTDisabled.java \ - runtime/NMT/MallocRoundingReportTest.java \ - runtime/NMT/MallocSiteHashOverflow.java \ - runtime/NMT/MallocStressTest.java \ - runtime/NMT/MallocTestType.java \ - runtime/NMT/MallocTrackingVerify.java \ - runtime/NMT/ReleaseCommittedMemory.java \ - runtime/NMT/ReleaseNoCommit.java \ - runtime/NMT/ShutdownTwice.java \ - runtime/NMT/SummaryAfterShutdown.java \ - runtime/NMT/SummarySanityCheck.java \ - runtime/NMT/ThreadedMallocTestType.java \ - runtime/NMT/ThreadedVirtualAllocTestType.java \ - runtime/NMT/VirtualAllocCommitUncommitRecommit.java \ - runtime/NMT/VirtualAllocTestType.java \ - runtime/RedefineObject/TestRedefineObject.java \ - runtime/Thread/TestThreadDumpMonitorContention.java \ - runtime/Thread/ThreadPriorities.java \ - runtime/XCheckJniJsig/XCheckJSig.java \ - serviceability/attach/AttachWithStalePidFile.java \ - serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \ - serviceability/dcmd/vm/DynLibsTest.java \ - serviceability/tmtools - - -# JRE adds further tests to compact3 -# -jre = \ - :compact3 \ - :needs_jre \ - -:needs_jdk - -# Tests that require the full JRE -# -needs_jre = \ - compiler/c2/Test6852078.java \ - compiler/c2/Test7047069.java \ - runtime/6294277/SourceDebugExtension.java \ - runtime/ClassFile/JsrRewriting.java \ - runtime/ClassFile/OomWhileParsingRepeatedJsr.java \ - runtime/SharedArchiveFile/LimitSharedSizes.java \ - runtime/SharedArchiveFile/SpaceUtilizationCheck.java - -# Compact 3 adds further tests to compact2 -# -compact3 = \ - :compact2 \ - :needs_compact3 \ - -:needs_jre \ - -:needs_jdk - - -# Tests that require compact3 API's -# -needs_compact3 = \ - gc/TestFullGCCount.java \ - gc/arguments/TestG1HeapRegionSize.java \ - gc/arguments/TestDynMinHeapFreeRatio.java \ - gc/arguments/TestDynMaxHeapFreeRatio.java \ - gc/cms/TestMBeanCMS.java \ - gc/g1/TestHumongousAllocInitialMark.java \ - gc/g1/TestShrinkAuxiliaryData00.java \ - gc/g1/TestShrinkAuxiliaryData05.java \ - gc/g1/TestShrinkAuxiliaryData10.java \ - gc/g1/TestShrinkAuxiliaryData15.java \ - gc/g1/TestShrinkAuxiliaryData20.java \ - gc/g1/TestShrinkAuxiliaryData25.java \ - gc/g1/TestShrinkAuxiliaryData30.java \ - gc/metaspace/TestMetaspaceMemoryPool.java \ - gc/survivorAlignment \ - runtime/InternalApi/ThreadCpuTimesDeadlock.java \ - runtime/NMT/JcmdSummaryDiff.java \ - runtime/RedefineTests/RedefineAnnotations.java \ - serviceability/threads/TestFalseDeadLock.java \ - compiler/codecache/jmx \ - compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java \ - compiler/rangechecks/TestRangeCheckSmearing.java \ - compiler/whitebox/DeoptimizeMultipleOSRTest.java \ - serviceability/dcmd \ - testlibrary_tests/whitebox/vm_flags - -# Compact 2 adds full VM tests -compact2 = \ - :compact2_minimal \ - :compact1 \ - :needs_full_vm_compact2 \ - -:needs_compact3 \ - -:needs_jre \ - -:needs_jdk - -# Tests that require compact2 API's and a full VM -# -needs_full_vm_compact2 = - -# Compact 1 adds full VM tests -# -compact1 = \ - :compact1_minimal \ - :needs_full_vm_compact1 \ - -:needs_compact2 \ - -:needs_full_vm_compact2 \ - -:needs_compact3 \ - -:needs_jre \ - -:needs_jdk - -# Tests that require compact1 API's and a full VM -# -needs_full_vm_compact1 = \ - runtime/NMT \ - gc/g1/TestRegionAlignment.java \ - gc/g1/TestShrinkToOneRegion.java \ - gc/metaspace/G1AddMetaspaceDependency.java \ - gc/startup_warnings/TestCMS.java \ - gc/startup_warnings/TestParallelGC.java \ - gc/startup_warnings/TestParallelScavengeSerialOld.java \ - runtime/SharedArchiveFile/SharedArchiveFile.java - -# Minimal VM on Compact 2 adds in some compact2 tests -# -compact2_minimal = \ - :compact1_minimal \ - :needs_compact2 \ - -:needs_full_vm_compact2 \ - -:needs_compact3 \ - -:needs_jre \ - -:needs_jdk - -# Tests that require compact2 API's -# -needs_compact2 = \ - compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java - -# All tests that run on the most minimal configuration: Minimal VM on Compact 1 -compact1_minimal = \ - serviceability/ \ - compiler/ \ - sanity/ \ - runtime/ \ - gc/ \ - -:needs_full_vm_compact1 \ - -:needs_full_vm_compact2 \ - -:needs_compact2 \ - -:needs_compact3 \ - -:needs_jre \ - -:needs_jdk - -# All tests that explicitly set the G1 GC -# -needs_g1gc = \ - compiler/regalloc/C1ObjectSpillInLogicOp.java \ - gc/TestHumongousReferenceObject.java \ - gc/TestSmallHeap.java \ - gc/TestSystemGC.java \ - gc/arguments/TestAlignmentToUseLargePages.java \ - gc/arguments/TestG1ConcRefinementThreads.java \ - gc/arguments/TestG1HeapRegionSize.java \ - gc/arguments/TestG1HeapSizeFlags.java \ - gc/arguments/TestG1PercentageOptions.java \ - gc/arguments/TestMaxHeapSizeTools.java \ - gc/arguments/TestMaxNewSize.java \ - gc/arguments/TestParallelGCThreads.java \ - gc/arguments/TestUseCompressedOopsErgo.java \ - gc/class_unloading/TestG1ClassUnloadingHWM.java \ - gc/ergonomics/TestDynamicNumberOfGCThreads.java \ - gc/g1/ \ - gc/logging/TestGCId.java \ - gc/metaspace/G1AddMetaspaceDependency.java \ - gc/metaspace/TestMetaspacePerfCounters.java \ - gc/startup_warnings/TestG1.java \ - gc/whitebox/TestConcMarkCycleWB.java - hotspot_native_sanity = \ native_sanity @@ -447,17 +223,3 @@ hotspot_runtime_minimalvm = \ runtime/MinimalVM \ runtime/ErrorHandling \ runtime/logging - -#All tests that depends on nashorn extension. -# -needs_nashorn = \ - compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java - -#All tests that do not depends on nashorn extension -# -not_needs_nashorn = \ - :jdk \ - -:needs_nashorn - -hotspot_tmtools = \ - serviceability/tmtools From 57f866aaebf426cdb5e0cc8bf8082ef9b5f3d56b Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 1 Mar 2017 14:59:36 -0800 Subject: [PATCH 34/86] 8155980: ARM InterpreterMacroAssembler::get_method_counters() should not be saving caller saved registers Make get_method_counters() only save registers specified by caller, not all of them Reviewed-by: dlong, jiangli --- .../cpu/arm/vm/abstractInterpreter_arm.cpp | 11 ++- hotspot/src/cpu/arm/vm/interp_masm_arm.cpp | 81 ++++++------------- hotspot/src/cpu/arm/vm/interp_masm_arm.hpp | 8 +- .../vm/templateInterpreterGenerator_arm.cpp | 8 +- hotspot/src/cpu/arm/vm/templateTable_arm.cpp | 13 ++- 5 files changed, 56 insertions(+), 65 deletions(-) diff --git a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp index 7899c102e5b..35f0d258e49 100644 --- a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp +++ b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -234,8 +234,15 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef AARCH64 interpreter_frame->interpreter_frame_set_stack_top(stack_top); + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries()); intptr_t* extended_sp = (intptr_t*) monbot - - (method->max_stack() + 1) * Interpreter::stackElementWords - // +1 is reserved slot for exception handler + (max_stack * Interpreter::stackElementWords) - popframe_extra_args; extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes); interpreter_frame->interpreter_frame_set_extended_sp(extended_sp); diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp index 2f41b102a85..d007a4629df 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -2195,75 +2195,42 @@ void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, void InterpreterMacroAssembler::get_method_counters(Register method, Register Rcounters, - Label& skip) { + Label& skip, + bool saveRegs, + Register reg1, + Register reg2, + Register reg3) { const Address method_counters(method, Method::method_counters_offset()); Label has_counters; ldr(Rcounters, method_counters); cbnz(Rcounters, has_counters); + if (saveRegs) { + // Save and restore in use caller-saved registers since they will be trashed by call_VM + assert(reg1 != noreg, "must specify reg1"); + assert(reg2 != noreg, "must specify reg2"); #ifdef AARCH64 - const Register tmp = Rcounters; - const int saved_regs_size = 20*wordSize; - - // Note: call_VM will cut SP according to Rstack_top value before call, and restore SP to - // extended_sp value from frame after the call. - // So make sure there is enough stack space to save registers and adjust Rstack_top accordingly. - { - Label enough_stack_space; - check_extended_sp(tmp); - sub(Rstack_top, Rstack_top, saved_regs_size); - cmp(SP, Rstack_top); - b(enough_stack_space, ls); - - align_reg(tmp, Rstack_top, StackAlignmentInBytes); - mov(SP, tmp); - str(tmp, Address(FP, frame::interpreter_frame_extended_sp_offset * wordSize)); - - bind(enough_stack_space); - check_stack_top(); - - int offset = 0; - stp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - } + assert(reg3 != noreg, "must specify reg3"); + stp(reg1, reg2, Address(Rstack_top, -2*wordSize, pre_indexed)); + stp(reg3, ZR, Address(Rstack_top, -2*wordSize, pre_indexed)); #else - push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + assert(reg3 == noreg, "must not specify reg3"); + push(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } mov(R1, method); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::build_method_counters), R1); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), R1); + if (saveRegs) { #ifdef AARCH64 - { - int offset = 0; - ldp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - - add(Rstack_top, Rstack_top, saved_regs_size); - } + ldp(reg3, ZR, Address(Rstack_top, 2*wordSize, post_indexed)); + ldp(reg1, reg2, Address(Rstack_top, 2*wordSize, post_indexed)); #else - pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + pop(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } ldr(Rcounters, method_counters); cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp index 43f0d54edc4..af78144ed7b 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp @@ -349,7 +349,13 @@ class InterpreterMacroAssembler: public MacroAssembler { void trace_state(const char* msg) PRODUCT_RETURN; - void get_method_counters(Register method, Register Rcounters, Label& skip); +void get_method_counters(Register method, + Register Rcounters, + Label& skip, + bool saveRegs = false, + Register reg1 = noreg, + Register reg2 = noreg, + Register reg3 = noreg); }; #endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP diff --git a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp index aab1fb0aec0..f2576790c78 100644 --- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -1401,7 +1401,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef AARCH64 // setup RmaxStack __ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset())); - __ add(RmaxStack, RmaxStack, MAX2(1, Method::extra_stack_entries())); // reserve slots for exception handler and JSR292 appendix argument + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + __ add(RmaxStack, RmaxStack, MAX2(3, Method::extra_stack_entries())); #endif // AARCH64 // see if we've got enough room on the stack for locals plus overhead. diff --git a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp index c8711b830eb..b27d764a5a3 100644 --- a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -2286,13 +2286,18 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { } __ bind(no_mdo); // Increment backedge counter in MethodCounters* - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Note Rbumped_taken_count is a callee saved registers for ARM32, but caller saved for ARM64 + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset())); __ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask, Rcnt, R4_tmp, eq, &backedge_counter_overflow); } else { - // increment counter - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Increment backedge counter in MethodCounters* + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); __ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter __ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter __ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter From 812444f78a31f1a97afd7f68476490e5d052ccfb Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 2 Mar 2017 09:51:47 +0100 Subject: [PATCH 35/86] 8136650: Add support for custom jtreg native tests Reviewed-by: ctornqvi, erikj --- hotspot/make/test/JtregNative.gmk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 7223733367a..d3f44bf67fd 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2017, 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 @@ -35,12 +35,14 @@ include $(SPEC) include MakeBase.gmk include TestFilesCompilation.gmk +$(eval $(call IncludeCustomExtension, hotspot, test/JtregNative.gmk)) + ################################################################################ # Targets for building the native tests themselves. ################################################################################ # Add more directories here when needed. -BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ +BUILD_HOTSPOT_JTREG_NATIVE_SRC += \ $(HOTSPOT_TOPDIR)/test/native_sanity \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ From 2ea73551ba98bc7dc505f1b487b0b804319d8fb6 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 3 Mar 2017 12:02:35 +0100 Subject: [PATCH 36/86] 8176096: Wrong macro checks for INCLUDE_TRACE Reviewed-by: dholmes, coleenp, mgronlun --- hotspot/src/share/vm/runtime/mutexLocker.cpp | 4 ++-- hotspot/src/share/vm/runtime/mutexLocker.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index 29ad520e1f0..ef1122458fb 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -124,7 +124,7 @@ Monitor* Service_lock = NULL; Monitor* PeriodicTask_lock = NULL; Monitor* RedefineClasses_lock = NULL; -#ifdef INCLUDE_TRACE +#if INCLUDE_TRACE Mutex* JfrStacktrace_lock = NULL; Monitor* JfrMsg_lock = NULL; Mutex* JfrBuffer_lock = NULL; @@ -276,7 +276,7 @@ void mutex_init() { def(Compilation_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_never); } -#ifdef INCLUDE_TRACE +#if INCLUDE_TRACE def(JfrMsg_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_always); def(JfrBuffer_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); def(JfrThreadGroups_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index c0db4e9f4e6..2129f85f06f 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -124,7 +124,7 @@ extern Monitor* Service_lock; // a lock used for service thre extern Monitor* PeriodicTask_lock; // protects the periodic task structure extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition -#ifdef INCLUDE_TRACE +#if INCLUDE_TRACE extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table extern Monitor* JfrMsg_lock; // protects JFR messaging extern Mutex* JfrBuffer_lock; // protects JFR buffer operations From b067fc774d7be10832617a7d75ce661699990f25 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Sat, 4 Mar 2017 15:56:22 -0500 Subject: [PATCH 37/86] 8175221: Cleanup DirtyCardQueueSet::concatenate_log Concatenate_log calls flush, flush no longer checks "permanent" Reviewed-by: tschatzl, shade --- hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 6 ++---- hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp | 6 +----- hotspot/src/share/vm/gc/g1/ptrQueue.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/ptrQueue.hpp | 4 ++-- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index dcd88be5057..822a85d59a9 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -301,9 +301,7 @@ void DirtyCardQueueSet::abandon_logs() { void DirtyCardQueueSet::concatenate_log(DirtyCardQueue& dcq) { if (!dcq.is_empty()) { - enqueue_complete_buffer( - BufferNode::make_node_from_buffer(dcq.get_buf(), dcq.get_index())); - dcq.reinitialize(); + dcq.flush(); } } diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp index faaa1bd9d0a..675f15a1191 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -52,10 +52,6 @@ public: // Process queue entries and release resources. void flush() { flush_impl(); } - void **get_buf() { return _buf;} - size_t get_index() { return _index;} - void reinitialize() { _buf = 0; _sz = 0; _index = 0;} - // Compiler support. static ByteSize byte_offset_of_index() { return PtrQueue::byte_offset_of_index(); diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp index 5c94f87eafd..50f8e622ff0 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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,7 +42,7 @@ PtrQueue::~PtrQueue() { } void PtrQueue::flush_impl() { - if (!_permanent && _buf != NULL) { + if (_buf != NULL) { BufferNode* node = BufferNode::make_node_from_buffer(_buf, _index); if (is_empty()) { // No work to do. diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp index 50c23960eca..8ef754bbcef 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ protected: PtrQueueSet* qset() { return _qset; } bool is_permanent() const { return _permanent; } - // Process queue entries and release resources, if not permanent. + // Process queue entries and release resources. void flush_impl(); // Initialize this queue to contain a null buffer, and be part of the From 6677810ffa04b9f75fcda569565dc4f69d8e70e7 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 6 Mar 2017 15:33:14 +0100 Subject: [PATCH 38/86] 8175367: Wrong assert for UseCompressedOops in aarch64 Copy::conjoint_oops_atomic implementation Remove wrong check for UseCompressedOops Reviewed-by: aph --- .../src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp index 96575867dc2..55675e57537 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -159,7 +159,6 @@ static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { } static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { - assert(!UseCompressedOops, "foo!"); assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count); } From 8d405d171cbffe62fb3c6db620bdff8b73c73749 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 6 Mar 2017 17:03:35 +0100 Subject: [PATCH 39/86] 8071278: Fix the closure mess in G1RemSet::refine_card() Remove the use of many nested closure in the code to refine a card. Reviewed-by: kbarrett, sjohanss --- hotspot/src/share/vm/gc/g1/g1OopClosures.hpp | 77 ++----------------- .../share/vm/gc/g1/g1OopClosures.inline.hpp | 58 +------------- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 50 ++++-------- .../vm/gc/g1/g1_specialized_oop_closures.hpp | 6 +- hotspot/src/share/vm/gc/g1/heapRegion.cpp | 23 ++++-- hotspot/src/share/vm/gc/g1/heapRegion.hpp | 4 +- 6 files changed, 49 insertions(+), 169 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index bc594ed86e9..4050f3ae5c2 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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,29 +143,6 @@ class G1KlassScanClosure : public KlassClosure { void do_klass(Klass* klass); }; -class FilterIntoCSClosure: public OopClosure { - G1CollectedHeap* _g1; - OopClosure* _oc; -public: - FilterIntoCSClosure(G1CollectedHeap* g1, OopClosure* oc) : _g1(g1), _oc(oc) { } - - template void do_oop_work(T* p); - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } -}; - -class FilterOutOfRegionClosure: public ExtendedOopClosure { - HeapWord* _r_bottom; - HeapWord* _r_end; - OopClosure* _oc; -public: - FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc); - template void do_oop_nv(T* p); - virtual void do_oop(oop* p) { do_oop_nv(p); } - virtual void do_oop(narrowOop* p) { do_oop_nv(p); } - bool apply_to_weak_ref_discovered_field() { return true; } -}; - // Closure for iterating over object fields during concurrent marking class G1CMOopClosure : public MetadataAwareOopClosure { protected: @@ -193,58 +170,16 @@ public: virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; -// Closure that applies the given two closures in sequence. -// Used by the RSet refinement code (when updating RSets -// during an evacuation pause) to record cards containing -// pointers into the collection set. - -class G1Mux2Closure : public OopClosure { - OopClosure* _c1; - OopClosure* _c2; -public: - G1Mux2Closure(OopClosure *c1, OopClosure *c2); - template inline void do_oop_work(T* p); - virtual inline void do_oop(oop* p); - virtual inline void do_oop(narrowOop* p); -}; - -// A closure that returns true if it is actually applied -// to a reference - -class G1TriggerClosure : public OopClosure { - bool _triggered; -public: - G1TriggerClosure(); - bool triggered() const { return _triggered; } - template inline void do_oop_work(T* p); - virtual inline void do_oop(oop* p); - virtual inline void do_oop(narrowOop* p); -}; - -// A closure which uses a triggering closure to determine -// whether to apply an oop closure. - -class G1InvokeIfNotTriggeredClosure: public OopClosure { - G1TriggerClosure* _trigger_cl; - OopClosure* _oop_cl; -public: - G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t, OopClosure* oc); - template inline void do_oop_work(T* p); - virtual inline void do_oop(oop* p); - virtual inline void do_oop(narrowOop* p); -}; - -class G1UpdateRSOrPushRefOopClosure: public OopClosure { +class G1UpdateRSOrPushRefOopClosure: public ExtendedOopClosure { G1CollectedHeap* _g1; - G1RemSet* _g1_rem_set; HeapRegion* _from; G1ParPushHeapRSClosure* _push_ref_cl; bool _record_refs_into_cset; uint _worker_i; + bool _has_refs_into_cset; public: G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, - G1RemSet* rs, G1ParPushHeapRSClosure* push_ref_cl, bool record_refs_into_cset, uint worker_i = 0); @@ -254,13 +189,17 @@ public: _from = from; } + bool apply_to_weak_ref_discovered_field() { return true; } + bool self_forwarded(oop obj) { markOop m = obj->mark(); bool result = (m->is_marked() && ((oop)m->decode_pointer() == obj)); return result; } - template inline void do_oop_work(T* p); + bool has_refs_into_cset() const { return _has_refs_into_cset; } + + template inline void do_oop_nv(T* p); virtual inline void do_oop(narrowOop* p); virtual inline void do_oop(oop* p); }; diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index 054aefbdedd..5f863fdcf7a 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -36,31 +36,6 @@ #include "memory/iterator.inline.hpp" #include "runtime/prefetch.inline.hpp" -/* - * This really ought to be an inline function, but apparently the C++ - * compiler sometimes sees fit to ignore inline declarations. Sigh. - */ - -template -inline void FilterIntoCSClosure::do_oop_work(T* p) { - T heap_oop = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(heap_oop) && - _g1->is_in_cset_or_humongous(oopDesc::decode_heap_oop_not_null(heap_oop))) { - _oc->do_oop(p); - } -} - -template -inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { - T heap_oop = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(heap_oop)) { - HeapWord* obj_hw = (HeapWord*)oopDesc::decode_heap_oop_not_null(heap_oop); - if (obj_hw < _r_bottom || obj_hw >= _r_end) { - _oc->do_oop(p); - } - } -} - // This closure is applied to the fields of the objects that have just been copied. template inline void G1ParScanClosure::do_oop_nv(T* p) { @@ -136,33 +111,7 @@ inline void G1RootRegionScanClosure::do_oop_nv(T* p) { } template -inline void G1Mux2Closure::do_oop_work(T* p) { - // Apply first closure; then apply the second. - _c1->do_oop(p); - _c2->do_oop(p); -} -void G1Mux2Closure::do_oop(oop* p) { do_oop_work(p); } -void G1Mux2Closure::do_oop(narrowOop* p) { do_oop_work(p); } - -template -inline void G1TriggerClosure::do_oop_work(T* p) { - // Record that this closure was actually applied (triggered). - _triggered = true; -} -void G1TriggerClosure::do_oop(oop* p) { do_oop_work(p); } -void G1TriggerClosure::do_oop(narrowOop* p) { do_oop_work(p); } - -template -inline void G1InvokeIfNotTriggeredClosure::do_oop_work(T* p) { - if (!_trigger_cl->triggered()) { - _oop_cl->do_oop(p); - } -} -void G1InvokeIfNotTriggeredClosure::do_oop(oop* p) { do_oop_work(p); } -void G1InvokeIfNotTriggeredClosure::do_oop(narrowOop* p) { do_oop_work(p); } - -template -inline void G1UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { +inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); if (obj == NULL) { return; @@ -217,6 +166,7 @@ inline void G1UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { // instance for this worker thread. _push_ref_cl->do_oop(p); } + _has_refs_into_cset = true; // Deferred updates to the CSet are either discarded (in the normal case), // or processed (if an evacuation failure occurs) at the end @@ -232,8 +182,8 @@ inline void G1UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { to->rem_set()->add_reference(p, _worker_i); } } -void G1UpdateRSOrPushRefOopClosure::do_oop(oop* p) { do_oop_work(p); } -void G1UpdateRSOrPushRefOopClosure::do_oop(narrowOop* p) { do_oop_work(p); } +void G1UpdateRSOrPushRefOopClosure::do_oop(oop* p) { do_oop_nv(p); } +void G1UpdateRSOrPushRefOopClosure::do_oop(narrowOop* p) { do_oop_nv(p); } template void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) { diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 11a8806a4ea..692160b66c3 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -527,25 +527,16 @@ void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) { _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); } -G1TriggerClosure::G1TriggerClosure() : - _triggered(false) { } - -G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl, - OopClosure* oop_cl) : - _trigger_cl(t_cl), _oop_cl(oop_cl) { } - -G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) : - _c1(c1), _c2(c2) { } - -G1UpdateRSOrPushRefOopClosure:: -G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, - G1RemSet* rs, - G1ParPushHeapRSClosure* push_ref_cl, - bool record_refs_into_cset, - uint worker_i) : - _g1(g1h), _g1_rem_set(rs), _from(NULL), +G1UpdateRSOrPushRefOopClosure::G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, + G1ParPushHeapRSClosure* push_ref_cl, + bool record_refs_into_cset, + uint worker_i) : + _g1(g1h), + _from(NULL), _record_refs_into_cset(record_refs_into_cset), - _push_ref_cl(push_ref_cl), _worker_i(worker_i) { } + _has_refs_into_cset(false), + _push_ref_cl(push_ref_cl), + _worker_i(worker_i) { } // Returns true if the given card contains references that point // into the collection set, if we're checking for such references; @@ -690,25 +681,14 @@ bool G1RemSet::refine_card(jbyte* card_ptr, assert(!dirty_region.is_empty(), "sanity"); G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1, - _g1->g1_rem_set(), oops_in_heap_closure, check_for_refs_into_cset, worker_i); update_rs_oop_cl.set_from(r); - G1TriggerClosure trigger_cl; - FilterIntoCSClosure into_cs_cl(_g1, &trigger_cl); - G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); - G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); - - FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r, - (check_for_refs_into_cset ? - (OopClosure*)&mux : - (OopClosure*)&update_rs_oop_cl)); - bool card_processed = r->oops_on_card_seq_iterate_careful(dirty_region, - &filter_then_update_rs_oop_cl); + &update_rs_oop_cl); // If unable to process the card then we encountered an unparsable // part of the heap (e.g. a partially allocated object) while @@ -731,15 +711,15 @@ bool G1RemSet::refine_card(jbyte* card_ptr, _conc_refine_cards++; } - // This gets set to true if the card being refined has - // references that point into the collection set. - bool has_refs_into_cset = trigger_cl.triggered(); + // This gets set to true if the card being refined has references that point + // into the collection set. + bool has_refs_into_cset = update_rs_oop_cl.has_refs_into_cset(); // We should only be detecting that the card contains references // that point into the collection set if the current thread is // a GC worker thread. assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(), - "invalid result at non safepoint"); + "invalid result at non safepoint"); return has_refs_into_cset; } diff --git a/hotspot/src/share/vm/gc/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc/g1/g1_specialized_oop_closures.hpp index e2698be9963..fa3d82bea7e 100644 --- a/hotspot/src/share/vm/gc/g1/g1_specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_specialized_oop_closures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -35,14 +35,14 @@ class G1ParScanClosure; class G1ParPushHeapRSClosure; -class FilterOutOfRegionClosure; +class G1UpdateRSOrPushRefOopClosure; class G1CMOopClosure; class G1RootRegionScanClosure; #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f) \ f(G1ParScanClosure,_nv) \ f(G1ParPushHeapRSClosure,_nv) \ - f(FilterOutOfRegionClosure,_nv) \ + f(G1UpdateRSOrPushRefOopClosure,_nv) \ f(G1CMOopClosure,_nv) \ f(G1RootRegionScanClosure,_nv) diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 38273660b62..27a6584b30e 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -55,10 +55,6 @@ HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1, DirtyCardToOopClosure(hr, cl, precision, NULL), _hr(hr), _rs_scan(cl), _g1(g1) { } -FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r, - OopClosure* oc) : - _r_bottom(r->bottom()), _r_end(r->end()), _oc(oc) { } - void HeapRegionDCTOC::walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top) { @@ -357,7 +353,7 @@ void HeapRegion::note_self_forwarding_removal_end(size_t marked_bytes) { // special handling for concurrent processing encountering an // in-progress allocation. static bool do_oops_on_card_in_humongous(MemRegion mr, - FilterOutOfRegionClosure* cl, + G1UpdateRSOrPushRefOopClosure* cl, HeapRegion* hr, G1CollectedHeap* g1h) { assert(hr->is_humongous(), "precondition"); @@ -398,7 +394,7 @@ static bool do_oops_on_card_in_humongous(MemRegion mr, } bool HeapRegion::oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl) { + G1UpdateRSOrPushRefOopClosure* cl) { assert(MemRegion(bottom(), end()).contains(mr), "Card region not in heap region"); G1CollectedHeap* g1h = G1CollectedHeap::heap(); @@ -769,6 +765,21 @@ public: } }; +// Closure that applies the given two closures in sequence. +class G1Mux2Closure : public OopClosure { + OopClosure* _c1; + OopClosure* _c2; +public: + G1Mux2Closure(OopClosure *c1, OopClosure *c2) { _c1 = c1; _c2 = c2; } + template inline void do_oop_work(T* p) { + // Apply first closure; then apply the second. + _c1->do_oop(p); + _c2->do_oop(p); + } + virtual inline void do_oop(oop* p) { do_oop_work(p); } + virtual inline void do_oop(narrowOop* p) { do_oop_work(p); } +}; + // This really ought to be commoned up into OffsetTableContigSpace somehow. // We would need a mechanism to make that code skip dead objects. diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.hpp index 195ebea6c74..6981a8de0e9 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -661,7 +661,7 @@ class HeapRegion: public G1ContiguousSpace { // encountered; that only happens when invoked concurrently with the // mutator. bool oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl); + G1UpdateRSOrPushRefOopClosure* cl); size_t recorded_rs_length() const { return _recorded_rs_length; } double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; } From 1bcca93f8a0a39c70ae7591e103c89dccb550ab5 Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Mon, 6 Mar 2017 09:24:47 -0800 Subject: [PATCH 40/86] 8176163: [TESTBUG] Create hotspot_cds test group Created a new test group Reviewed-by: sspitsyn, dholmes, ehelin --- hotspot/test/TEST.groups | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 724ed0c9b7c..62ebf674604 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -182,6 +182,11 @@ hotspot_fast_runtime = \ sanity/ \ testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +hotspot_cds = \ + runtime/SharedArchiveFile/ \ + runtime/CompressedOops/ + + hotspot_fast_serviceability = \ serviceability/dcmd/compiler \ serviceability/logging From e44e774bbee76e026949dece18569cb5f7c3d06d Mon Sep 17 00:00:00 2001 From: Gunter Haug Date: Mon, 27 Feb 2017 12:57:16 +0100 Subject: [PATCH 41/86] 8175900: Assertion too strict in G1CollectedHeap::new_mutator_alloc_region Reviewed-by: simonis, tschatzl, kbarrett --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index b30f9a512eb..830d7ac8584 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -5269,8 +5269,6 @@ bool G1CollectedHeap::is_in_closed_subset(const void* p) const { HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, bool force) { assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); - assert(!force || g1_policy()->can_expand_young_list(), - "if force is true we should be able to expand the young list"); bool should_allocate = g1_policy()->should_allocate_mutator_region(); if (force || should_allocate) { HeapRegion* new_alloc_region = new_region(word_size, From 3e707c36714e2d0d4ec131a420a193a717e659f1 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Tue, 7 Mar 2017 11:35:45 -0500 Subject: [PATCH 42/86] 8176102: Rename hotspot_fast* test groups to hotspot_tier1* Reviewed-by: dholmes, mseledtsov, gtriantafill --- hotspot/test/TEST.groups | 74 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 62ebf674604..a8827168292 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -46,7 +46,7 @@ hotspot_misc = \ hotspot_native_sanity = \ native_sanity -hotspot_fast_compiler_1 = \ +hotspot_tier1_compiler_1 = \ compiler/aot/ \ compiler/arraycopy/ \ compiler/c1/ \ @@ -62,7 +62,7 @@ hotspot_fast_compiler_1 = \ -compiler/c2/Test6603011.java \ -compiler/c2/Test6912517.java \ -hotspot_fast_compiler_2 = \ +hotspot_tier1_compiler_2 = \ compiler/classUnloading/ \ compiler/codecache/ \ compiler/codegen/ \ @@ -81,7 +81,7 @@ hotspot_fast_compiler_2 = \ -compiler/codecache/stress \ -compiler/gcbarriers/PreserveFPRegistersTest.java -hotspot_fast_compiler_3 = \ +hotspot_tier1_compiler_3 = \ compiler/intrinsics/ \ compiler/jsr292/ \ compiler/loopopts/ \ @@ -102,20 +102,20 @@ hotspot_fast_compiler_3 = \ -compiler/loopopts/Test7052494.java \ -compiler/runtime/Test6826736.java -hotspot_fast_compiler_closed = \ +hotspot_tier1_compiler_closed = \ sanity/ExecuteInternalVMTests.java hotspot_not_fast_compiler = \ :hotspot_compiler \ - -:hotspot_fast_compiler_1 \ - -:hotspot_fast_compiler_2 \ - -:hotspot_fast_compiler_3 \ - -:hotspot_fast_compiler_closed + -:hotspot_tier1_compiler_1 \ + -:hotspot_tier1_compiler_2 \ + -:hotspot_tier1_compiler_3 \ + -:hotspot_tier1_compiler_closed -hotspot_fast_gc_1 = \ +hotspot_tier1_gc_1 = \ gc/g1/ -hotspot_fast_gc_2 = \ +hotspot_tier1_gc_2 = \ sanity/ExecuteInternalVMTests.java \ gc/ \ -gc/g1/ \ @@ -125,19 +125,19 @@ hotspot_fast_gc_2 = \ -gc/cms/TestMBeanCMS.java \ -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java -hotspot_fast_gc_closed = \ +hotspot_tier1_gc_closed = \ sanity/ExecuteInternalVMTests.java -hotspot_fast_gc_gcold = \ +hotspot_tier1_gc_gcold = \ gc/stress/TestGCOld.java -hotspot_fast_gc_gcbasher = \ +hotspot_tier1_gc_gcbasher = \ gc/stress/gcbasher/TestGCBasherWithG1.java \ gc/stress/gcbasher/TestGCBasherWithCMS.java \ gc/stress/gcbasher/TestGCBasherWithSerial.java \ gc/stress/gcbasher/TestGCBasherWithParallel.java -hotspot_fast_runtime = \ +hotspot_tier1_runtime = \ runtime/ \ -runtime/6626217/Test6626217.sh \ -runtime/7100935 \ @@ -187,42 +187,42 @@ hotspot_cds = \ runtime/CompressedOops/ -hotspot_fast_serviceability = \ +hotspot_tier1_serviceability = \ serviceability/dcmd/compiler \ serviceability/logging -hotspot_jprt = \ - :hotspot_fast_compiler_1 \ - :hotspot_fast_compiler_2 \ - :hotspot_fast_compiler_3 \ - :hotspot_fast_compiler_closed \ - :hotspot_fast_gc_1 \ - :hotspot_fast_gc_2 \ - :hotspot_fast_gc_closed \ - :hotspot_fast_gc_gcold \ - :hotspot_fast_runtime \ - :hotspot_fast_serviceability +hotspot_tier1 = \ + :hotspot_tier1_compiler_1 \ + :hotspot_tier1_compiler_2 \ + :hotspot_tier1_compiler_3 \ + :hotspot_tier1_compiler_closed \ + :hotspot_tier1_gc_1 \ + :hotspot_tier1_gc_2 \ + :hotspot_tier1_gc_closed \ + :hotspot_tier1_gc_gcold \ + :hotspot_tier1_runtime \ + :hotspot_tier1_serviceability -hotspot_runtime_tier2 = \ +hotspot_tier2_runtime = \ runtime/ \ serviceability/ \ -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \ -runtime/Thread/TestThreadDumpMonitorContention.java \ - -:hotspot_fast_runtime \ - -:hotspot_fast_serviceability \ - -:hotspot_runtime_tier2_platform_agnostic + -:hotspot_tier1_runtime \ + -:hotspot_tier1_serviceability \ + -:hotspot_tier2_runtime_platform_agnostic -hotspot_runtime_tier2_platform_agnostic = \ +hotspot_tier2_runtime_platform_agnostic = \ runtime/SelectionResolution \ - -:hotspot_fast_runtime + -:hotspot_tier1_runtime -hotspot_runtime_tier3 = \ +hotspot_tier3_runtime = \ runtime/ \ serviceability/ \ - -:hotspot_fast_runtime \ - -:hotspot_fast_serviceability \ - -:hotspot_runtime_tier2_platform_agnostic \ - -:hotspot_runtime_tier2 + -:hotspot_tier1_runtime \ + -:hotspot_tier1_serviceability \ + -:hotspot_tier2_runtime_platform_agnostic \ + -:hotspot_tier2_runtime hotspot_runtime_minimalvm = \ runtime/MinimalVM \ From d86c76dca9db7e3ab241742b25de7cfc94b2556c Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Tue, 7 Mar 2017 10:25:58 -0800 Subject: [PATCH 43/86] 8023905: Failing to initialize VM with small initial heap when NUMA and large pages are enabled Exit VM when fails to initialize small initial heap with NUMA and large pages enabled Reviewed-by: jmasa, sjohanss --- .../share/vm/gc/parallel/mutableNUMASpace.cpp | 16 ++- .../share/vm/gc/parallel/mutableNUMASpace.hpp | 4 +- ...tSmallInitialHeapWithLargePageAndNUMA.java | 99 +++++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java diff --git a/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp index c4cb76d5c86..caa7c0ae0a4 100644 --- a/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp @@ -30,11 +30,21 @@ #include "runtime/atomic.hpp" #include "runtime/thread.inline.hpp" -MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) { +MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment), _must_use_large_pages(false) { _lgrp_spaces = new (ResourceObj::C_HEAP, mtGC) GrowableArray(0, true); _page_size = os::vm_page_size(); _adaptation_cycles = 0; _samples_count = 0; + +#ifdef LINUX + // Changing the page size can lead to freeing of memory. When using large pages + // and the memory has been both reserved and committed, Linux does not support + // freeing parts of it. + if (UseLargePages && !os::can_commit_large_page_memory()) { + _must_use_large_pages = true; + } +#endif // LINUX + update_layout(true); } @@ -578,6 +588,10 @@ void MutableNUMASpace::initialize(MemRegion mr, // Try small pages if the chunk size is too small if (base_space_size_pages / lgrp_spaces()->length() == 0 && page_size() > (size_t)os::vm_page_size()) { + // Changing the page size below can lead to freeing of memory. So we fail initialization. + if (_must_use_large_pages) { + vm_exit_during_initialization("Failed initializing NUMA with large pages. Too small heap size"); + } set_page_size(os::vm_page_size()); rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size()); rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size()); diff --git a/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.hpp index c8b626a45b3..0a531d5dd39 100644 --- a/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, 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 @@ -145,6 +145,8 @@ class MutableNUMASpace : public MutableSpace { size_t _page_size; unsigned _adaptation_cycles, _samples_count; + bool _must_use_large_pages; + void set_page_size(size_t psz) { _page_size = psz; } size_t page_size() const { return _page_size; } diff --git a/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java b/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java new file mode 100644 index 00000000000..fdfe66a5a4c --- /dev/null +++ b/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestSmallInitialHeapWithLargePageAndNUMA + * @bug 8023905 + * @requires os.family == "linux" + * @requires vm.gc.Parallel + * @summary Check large pages and NUMA are working together via the output message. + * @library /testlibrary /test/lib /test/lib/share/classes + * @modules java.base/jdk.internal.misc + * @modules java.management/sun.management + * @build TestSmallInitialHeapWithLargePageAndNUMA + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UseHugeTLBFS -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestSmallInitialHeapWithLargePageAndNUMA +*/ + +import jdk.test.lib.ProcessTools; +import jdk.test.lib.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class TestSmallInitialHeapWithLargePageAndNUMA { + + private static final String MSG_EXIT_TOO_SMALL_HEAP = "Failed initializing NUMA with large pages. Too small heap size"; + private static final String MSG_GC_TRIGGERED_BEFORE_INIT = "GC triggered before VM initialization completed."; + + public static void main(String[] args) throws Exception { + + WhiteBox wb = WhiteBox.getWhiteBox(); + long heapAlignment = wb.getHeapAlignment(); + + // When using large pages, Linux does not support freeing parts of reserved and committed memory. + // And current Linux implementation uses page size as a condition to actually freeing memory. + // If we allocate pages less than NUMA node, NUMA will try to use default page size and + // this will free the memory which Linux does not support. + // Assume the minimum NUMA node as 2. + long initHeap = heapAlignment; + long maxHeap = heapAlignment * 2; + + String[] vmArgs = {"-XX:+UseParallelGC", + "-Xms" + String.valueOf(initHeap), + "-Xmx" + String.valueOf(maxHeap), + "-XX:+UseNUMA", + "-XX:+UseHugeTLBFS", + "-XX:+PrintFlagsFinal", + "-version"}; + + ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(vmArgs); + OutputAnalyzer analyzer = new OutputAnalyzer(pb_enabled.start()); + + if (largePageOrNumaEnabled(analyzer)) { + // We reach here, if both NUMA and HugeTLB are supported. + // However final flags will not be printed as NUMA initialization will be failed. + checkAnalyzerValues(analyzer, 1, MSG_EXIT_TOO_SMALL_HEAP); + } + } + + // If both NUMA and large pages are enabled, VM will exit during NUMA initialization + // under the small heap configuration. So final flags will not be printed. + private static boolean largePageOrNumaEnabled(OutputAnalyzer analyzer) { + String output = analyzer.getOutput(); + + return !output.contains("[Global flags]"); + } + + // We need to test with small heap but fastdebug binary fails to initialize because of the small heap. + // So skip that case. + private static void checkAnalyzerValues(OutputAnalyzer analyzer, int expectedExitValue, String expectedMessage) { + String output = analyzer.getOutput(); + + // If the VM exits because of the small heap, skip checking the exit value. + if (!output.contains(MSG_GC_TRIGGERED_BEFORE_INIT)) { + analyzer.shouldHaveExitValue(expectedExitValue); + } + if (expectedMessage != null) { + analyzer.shouldContain(expectedMessage); + } + } +} From f91cc0cd42069129049fa389df0b19944d5c2b19 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 7 Mar 2017 13:35:34 -0800 Subject: [PATCH 44/86] 8175341: "java/util/Arrays/ParallelPrefix.java" Crash Internal Error ...diagnosticCommand.cpp...assert(k != __null) failed: FinalizerHistogram class is not accessible Allow the dcmd to fail with a pending exception rather than assert Reviewed-by: sspitsyn, dholmes --- hotspot/src/share/vm/services/diagnosticCommand.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 29aa08daf94..a34a33fc3d4 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -420,10 +420,8 @@ void HeapInfoDCmd::execute(DCmdSource source, TRAPS) { void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) { ResourceMark rm; - - Klass* k = SystemDictionary::resolve_or_null( - vmSymbols::finalizer_histogram_klass(), THREAD); - assert(k != NULL, "FinalizerHistogram class is not accessible"); + Klass* k = SystemDictionary::resolve_or_fail( + vmSymbols::finalizer_histogram_klass(), true, CHECK); instanceKlassHandle klass(THREAD, k); JavaValue result(T_ARRAY); From 99a554c5ad5a5539e506ff9f8bbce19c1943a113 Mon Sep 17 00:00:00 2001 From: Lutz Schmidt Date: Wed, 8 Mar 2017 14:55:32 +0100 Subject: [PATCH 45/86] 8175368: [s390] Provide intrinsic implementation for CRC32C Reviewed-by: mdoerr, simonis --- .../src/cpu/s390/vm/c1_LIRAssembler_s390.cpp | 9 +- .../src/cpu/s390/vm/c1_LIRGenerator_s390.cpp | 77 +- .../src/cpu/s390/vm/macroAssembler_s390.cpp | 103 +- .../src/cpu/s390/vm/macroAssembler_s390.hpp | 29 +- .../src/cpu/s390/vm/stubGenerator_s390.cpp | 83 +- hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp | 1048 ++++++++++------- hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp | 7 +- .../vm/templateInterpreterGenerator_s390.cpp | 79 +- hotspot/src/cpu/s390/vm/vm_version_s390.cpp | 23 +- hotspot/src/share/vm/c1/c1_Compiler.cpp | 2 +- 10 files changed, 904 insertions(+), 556 deletions(-) diff --git a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp index 84fb4205099..2f75604e2b0 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -3048,9 +3048,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr()); - __ not_(crc, noreg, false); // ~crc - __ update_byte_crc32(crc, val, res); - __ not_(res, crc, false); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ z_lgfr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp index 98489aa7371..9e4b3a7eab4 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -61,20 +61,6 @@ void LIRItem::load_nonconstant(int bits) { } } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_constant()) { - // Constants get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } else { - if (!r->is_register()) { - li.load_item_force(dst); - } - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } -} - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -1217,10 +1203,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { LIR_Opr arg2 = cc->at(1); LIR_Opr arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1233,7 +1218,60 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem len(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + } + + LIR_Address* a = new LIR_Address(base_op, index, offset, T_BYTE); + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for (x->type()); + + LIR_Opr arg1 = cc->at(0); + LIR_Opr arg2 = cc->at(1); + LIR_Opr arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + len.load_item_force(arg3); // We skip int->long conversion here, because CRC32C stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } } void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { @@ -1264,4 +1302,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp index 1e21c6d8cba..bf3363793d8 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -5910,8 +5910,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param len register containing number of bytes * @param table register pointing to CRC table */ -void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC) { +void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, Register data) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -5921,20 +5920,12 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register z_ltr(len, len); z_brnh(L_done); - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_mainLoop); z_llgc(data, Address(buf, (intptr_t)0));// Current byte of input buffer (zero extended). Avoids garbage in upper half of register. add2reg(buf, mainLoop_stepping); // Advance buffer position. update_byte_crc32(crc, data, table); z_brct(len, L_mainLoop); // Iterate. - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_done); } @@ -5951,6 +5942,7 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab // c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ // crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] // #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + // Pre-calculate (constant) column offsets, use columns 4..7 for big-endian. const int ix0 = 4*(4*CRC32_COLUMN_SIZE); const int ix1 = 5*(4*CRC32_COLUMN_SIZE); const int ix2 = 6*(4*CRC32_COLUMN_SIZE); @@ -5969,17 +5961,12 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab rotate_then_insert(t1, t0, 56-2, 63-2, 2-16, true); // ((c >> 16) & 0xff) << 2 rotate_then_insert(t0, t0, 56-2, 63-2, 2-24, true); // ((c >> 24) & 0xff) << 2 - // Load pre-calculated table values. - // Use columns 4..7 for big-endian. - z_ly(t3, Address(table, t3, (intptr_t)ix0)); + // XOR indexed table values to calculate updated crc. z_ly(t2, Address(table, t2, (intptr_t)ix1)); - z_ly(t1, Address(table, t1, (intptr_t)ix2)); z_ly(t0, Address(table, t0, (intptr_t)ix3)); - - // Calculate new crc from table values. - z_xr(t2, t3); - z_xr(t0, t1); - z_xr(t0, t2); // Now crc contains the final checksum value. + z_xy(t2, Address(table, t3, (intptr_t)ix0)); + z_xy(t0, Address(table, t1, (intptr_t)ix2)); + z_xr(t0, t2); // Now t0 contains the updated CRC value. lgr_if_needed(crc, t0); } @@ -5992,7 +5979,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6007,7 +5995,9 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } #if 0 { @@ -6022,7 +6012,7 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len rotate_then_insert(ctr, ctr, 62, 63, 0, true); // TODO: should set cc z_sgfr(len, ctr); // Remaining len after alignment. - update_byteLoop_crc32(crc, buf, ctr, table, data, false); + update_byteLoop_crc32(crc, buf, ctr, table, data); } #endif @@ -6030,21 +6020,23 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len z_srag(ctr, len, log_stepping); z_brnh(L_tail); - z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. + z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. rotate_then_insert(len, len, 64-log_stepping, 63, 0, true); // #bytes for tailLoop BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, 0, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 4, mainLoop_stepping, crc, t1, t2, t3); - z_brct(ctr, L_mainLoop); // Iterate. + z_brct(ctr, L_mainLoop); // Iterate. - z_lrvr(crc, crc); // Revert byte order back to original. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6056,7 +6048,8 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6070,7 +6063,9 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } // Check for short (<4 bytes) buffer. z_srag(ctr, len, log_stepping); @@ -6082,13 +6077,16 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, mainLoop_stepping, crc, t1, t2, t3); z_brct(ctr, L_mainLoop); // Iterate. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6098,22 +6096,51 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len * @param table register pointing to CRC table */ void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Register data = t0; - update_byteLoop_crc32(crc, buf, len, table, data, true); + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byteLoop_crc32(crc, buf, len, table, data); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } -void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { +void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC) { assert_different_registers(crc, buf, len, table, tmp); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } z_llgc(tmp, Address(buf, (intptr_t)0)); // Current byte of input buffer (zero extended). Avoids garbage in upper half of register. update_byte_crc32(crc, tmp, table); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } +} + +void MacroAssembler::kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC) { + assert_different_registers(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byte_crc32(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } // diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp index 588bde6207e..9bb414da3a5 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -1009,22 +1009,35 @@ class MacroAssembler: public Assembler { int before = 0, int after = 0) PRODUCT_RETURN; // Emitters for CRC32 calculation. + // A note on invertCRC: + // Unfortunately, internal representation of crc differs between CRC32 and CRC32C. + // CRC32 holds it's current crc value in the externally visible representation. + // CRC32C holds it's current crc value in internal format, ready for updating. + // Thus, the crc value must be bit-flipped before updating it in the CRC32 case. + // In the CRC32C case, it must be bit-flipped when it is given to the outside world (getValue()). + // The bool invertCRC parameter indicates whether bit-flipping is required before updates. private: void fold_byte_crc32(Register crc, Register table, Register val, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp); + void update_byte_crc32( Register crc, Register val, Register table); void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC); + Register data); void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc, Register t0, Register t1, Register t2, Register t3); public: - void update_byte_crc32( Register crc, Register val, Register table); - void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); + void kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC); + void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC); void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); // Emitters for BigInteger.multiplyToLen intrinsic // note: length of result array (zlen) is passed on the stack diff --git a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp index aadef1f9f1a..bcadfaf3919 100644 --- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -2310,26 +2310,25 @@ class StubGenerator: public StubCodeGenerator { } - - // Arguments: - // Z_ARG1 - int crc - // Z_ARG2 - byte* buf - // Z_ARG3 - int length (of buffer) - // - // Result: - // Z_RET - int crc result - // - // Compute CRC32 function. - address generate_CRC32_updateBytes(const char* name) { - __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + /** + * Arguments: + * + * Inputs: + * Z_ARG1 - int crc + * Z_ARG2 - byte* buf + * Z_ARG3 - int length (of buffer) + * + * Result: + * Z_RET - int crc result + **/ + // Compute CRC function (generic, for all polynomials). + void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) { // arguments to kernel_crc32: Register crc = Z_ARG1; // Current checksum, preset by caller or result from previous call, int. Register data = Z_ARG2; // source byte array Register dataLen = Z_ARG3; // #bytes to process, int - Register table = Z_ARG4; // crc table address +// Register table = Z_ARG4; // crc table address. Preloaded and passed in by caller. const Register t0 = Z_R10; // work reg for kernel* emitters const Register t1 = Z_R11; // work reg for kernel* emitters const Register t2 = Z_R12; // work reg for kernel* emitters @@ -2341,16 +2340,50 @@ class StubGenerator: public StubCodeGenerator { // Crc used as int. __ z_llgfr(dataLen, dataLen); - StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, invertCRC); __ z_lmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 back from stack. __ resize_frame(+(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_llgfr(Z_RET, crc); // Updated crc is function result. No copying required, just zero upper 32 bits. __ z_br(Z_R14); // Result already in Z_RET == Z_ARG1. + } + + + // Compute CRC32 function. + address generate_CRC32_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32Intrinsics, "should not generate this stub (%s) with CRC32 intrinsics disabled", name); + + BLOCK_COMMENT("CRC32_updateBytes {"); + Register table = Z_ARG4; // crc32 table address. + StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, true); + BLOCK_COMMENT("} CRC32_updateBytes"); + + return __ addr_at(start_off); + } + + + // Compute CRC32C function. + address generate_CRC32C_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32CIntrinsics, "should not generate this stub (%s) with CRC32C intrinsics disabled", name); + + BLOCK_COMMENT("CRC32C_updateBytes {"); + Register table = Z_ARG4; // crc32c table address. + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, false); + BLOCK_COMMENT("} CRC32C_updateBytes"); return __ addr_at(start_off); } @@ -2421,9 +2454,13 @@ class StubGenerator: public StubCodeGenerator { // Entry points that are platform specific. if (UseCRC32Intrinsics) { - // We have no CRC32 table on z/Architecture. - StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; - StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; + StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + } + + if (UseCRC32CIntrinsics) { + StubRoutines::_crc32c_table_addr = (address)StubRoutines::zarch::_crc32c_table; + StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes"); } // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp index e99eb48035a..ab167d9030f 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -42,14 +42,15 @@ int StubRoutines::zarch::_atomic_memory_operation_lock = StubRoutines::zarch::un #define __ masm-> -void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { +void StubRoutines::zarch::generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents) { + __ load_absolute_address(table, table_addr); - __ load_absolute_address(table, StubRoutines::_crc_table_adr); #ifdef ASSERT - assert(_crc_table_adr != NULL, "CRC lookup table address must be initialized by now"); + assert(table_addr != NULL, "CRC lookup table address must be initialized by now"); + assert(*((uint32_t*)(table_addr+4)) == (uint32_t)table_contents, "Bad CRC lookup table: 0x%8.8x, expected 0x%8.8x", *((uint32_t*)(table_addr+4)), (uint32_t)table_contents); { Label L; - __ load_const_optimized(Z_R0, StubRoutines::_crc_table_adr); + __ load_const_optimized(Z_R0, table_addr); __ z_cgr(table, Z_R0); // safety net __ z_bre(L); __ z_illtrap(); @@ -58,7 +59,7 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg } { Label L; - __ load_const_optimized(Z_R0, 0x77073096UL); + __ load_const_optimized(Z_R0, table_contents); // crc_table: data @ offset(4) __ z_cl(Z_R0, Address(table, 4)); // safety net __ z_bre(L); __ z_l(Z_R0, Address(table, 4)); // Load data from memory, we know the constant we compared against. @@ -69,6 +70,17 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg #endif } +void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0x77073096UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc_table_adr, table_contents); +} + +void StubRoutines::zarch::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0xf26b8303UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc32c_table_addr, table_contents); +} + + // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. void StubRoutines::zarch::generate_load_trot_table_addr(MacroAssembler* masm, Register table) { @@ -128,440 +140,590 @@ jlong StubRoutines::zarch::_trot_table[TROT_COLUMN_SIZE] = { }; -// crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h juint StubRoutines::zarch::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::zarch::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp index d33cf9cfc7a..b2509b23094 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -72,6 +72,7 @@ class zarch { static address _partial_subtype_check; static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static address _trot_table_addr; @@ -91,7 +92,9 @@ class zarch { static address partial_subtype_check() { return _partial_subtype_check; } + static void generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table); // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static void generate_load_trot_table_addr(MacroAssembler* masm, Register table); diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp index e4f74df51e3..60d6070204d 100644 --- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -1964,7 +1964,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1); + __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true); // Restore caller sp for c2i case. __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. @@ -2020,10 +2020,10 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off BLOCK_COMMENT("CRC32_updateByteBuffer {"); __ z_llgf(crc, 5*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process - } else { // Used for "updateBytes update". + } else { // Used for "updateBytes update". // crc @ (SP + 4W) (32bit) // buf @ (SP + 3W) (64bit ptr to byte array) // off @ (SP + 2W) (32bit) @@ -2031,7 +2031,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off + base_offset BLOCK_COMMENT("CRC32_updateBytes {"); __ z_llgf(crc, 4*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); @@ -2041,7 +2041,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true); __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. // Restore caller sp for c2i case. @@ -2060,8 +2060,73 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported + +// Method entry for static native methods: +// int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int len) +// int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int len) address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + + if (UseCRC32CIntrinsics) { + uint64_t entry_off = __ offset(); + + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte array + const Register dataLen = Z_ARG3; // source data len + const Register table = Z_ARG4; // address of crc32 table + const Register t0 = Z_R10; // work reg for kernel* emitters + const Register t1 = Z_R11; // work reg for kernel* emitters + const Register t2 = Z_R12; // work reg for kernel* emitters + const Register t3 = Z_R13; // work reg for kernel* emitters + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct". + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + __ z_llgf(crc, 5*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process + } else { // Used for "updateBytes update". + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + BLOCK_COMMENT("CRC32C_updateBytes {"); + __ z_llgf(crc, 4*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process + __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. + __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false); + __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + + __ z_br(Z_R14); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return __ addr_at(entry_off); + } + return NULL; } diff --git a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp index 55dbd30aec8..6350c0b9b8f 100644 --- a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp @@ -111,13 +111,23 @@ void VM_Version::initialize() { ContendedPaddingWidth = cache_line_size; } - // On z/Architecture, the CRC32 intrinsics had to be implemented "by hand". - // They cannot be based on the CHECKSUM instruction which has been there - // since the very beginning (of z/Architecture). It computes "some kind of" a checksum - // which has nothing to do with the CRC32 algorithm. + // On z/Architecture, the CRC32/CRC32C intrinsics are implemented "by hand". + // TODO: Provide implementation based on the vector instructions available from z13. + // Note: The CHECKSUM instruction, which has been there since the very beginning + // (of z/Architecture), computes "some kind of" a checksum. + // It has nothing to do with the CRC32 algorithm. if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); + } // On z/Architecture, we take UseAES as the general switch to enable/disable the AES intrinsics. // The specific, and yet to be defined, switches UseAESxxxIntrinsics will then be set @@ -195,11 +205,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); } diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 731b9efc96c..2aee2263300 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -212,7 +212,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: -#ifdef SPARC +#if defined(SPARC) || defined(S390) case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: #endif From 1e8667e33466dc07f99c85ca24aaeff258c13c16 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Wed, 8 Mar 2017 15:48:41 -0800 Subject: [PATCH 46/86] 8176403: [TESTBUG] gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA is referencing no longer existing group Changed to use correct test library path Reviewed-by: dholmes, dcubed --- .../TestSmallInitialHeapWithLargePageAndNUMA.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java b/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java index fdfe66a5a4c..009d129897e 100644 --- a/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java +++ b/hotspot/test/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @requires os.family == "linux" * @requires vm.gc.Parallel * @summary Check large pages and NUMA are working together via the output message. - * @library /testlibrary /test/lib /test/lib/share/classes + * @library /test/lib * @modules java.base/jdk.internal.misc * @modules java.management/sun.management * @build TestSmallInitialHeapWithLargePageAndNUMA @@ -35,8 +35,8 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UseHugeTLBFS -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestSmallInitialHeapWithLargePageAndNUMA */ -import jdk.test.lib.ProcessTools; -import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; import sun.hotspot.WhiteBox; public class TestSmallInitialHeapWithLargePageAndNUMA { From 0171aad88e8871a06799c3401ce431551db7dace Mon Sep 17 00:00:00 2001 From: Lutz Schmidt Date: Wed, 8 Mar 2017 17:01:13 -0800 Subject: [PATCH 47/86] 8175369: [ppc] Provide intrinsic implementation for CRC32C Reviewed-by: mdoerr, simonis, kvn --- .../src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp | 9 +- .../src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp | 83 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 114 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp | 32 +- hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 114 +- hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp | 7 +- .../src/cpu/ppc/vm/stubRoutines_ppc_64.cpp | 1031 ++++++++++------- .../vm/templateInterpreterGenerator_ppc.cpp | 88 +- hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 30 +- hotspot/src/share/vm/c1/c1_Compiler.cpp | 2 +- 10 files changed, 963 insertions(+), 547 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp index 127403fde2f..b64e3cd8a4a 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -3177,9 +3177,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr(), R0); - __ nand(crc, crc, crc); // ~crc - __ update_byte_crc32(crc, val, res); - __ nand(res, crc, crc); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ mr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index 86eacda77f1..045e7b0184c 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -63,18 +63,6 @@ void LIRItem::load_nonconstant() { } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_register()) { - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } else { - // Constants or memory get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } -} - - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -1419,10 +1407,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { arg2 = cc->at(1), arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1434,6 +1421,66 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } } +void LIRGenerator::do_update_CRC32C(Intrinsic* x) { + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem len(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + LIR_Address* a = NULL; + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + __ add(index, LIR_OprFact::intptrConst(offset), index); + a = new LIR_Address(base_op, index, T_BYTE); + } else { + a = new LIR_Address(base_op, offset, T_BYTE); + } + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for(x->type()); + + LIR_Opr arg1 = cc->at(0), + arg2 = cc->at(1), + arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } +} + void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { assert(x->number_of_arguments() == 3, "wrong type"); assert(UseFMA, "Needs FMA instructions support."); @@ -1460,7 +1507,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - -void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); -} diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index a5d5613a414..c81cd56acdd 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -4092,7 +4092,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param table register pointing to CRC table */ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool loopAlignment, bool invertCRC) { + Register data, bool loopAlignment) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -4103,10 +4103,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register clrldi_(len, len, 32); // Enforce 32 bit. Anything to do? beq(CCR0, L_done); - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - mtctr(len); align(mainLoop_alignment); BIND(L_mainLoop); @@ -4115,10 +4111,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register update_byte_crc32(crc, data, table); bdnz(L_mainLoop); // Iterate. - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - bind(L_done); } @@ -4175,7 +4167,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, Register t0, Register t1, Register t2, Register t3, - Register tc0, Register tc1, Register tc2, Register tc3) { + Register tc0, Register tc1, Register tc2, Register tc3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -4189,14 +4182,16 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len const int complexThreshold = 2*mainLoop_stepping; // Don't test for len <= 0 here. This pathological case should not occur anyway. - // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles. - // The situation itself is detected and handled correctly by the conditional branches - // following aghi(len, -stepping) and aghi(len, +stepping). + // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles + // for all well-behaved cases. The situation itself is detected and handled correctly + // within update_byteLoop_crc32. assert(tailLoop_stepping == 1, "check tailLoop_stepping!"); BLOCK_COMMENT("kernel_crc32_2word {"); - nand(crc, crc, crc); // ~c + if (invertCRC) { + nand(crc, crc, crc); // 1s complement of crc + } // Check for short (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4253,9 +4248,11 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // Process last few (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4346,9 +4346,11 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // Process last few ( -// CRC32 Intrinsics. +// CRC32(C) Intrinsics. +void StubRoutines::ppc64::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + __ load_const_optimized(table, StubRoutines::_crc32c_table_addr, R0); +} + void StubRoutines::ppc64::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { __ load_const_optimized(table, StubRoutines::_crc_table_adr, R0); } @@ -347,441 +351,592 @@ juint* StubRoutines::ppc64::generate_crc_barret_constants() { * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h */ juint StubRoutines::ppc64::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::ppc64::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; juint* StubRoutines::ppc64::_constants = StubRoutines::ppc64::generate_crc_constants(); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 7a0274d6156..221373b72d1 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2016 SAP SE. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -1895,7 +1895,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp); + __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -1911,6 +1911,10 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { return NULL; } +// TODO: generate_CRC32_updateBytes_entry and generate_CRC32C_updateBytes_entry are identical +// except for using different crc tables and some block comment strings. +// We should provide a common implementation. + // CRC32 Intrinsics. /** * Method entry for static native methods: @@ -1987,7 +1991,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // Performance measurements show the 1word and 2word variants to be almost equivalent, // with very light advantages for the 1word variant. We chose the 1word variant for // code compactness. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -2003,8 +2007,84 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported +// CRC32C Intrinsics. +/** + * Method entry for static native methods: + * int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int len) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int len) + **/ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + if (UseCRC32CIntrinsics) { + address start = __ pc(); // Remember stub start address (is rtn value). + + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; // address of java byte array + const Register dataLen = R5_ARG3; // source data len + const Register table = R6_ARG4; // address of crc32c table + + const Register t0 = R9; // scratch registers for crc calculation + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + + const Register tc0 = R2; // registers to hold pre-calculated column addresses + const Register tc1 = R7; + const Register tc2 = R8; + const Register tc3 = table; // table address is reconstructed at the end of kernel_crc32_* emitters + + const Register tmp = t0; // Only used very locally to calculate byte buffer address. + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer". + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ lwz( crc, 5*wordSize, argP); // current crc state + __ add( data, data, tmp); // Add byte buffer offset. + } else { // Used for "updateBytes update". + BLOCK_COMMENT("CRC32C_updateBytes {"); + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ add( data, data, tmp); // add byte buffer offset + __ lwz( crc, 4*wordSize, argP); // current crc state + __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + + // Performance measurements show the 1word and 2word variants to be almost equivalent, + // with very light advantages for the 1word variant. We chose the 1word variant for + // code compactness. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, false); + + // Restore caller sp for c2i case and return. + __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. + __ blr(); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return start; + } + return NULL; } diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 5e8be1425fa..2f1afee0299 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -172,18 +172,27 @@ void VM_Version::initialize() { assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Implementation does not use any of the vector instructions - // available with Power8. Their exploitation is still pending. + // If defined(VM_LITTLE_ENDIAN) and running on Power8 or newer hardware, + // the implementation uses the vector instructions available with Power8. + // In all other cases, the implementation uses only generally available instructions. if (!UseCRC32Intrinsics) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } } - if (UseCRC32CIntrinsics) { - if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) - warning("CRC32C intrinsics are not available on this CPU"); - FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + // Implementation does not use any of the vector instructions available with Power8. + // Their exploitation is still pending (aka "work in progress"). + if (!UseCRC32CIntrinsics) { + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); } // The AES intrinsic stubs require AES instruction support. @@ -245,11 +254,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 2aee2263300..1c52e80bad5 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -212,7 +212,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: -#if defined(SPARC) || defined(S390) +#if defined(SPARC) || defined(S390) || defined(PPC64) case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: #endif From 6fdf39662440c5d1e0c91f49a4f1b15ad4b08dce Mon Sep 17 00:00:00 2001 From: Alexander Harlap Date: Thu, 9 Mar 2017 10:48:44 +0100 Subject: [PATCH 48/86] 8165674: G1CMMarkStack::out_of_memory possibly redundant Remove the redundant G1CMMarkStack::_out_of_memory member. Reviewed-by: kbarrett, tschatzl --- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 32 ++++++------------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 10 ++---- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 6a5dedbdbda..d64714cb435 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -136,7 +136,6 @@ G1CMMarkStack::G1CMMarkStack() : _max_chunk_capacity(0), _base(NULL), _chunk_capacity(0), - _out_of_memory(false), _should_expand(false) { set_empty(); } @@ -278,11 +277,10 @@ bool G1CMMarkStack::par_push_chunk(oop* ptr_arr) { if (new_chunk == NULL) { // Did not get a chunk from the free list. Allocate from backing memory. new_chunk = allocate_new_chunk(); - } - if (new_chunk == NULL) { - _out_of_memory = true; - return false; + if (new_chunk == NULL) { + return false; + } } Copy::conjoint_memory_atomic(ptr_arr, new_chunk->data, OopsPerChunk * sizeof(oop)); @@ -308,7 +306,6 @@ bool G1CMMarkStack::par_pop_chunk(oop* ptr_arr) { void G1CMMarkStack::set_empty() { _chunks_in_chunk_list = 0; _hwm = 0; - clear_out_of_memory(); _chunk_list = NULL; _free_list = NULL; } @@ -592,14 +589,10 @@ void G1ConcurrentMark::reset() { } -void G1ConcurrentMark::reset_marking_state(bool clear_overflow) { +void G1ConcurrentMark::reset_marking_state() { _global_mark_stack.set_should_expand(has_overflown()); - _global_mark_stack.set_empty(); // Also clears the overflow stack's overflow flag - if (clear_overflow) { - clear_has_overflown(); - } else { - assert(has_overflown(), "pre-condition"); - } + _global_mark_stack.set_empty(); + clear_has_overflown(); _finger = _heap_start; for (uint i = 0; i < _max_worker_id; ++i) { @@ -883,7 +876,7 @@ void G1ConcurrentMark::enter_first_sync_barrier(uint worker_id) { // not clear the overflow flag since we rely on it being true when // we exit this method to abort the pause and restart concurrent // marking. - reset_marking_state(true /* clear_overflow */); + reset_marking_state(); log_info(gc, marking)("Concurrent Mark reset for overflow"); } @@ -1749,14 +1742,8 @@ void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // oop closures will set the has_overflown flag if we overflow the // global marking stack. - assert(_global_mark_stack.is_out_of_memory() || _global_mark_stack.is_empty(), - "Mark stack should be empty (unless it is out of memory)"); - - if (_global_mark_stack.is_out_of_memory()) { - // This should have been done already when we tried to push an - // entry on to the global mark stack. But let's do it again. - set_has_overflown(); - } + assert(has_overflown() || _global_mark_stack.is_empty(), + "Mark stack should be empty (unless it has overflown)"); assert(rp->num_q() == active_workers, "why not"); @@ -2931,7 +2918,6 @@ void G1CMTask::do_marking_step(double time_target_ms, guarantee(_cm->mark_stack_empty(), "only way to reach here"); guarantee(_task_queue->size() == 0, "only way to reach here"); guarantee(!_cm->has_overflown(), "only way to reach here"); - guarantee(!_cm->mark_stack_overflow(), "only way to reach here"); } else { // Apparently there's more work to do. Let's abort this task. It // will restart it and we can hopefully find more things to do. diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 277e9fe2596..fa0bfc58e2a 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -192,8 +192,6 @@ private: // NULL if out of memory. OopChunk* allocate_new_chunk(); - volatile bool _out_of_memory; - // Atomically add the given chunk to the list. void add_chunk_to_list(OopChunk* volatile* list, OopChunk* elem); // Atomically remove and return a chunk from the given list. Returns NULL if the @@ -240,9 +238,6 @@ private: size_t capacity() const { return _chunk_capacity; } - bool is_out_of_memory() const { return _out_of_memory; } - void clear_out_of_memory() { _out_of_memory = false; } - bool should_expand() const { return _should_expand; } void set_should_expand(bool value) { _should_expand = value; } @@ -432,7 +427,7 @@ protected: // Resets all the marking data structures. Called when we have to restart // marking or when marking completes (via set_non_marking_state below). - void reset_marking_state(bool clear_overflow = true); + void reset_marking_state(); // We do this after we're done with marking so that the marking data // structures are initialized to a sensible and predictable state. @@ -543,7 +538,6 @@ public: } size_t mark_stack_size() { return _global_mark_stack.size(); } size_t partial_mark_stack_size_target() { return _global_mark_stack.capacity()/3; } - bool mark_stack_overflow() { return _global_mark_stack.is_out_of_memory(); } bool mark_stack_empty() { return _global_mark_stack.is_empty(); } G1CMRootRegions* root_regions() { return &_root_regions; } From 5806258936802afae545b3f72dd5f204291f60cd Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 8 Mar 2017 19:25:15 +0100 Subject: [PATCH 49/86] 8176140: 8176140-Crashes-or-timeouts-during-error-reporting-may-lead-to-infinitely-repeated-error-logs-until-ErrorLogTimeout-is-hit Reviewed-by: cjplummer, dholmes --- hotspot/src/share/vm/utilities/vmError.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index ee8d028f97c..84e63d89e04 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -1323,6 +1323,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt } report(&log, true); + log_done = true; _current_step = 0; _current_step_info = ""; @@ -1343,7 +1344,6 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt } log.set_fd(-1); - log_done = true; } static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay From ade6d7cd180f0b03d9417c2919a848453ce22e7b Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Thu, 9 Mar 2017 15:00:23 -0800 Subject: [PATCH 50/86] 8164038: Missing volatile keyword at CardTableRS::write_ref_field_gc_par() Reviewed-by: tschatzl, kbarrett --- hotspot/src/share/vm/gc/shared/cardTableRS.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp index eabc5156902..0c87676ce02 100644 --- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp +++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -282,7 +282,7 @@ void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) { // cur-younger-gen ==> cur_younger_gen // cur_youngergen_and_prev_nonclean_card ==> no change. void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) { - jbyte* entry = _ct_bs->byte_for(field); + volatile jbyte* entry = _ct_bs->byte_for(field); do { jbyte entry_val = *entry; // We put this first because it's probably the most common case. From 8a5f33bd16268771e08f2cc16ee1c6711690c76d Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 10 Mar 2017 08:04:17 -0500 Subject: [PATCH 51/86] 8172514: Stop checking for duplicate packages in the JVM_DefineModule() package list Use GrowableArray append() instead of append_if_missing() to stop searching for duplicates Reviewed-by: redestad, coleenp, dholmes, gtriantafill --- hotspot/src/share/vm/classfile/modules.cpp | 17 +++-------------- hotspot/src/share/vm/classfile/modules.hpp | 1 - .../test/runtime/modules/JVMDefineModule.java | 11 ----------- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp index 0dbe2fd3cef..78fcef54283 100644 --- a/hotspot/src/share/vm/classfile/modules.cpp +++ b/hotspot/src/share/vm/classfile/modules.cpp @@ -162,8 +162,7 @@ static void define_javabase_module(jobject module, jstring version, } - // Check that the list of packages has no duplicates and that the - // packages are syntactically ok. + // Check that the packages are syntactically ok. GrowableArray* pkg_list = new GrowableArray(num_packages); for (int x = 0; x < num_packages; x++) { const char *package_name = packages[x]; @@ -172,12 +171,7 @@ static void define_javabase_module(jobject module, jstring version, err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name)); } Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK); - // append_if_missing() returns FALSE if entry already exists. - if (!pkg_list->append_if_missing(pkg_symbol)) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - err_msg("Duplicate package name: %s for module " JAVA_BASE_NAME, - package_name)); - } + pkg_list->append(pkg_symbol); } // Validate java_base's loader is the boot loader. @@ -340,12 +334,7 @@ void Modules::define_module(jobject module, jstring version, } Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK); - // append_if_missing() returns FALSE if entry already exists. - if (!pkg_list->append_if_missing(pkg_symbol)) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - err_msg("Duplicate package name: %s for module %s", - package_name, module_name)); - } + pkg_list->append(pkg_symbol); } ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK); diff --git a/hotspot/src/share/vm/classfile/modules.hpp b/hotspot/src/share/vm/classfile/modules.hpp index 1759b9338fc..ce7d5be032e 100644 --- a/hotspot/src/share/vm/classfile/modules.hpp +++ b/hotspot/src/share/vm/classfile/modules.hpp @@ -45,7 +45,6 @@ public: // * Module's Class loader has already defined types for any of the module's packages // * Module_name is syntactically bad // * Packages contains an illegal package name - // * Packages contains a duplicate package name // * A package already exists in another module for this class loader // * Module is an unnamed module // * num_packages is negative diff --git a/hotspot/test/runtime/modules/JVMDefineModule.java b/hotspot/test/runtime/modules/JVMDefineModule.java index 5ef669ed93b..d8630bf358c 100644 --- a/hotspot/test/runtime/modules/JVMDefineModule.java +++ b/hotspot/test/runtime/modules/JVMDefineModule.java @@ -105,17 +105,6 @@ public class JVMDefineModule { } } - // Duplicates in package list, expect an IAE - m = ModuleHelper.ModuleObject("module.x", cl, new String[] { "mypackage4", "mypackage5" }); - try { - ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackage4", "mypackage5", "mypackage4" }); - throw new RuntimeException("Failed to get IAE for duplicate packages"); - } catch(IllegalArgumentException e) { - if (!e.getMessage().contains("Duplicate package name")) { - throw new RuntimeException("Failed to get expected IAE message for duplicate package: " + e.getMessage()); - } - } - // Empty entry in package list, expect an IAE m = ModuleHelper.ModuleObject("module.y", cl, new String[] { "mypackageX", "mypackageY" }); try { From e04f906b93a71ecf1f2493aa276d7a7af808c6ef Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Fri, 10 Mar 2017 12:58:37 -0500 Subject: [PATCH 52/86] 8175300: Enable artifact resolution for jtreg tests Reviewed-by: ihse, gtriantafill --- hotspot/test/TEST.groups | 2 + .../test/applications/scimark/Scimark.java | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 hotspot/test/applications/scimark/Scimark.java diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index a8827168292..4d25f0f90c4 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -38,6 +38,7 @@ hotspot_serviceability = \ hotspot_misc = \ / \ + -applications \ -:hotspot_compiler \ -:hotspot_gc \ -:hotspot_runtime \ @@ -228,3 +229,4 @@ hotspot_runtime_minimalvm = \ runtime/MinimalVM \ runtime/ErrorHandling \ runtime/logging + diff --git a/hotspot/test/applications/scimark/Scimark.java b/hotspot/test/applications/scimark/Scimark.java new file mode 100644 index 00000000000..6964c21518b --- /dev/null +++ b/hotspot/test/applications/scimark/Scimark.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /test/lib + * @run driver Scimark + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.artifacts.Artifact; +import jdk.test.lib.artifacts.ArtifactResolver; +import java.nio.file.Path; +import java.util.HashMap; + +@Artifact(organization = "gov.nist.math", name = "scimark", revision = "2.0", extension = "zip") +public class Scimark { + public static void main(String... args) throws Exception { + HashMap artifacts = ArtifactResolver.resolve(Scimark.class); + + OutputAnalyzer output = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder( + "-cp", artifacts.get("gov.nist.math.scimark-2.0").toString(), + "jnt.scimark2.commandline", "-large") + .start()); + output.shouldHaveExitValue(0); + } +} From f5777dc9bdd88dc3f066eee923fcfe27a0ab1418 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 3 Mar 2017 23:08:35 -0800 Subject: [PATCH 53/86] 8005165: Remove CPU-dependent code in self-patching vtables Reviewed-by: coleenp, stuefe, jiangli --- .../aarch64/vm/metaspaceShared_aarch64.cpp | 126 ------- .../src/cpu/arm/vm/metaspaceShared_arm.cpp | 99 ------ .../src/cpu/ppc/vm/metaspaceShared_ppc.cpp | 78 ---- .../src/cpu/s390/vm/metaspaceShared_s390.cpp | 76 ---- .../cpu/sparc/vm/metaspaceShared_sparc.cpp | 120 ------- .../src/cpu/x86/vm/metaspaceShared_x86_32.cpp | 124 ------- .../src/cpu/x86/vm/metaspaceShared_x86_64.cpp | 114 ------ .../src/cpu/zero/vm/metaspaceShared_zero.cpp | 37 -- .../share/vm/classfile/systemDictionary.cpp | 5 - hotspot/src/share/vm/memory/metaspace.cpp | 5 +- hotspot/src/share/vm/memory/metaspace.hpp | 3 +- .../src/share/vm/memory/metaspaceShared.cpp | 335 +++++++++++++----- .../src/share/vm/memory/metaspaceShared.hpp | 30 +- hotspot/src/share/vm/memory/universe.cpp | 24 -- hotspot/src/share/vm/memory/universe.hpp | 5 +- hotspot/src/share/vm/oops/constantPool.cpp | 3 +- hotspot/src/share/vm/oops/constantPool.hpp | 7 +- hotspot/src/share/vm/oops/klass.cpp | 3 +- hotspot/src/share/vm/oops/method.cpp | 14 +- hotspot/src/share/vm/oops/method.hpp | 7 +- 20 files changed, 269 insertions(+), 946 deletions(-) delete mode 100644 hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp delete mode 100644 hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp delete mode 100644 hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp delete mode 100644 hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp delete mode 100644 hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp delete mode 100644 hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp delete mode 100644 hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp delete mode 100644 hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp diff --git a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp deleted file mode 100644 index 72af9a84f04..00000000000 --- a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -extern "C" { - void aarch64_prolog(void); -} - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - -#ifdef BUILTIN_SIM - // Write a dummy word to the writable shared metaspace. - // MetaspaceShared::initialize_shared_spaces will fill it with the - // address of aarch64_prolog(). - address *prolog_ptr = (address*)*md_top; - *(intptr_t *)(*md_top) = (intptr_t)0; - (*md_top) += sizeof(intptr_t); -#endif - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // We're called directly from C code. -#ifdef BUILTIN_SIM - __ c_stub_prolog(8, 0, MacroAssembler::ret_type_integral, prolog_ptr); -#endif - // Load rscratch1 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - __ mov(rscratch1, (i << 8) + j); - __ b(common_code); - } - } - - __ bind(common_code); - - Register tmp0 = r10, tmp1 = r11; // AAPCS64 temporary registers - __ enter(); - __ lsr(tmp0, rscratch1, 8); // isolate vtable identifier. - __ mov(tmp1, (address)vtbl_list); // address of list of vtable pointers. - __ ldr(tmp1, Address(tmp1, tmp0, Address::lsl(LogBytesPerWord))); // get correct vtable pointer. - __ str(tmp1, Address(c_rarg0)); // update vtable pointer in obj. - __ add(rscratch1, tmp1, rscratch1, ext::uxtb, LogBytesPerWord); // address of real method pointer. - __ ldr(rscratch1, Address(rscratch1)); // get real method pointer. - __ blrt(rscratch1, 8, 0, 1); // jump to the real method. - __ leave(); - __ ret(lr); - - *mc_top = (char*)__ pc(); -} - -#ifdef BUILTIN_SIM -void MetaspaceShared::relocate_vtbl_list(char **buffer) { - void **sim_entry = (void**)*buffer; - *sim_entry = (void*)aarch64_prolog; - *buffer += sizeof(intptr_t); -} -#endif diff --git a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp b/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp deleted file mode 100644 index 1cda4dff24e..00000000000 --- a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "assembler_arm.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - for (int i = 0; i < vtbl_list_size; ++i) { - Label common_code; - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*) __ pc(); - __ mov(Rtemp, j); // Rtemp contains an index of a virtual method in the table - __ b(common_code); - } - - InlinedAddress vtable_address((address)&vtbl_list[i]); - __ bind(common_code); - const Register tmp2 = AARCH64_ONLY(Rtemp2) NOT_AARCH64(R4); - assert_different_registers(Rtemp, tmp2); -#ifndef AARCH64 - __ push(tmp2); -#endif // !AARCH64 - // Do not use ldr_global since the code must be portable across all ARM architectures - __ ldr_literal(tmp2, vtable_address); - __ ldr(tmp2, Address(tmp2)); // get correct vtable address - __ ldr(Rtemp, Address::indexed_ptr(tmp2, Rtemp)); // get real method pointer - __ str(tmp2, Address(R0)); // update vtable. R0 = "this" -#ifndef AARCH64 - __ pop(tmp2); -#endif // !AARCH64 - __ jump(Rtemp); - __ bind_literal(vtable_address); - } - - __ flush(); - *mc_top = (char*) __ pc(); -} diff --git a/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp b/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp deleted file mode 100644 index 6fd569a1122..00000000000 --- a/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - // There are more general problems with CDS on ppc, so I can not - // really test this. But having this instead of Unimplementd() allows - // us to pass TestOptionsWithRanges.java. - __ unimplemented(); -} - diff --git a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp b/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp deleted file mode 100644 index 8e7feacf527..00000000000 --- a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/codeBuffer.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size();. -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#undef __ -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - __ unimplemented(); -} diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp deleted file mode 100644 index cc0141c283e..00000000000 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - __ save(SP, -256, SP); - int offset = (i << 8) + j; - Register src = G0; - if (!Assembler::is_simm13(offset)) { - __ sethi(offset, L0); - src = L0; - offset = offset & ((1 << 10) - 1); - } - __ brx(Assembler::always, false, Assembler::pt, common_code); - - // Load L0 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[13..8] (6 bits) which virtual method table? - __ delayed()->or3(src, offset, L0); - } - } - - __ bind(common_code); - - // Expecting to be called with the "this" pointer in O0/I0 (where - // "this" is a Klass object). In addition, L0 was set (above) to - // identify the method and table. - - // Look up the correct vtable pointer. - - __ set((intptr_t)vtbl_list, L2); // L2 = address of new vtable list. - __ srl(L0, 8, L3); // Isolate L3 = vtable identifier. - __ sll(L3, LogBytesPerWord, L3); - __ ld_ptr(L2, L3, L3); // L3 = new (correct) vtable pointer. - __ st_ptr(L3, Address(I0, 0)); // Save correct vtable ptr in entry. - - // Restore registers and jump to the correct method; - - __ and3(L0, 255, L4); // Isolate L3 = method offset;. - __ sll(L4, LogBytesPerWord, L4); - __ ld_ptr(L3, L4, L4); // Get address of correct virtual method - __ jmpl(L4, 0, G0); // Jump to correct method. - __ delayed()->restore(); // Restore registers. - - __ flush(); - *mc_top = (char*)__ pc(); - - guarantee(*mc_top <= mc_end, "Insufficient space for method wrappers."); -} diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp deleted file mode 100644 index c2956a52a54..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load rax, with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - -#ifdef WIN32 - // Expecting to be called with "thiscall" conventions -- the arguments - // are on the stack, except that the "this" pointer is in rcx. -#else - // Expecting to be called with Unix conventions -- the arguments - // are on the stack, including the "this" pointer. -#endif - - // In addition, rax was set (above) to the offset of the method in the - // table. - -#ifdef WIN32 - __ push(rcx); // save "this" -#endif - __ mov(rcx, rax); - __ shrptr(rcx, 8); // isolate vtable identifier. - __ shlptr(rcx, LogBytesPerWord); - Address index(noreg, rcx, Address::times_1); - ExternalAddress vtbl((address)vtbl_list); - __ movptr(rdx, ArrayAddress(vtbl, index)); // get correct vtable address. -#ifdef WIN32 - __ pop(rcx); // restore "this" -#else - __ movptr(rcx, Address(rsp, BytesPerWord)); // fetch "this" -#endif - __ movptr(Address(rcx, 0), rdx); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, rdx); // address of real method pointer. - __ jmp(Address(rax, 0)); // get real method pointer. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp deleted file mode 100644 index 4ff6cc955d7..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load eax with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - - // Expecting to be called with "thiscall" convections -- the arguments - // are on the stack and the "this" pointer is in c_rarg0. In addition, rax - // was set (above) to the offset of the method in the table. - - __ push(c_rarg1); // save & free register - __ push(c_rarg0); // save "this" - __ mov(c_rarg0, rax); - __ shrptr(c_rarg0, 8); // isolate vtable identifier. - __ shlptr(c_rarg0, LogBytesPerWord); - __ lea(c_rarg1, ExternalAddress((address)vtbl_list)); // ptr to correct vtable list. - __ addptr(c_rarg1, c_rarg0); // ptr to list entry. - __ movptr(c_rarg1, Address(c_rarg1, 0)); // get correct vtable address. - __ pop(c_rarg0); // restore "this" - __ movptr(Address(c_rarg0, 0), c_rarg1); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, c_rarg1); // address of real method pointer. - __ pop(c_rarg1); // restore register. - __ movptr(rax, Address(rax, 0)); // get real method pointer. - __ jmp(rax); // jump to the real method. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp b/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp deleted file mode 100644 index 8cb5e15588f..00000000000 --- a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "assembler_zero.inline.hpp" -#include "memory/metaspaceShared.hpp" - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - ShouldNotCallThis(); -} diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 27624d50472..fca80937a0f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1348,11 +1348,6 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) { Klass* k = interfaces->at(index); - - // Note: can not use InstanceKlass::cast here because - // interfaces' InstanceKlass's C++ vtbls haven't been - // reinitialized yet (they will be once the interface classes - // are loaded) Symbol* name = k->name(); Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh)); if (k != i) { diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index db4bf613b60..fd88b6da9be 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -3781,7 +3781,10 @@ bool Metaspace::contains(const void* ptr) { if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(ptr)) { return true; } + return contains_non_shared(ptr); +} +bool Metaspace::contains_non_shared(const void* ptr) { if (using_class_space() && get_space_list(ClassType)->contains(ptr)) { return true; } diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp index 87ab90331b7..6edeb72ddd3 100644 --- a/hotspot/src/share/vm/memory/metaspace.hpp +++ b/hotspot/src/share/vm/memory/metaspace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -243,6 +243,7 @@ class Metaspace : public CHeapObj { void deallocate(MetaWord* ptr, size_t byte_size, bool is_class); static bool contains(const void* ptr); + static bool contains_non_shared(const void* ptr); void dump(outputStream* const out) const; diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 446517fd426..27030e8a341 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -40,8 +40,13 @@ #include "memory/metaspace.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" +#include "oops/instanceClassLoaderKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" +#include "oops/instanceRefKlass.hpp" +#include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +#include "oops/typeArrayKlass.hpp" #include "runtime/timerTrace.hpp" #include "runtime/os.hpp" #include "runtime/signature.hpp" @@ -229,85 +234,244 @@ static void rewrite_nofast_bytecodes_and_calculate_fingerprints() { } } -// Patch C++ vtable pointer in metadata. - -// Klass and other metadata objects contain references to c++ vtables in the -// JVM library. -// Fix them to point to our constructed vtables. However, don't iterate -// across the space while doing this, as that causes the vtables to be -// patched, undoing our useful work. Instead, iterate to make a list, -// then use the list to do the fixing. +// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables. +// (In GCC this is the field ::_vptr, i.e., first word in the object.) // -// Our constructed vtables: -// Dump time: -// 1. init_self_patching_vtbl_list: table of pointers to current virtual method addrs -// 2. generate_vtable_methods: create jump table, appended to above vtbl_list -// 3. patch_klass_vtables: for Klass list, patch the vtable entry in klass and -// associated metadata to point to jump table rather than to current vtbl -// Table layout: NOTE FIXED SIZE -// 1. vtbl pointers -// 2. #Klass X #virtual methods per Klass -// 1 entry for each, in the order: -// Klass1:method1 entry, Klass1:method2 entry, ... Klass1:method entry -// Klass2:method1 entry, Klass2:method2 entry, ... Klass2:method entry -// ... -// Klass:method1 entry, Klass:method2 entry, -// ... Klass:method entry -// Sample entry: (Sparc): -// save(sp, -256, sp) -// ba,pt common_code -// mov XXX, %L0 %L0 gets: Klass index <<8 + method index (note: max method index 255) +// Addresses of the vtables and the methods may be different across JVM runs, +// if libjvm.so is dynamically loaded at a different base address. // -// Restore time: -// 1. initialize_shared_space: reserve space for table -// 2. init_self_patching_vtbl_list: update pointers to NEW virtual method addrs in text +// To ensure that the Metadata objects in the CDS archive always have the correct vtable: // -// Execution time: -// First virtual method call for any object of these metadata types: -// 1. object->klass -// 2. vtable entry for that klass points to the jump table entries -// 3. branches to common_code with %O0/klass, %L0: Klass index <<8 + method index -// 4. common_code: -// Get address of new vtbl pointer for this Klass from updated table -// Update new vtbl pointer in the Klass: future virtual calls go direct -// Jump to method, using new vtbl pointer and method index +// + at dump time: we redirect the _vptr to point to our own vtables inside +// the CDS image +// + at run time: we clone the actual contents of the vtables from libjvm.so +// into our own tables. +// Currently, the archive contain ONLY the following types of objects that have C++ vtables. +#define CPP_VTABLE_PATCH_TYPES_DO(f) \ + f(ConstantPool) \ + f(InstanceKlass) \ + f(InstanceClassLoaderKlass) \ + f(InstanceMirrorKlass) \ + f(InstanceRefKlass) \ + f(Method) \ + f(ObjArrayKlass) \ + f(TypeArrayKlass) -static void* find_matching_vtbl_ptr(void** vtbl_list, void* new_vtable_start, void* obj) { - void* old_vtbl_ptr = *(void**)obj; - for (int i = 0; i < MetaspaceShared::vtbl_list_size; i++) { - if (vtbl_list[i] == old_vtbl_ptr) { - return (void**)new_vtable_start + i * MetaspaceShared::num_virtuals; - } +class CppVtableInfo { + intptr_t _vtable_size; + intptr_t _cloned_vtable[1]; +public: + static int num_slots(int vtable_size) { + return 1 + vtable_size; // Need to add the space occupied by _vtable_size; } - ShouldNotReachHere(); - return NULL; + int vtable_size() { return int(uintx(_vtable_size)); } + void set_vtable_size(int n) { _vtable_size = intptr_t(n); } + intptr_t* cloned_vtable() { return &_cloned_vtable[0]; } + void zero() { memset(_cloned_vtable, 0, sizeof(intptr_t) * vtable_size()); } + // Returns the address of the next CppVtableInfo that can be placed immediately after this CppVtableInfo + intptr_t* next(int vtable_size) { + return &_cloned_vtable[vtable_size]; + } +}; + +template class CppVtableCloner : public T { + static intptr_t* vtable_of(Metadata& m) { + return *((intptr_t**)&m); + } + static CppVtableInfo* _info; + + static int get_vtable_length(const char* name); + +public: + // Allocate and initialize the C++ vtable, starting from top, but do not go past end. + static intptr_t* allocate(const char* name, intptr_t* top, intptr_t* end); + + // Clone the vtable to ... + static intptr_t* clone_vtable(const char* name, CppVtableInfo* info); + + static void zero_vtable_clone() { + assert(DumpSharedSpaces, "dump-time only"); + _info->zero(); + } + + // Switch the vtable pointer to point to the cloned vtable. + static void patch(Metadata* obj) { + assert(DumpSharedSpaces, "dump-time only"); + *(void**)obj = (void*)(_info->cloned_vtable()); + } + + static bool is_valid_shared_object(const T* obj) { + intptr_t* vptr = *(intptr_t**)obj; + return vptr == _info->cloned_vtable(); + } +}; + +template CppVtableInfo* CppVtableCloner::_info = NULL; + +template +intptr_t* CppVtableCloner::allocate(const char* name, intptr_t* top, intptr_t* end) { + int n = get_vtable_length(name); + _info = (CppVtableInfo*)top; + intptr_t* next = _info->next(n); + + if (next > end) { + report_out_of_shared_space(SharedMiscData); + } + _info->set_vtable_size(n); + + intptr_t* p = clone_vtable(name, _info); + assert(p == next, "must be"); + + return p; } -// Assumes the vtable is in first slot in object. -static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) { +template +intptr_t* CppVtableCloner::clone_vtable(const char* name, CppVtableInfo* info) { + if (!DumpSharedSpaces) { + assert(_info == 0, "_info is initialized only at dump time"); + _info = info; // Remember it -- it will be used by MetaspaceShared::is_valid_shared_method() + } + T tmp; // Allocate temporary dummy metadata object to get to the original vtable. + int n = info->vtable_size(); + intptr_t* srcvtable = vtable_of(tmp); + intptr_t* dstvtable = info->cloned_vtable(); + + // We already checked (and, if necessary, adjusted n) when the vtables were allocated, so we are + // safe to do memcpy. + if (PrintSharedSpaces) { + tty->print_cr("Copying %3d vtable entries for %s", n, name); + } + memcpy(dstvtable, srcvtable, sizeof(intptr_t) * n); + return dstvtable + n; +} + +// To determine the size of the vtable for each type, we use the following +// trick by declaring 2 subclasses: +// +// class CppVtableTesterA: public InstanceKlass {virtual int last_virtual_method() {return 1;} }; +// class CppVtableTesterB: public InstanceKlass {virtual void* last_virtual_method() {return NULL}; }; +// +// CppVtableTesterA and CppVtableTesterB's vtables have the following properties: +// - Their size (N+1) is exactly one more than the size of InstanceKlass's vtable (N) +// - The first N entries have are exactly the same as in InstanceKlass's vtable. +// - Their last entry is different. +// +// So to determine the value of N, we just walk CppVtableTesterA and CppVtableTesterB's tables +// and find the first entry that's different. +// +// This works on all C++ compilers supported by Oracle, but you may need to tweak it for more +// esoteric compilers. + +template class CppVtableTesterB: public T { +public: + virtual int last_virtual_method() {return 1;} +}; + +template class CppVtableTesterA : public T { +public: + virtual void* last_virtual_method() { + // Make this different than CppVtableTesterB::last_virtual_method so the C++ + // compiler/linker won't alias the two functions. + return NULL; + } +}; + +template +int CppVtableCloner::get_vtable_length(const char* name) { + CppVtableTesterA a; + CppVtableTesterB b; + + intptr_t* avtable = vtable_of(a); + intptr_t* bvtable = vtable_of(b); + + // Start at slot 1, because slot 0 may be RTTI (on Solaris/Sparc) + int vtable_len = 1; + for (; ; vtable_len++) { + if (avtable[vtable_len] != bvtable[vtable_len]) { + break; + } + } + if (PrintSharedSpaces) { + tty->print_cr("Found %3d vtable entries for %s", vtable_len, name); + } + + return vtable_len; +} + +#define ALLOC_CPP_VTABLE_CLONE(c) \ + top = CppVtableCloner::allocate(#c, top, end); + +#define CLONE_CPP_VTABLE(c) \ + p = CppVtableCloner::clone_vtable(#c, (CppVtableInfo*)p); + +#define ZERO_CPP_VTABLE(c) \ + CppVtableCloner::zero_vtable_clone(); + +// This can be called at both dump time and run time. +intptr_t* MetaspaceShared::clone_cpp_vtables(intptr_t* p) { + assert(DumpSharedSpaces || UseSharedSpaces, "sanity"); + CPP_VTABLE_PATCH_TYPES_DO(CLONE_CPP_VTABLE); + return p; +} + +void MetaspaceShared::zero_cpp_vtable_clones_for_writing() { + assert(DumpSharedSpaces, "dump-time only"); + CPP_VTABLE_PATCH_TYPES_DO(ZERO_CPP_VTABLE); +} + +// Allocate and initialize the C++ vtables, starting from top, but do not go past end. +intptr_t* MetaspaceShared::allocate_cpp_vtable_clones(intptr_t* top, intptr_t* end) { + assert(DumpSharedSpaces, "dump-time only"); + // Layout (each slot is a intptr_t): + // [number of slots in the first vtable = n1] + // [ slots for the first vtable] + // [number of slots in the first second = n2] + // [ slots for the second vtable] + // ... + // The order of the vtables is the same as the CPP_VTAB_PATCH_TYPES_DO macro. + CPP_VTABLE_PATCH_TYPES_DO(ALLOC_CPP_VTABLE_CLONE); + return top; +} + +// Switch the vtable pointer to point to the cloned vtable. We assume the +// vtable pointer is in first slot in object. +void MetaspaceShared::patch_cpp_vtable_pointers() { int n = _global_klass_objects->length(); for (int i = 0; i < n; i++) { Klass* obj = _global_klass_objects->at(i); - // Note is_instance_klass() is a virtual call in debug. After patching vtables - // all virtual calls on the dummy vtables will restore the original! if (obj->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(obj); - *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik); + if (ik->is_class_loader_instance_klass()) { + CppVtableCloner::patch(ik); + } else if (ik->is_reference_instance_klass()) { + CppVtableCloner::patch(ik); + } else if (ik->is_mirror_instance_klass()) { + CppVtableCloner::patch(ik); + } else { + CppVtableCloner::patch(ik); + } ConstantPool* cp = ik->constants(); - *(void**)cp = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, cp); + CppVtableCloner::patch(cp); for (int j = 0; j < ik->methods()->length(); j++) { Method* m = ik->methods()->at(j); - *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); + CppVtableCloner::patch(m); + assert(CppVtableCloner::is_valid_shared_object(m), "must be"); } + } else if (obj->is_objArray_klass()) { + CppVtableCloner::patch(obj); } else { - // Array klasses - Klass* k = obj; - *(void**)k = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, k); + assert(obj->is_typeArray_klass(), "sanity"); + CppVtableCloner::patch(obj); } } } +bool MetaspaceShared::is_valid_shared_method(const Method* m) { + assert(is_in_shared_space(m), "must be"); + return CppVtableCloner::is_valid_shared_object(m); +} + // Closure for serializing initialization data out to a data area to be // written to the shared file. @@ -618,24 +782,12 @@ void VM_PopulateDumpSharedSpace::doit() { char* od_top = MetaspaceShared::optional_data_region()->alloc_top(); char* od_end = _od_vs.high(); - // Reserve space for the list of Klass*s whose vtables are used - // for patching others as needed. + char* vtbl_list = md_top; + md_top = (char*)MetaspaceShared::allocate_cpp_vtable_clones((intptr_t*)md_top, (intptr_t*)md_end); - void** vtbl_list = (void**)md_top; - int vtbl_list_size = MetaspaceShared::vtbl_list_size; - Universe::init_self_patching_vtbl_list(vtbl_list, vtbl_list_size); - - md_top += vtbl_list_size * sizeof(void*); - void* vtable = md_top; - - // Reserve space for a new dummy vtable for klass objects in the - // heap. Generate self-patching vtable entries. - - MetaspaceShared::generate_vtable_methods(vtbl_list, &vtable, - &md_top, md_end, - &mc_top, mc_end); - - guarantee(md_top <= md_end, "Insufficient space for vtables."); + // We don't use MC section anymore. We will remove it in a future RFE. For now, put one + // byte inside so the region writing/mapping code works. + mc_top ++; // Reorder the system dictionary. (Moving the symbols affects // how the hash table indices are calculated.) @@ -709,20 +861,19 @@ void VM_PopulateDumpSharedSpace::doit() { tty->print_cr("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]", total_bytes, total_alloced, total_u_perc); - // Update the vtable pointers in all of the Klass objects in the - // heap. They should point to newly generated vtable. - patch_klass_vtables(vtbl_list, vtable); + // During patching, some virtual methods may be called, so at this point + // the vtables must contain valid methods (as filled in by CppVtableCloner::allocate). + MetaspaceShared::patch_cpp_vtable_pointers(); - // dunno what this is for. - char* saved_vtbl = (char*)os::malloc(vtbl_list_size * sizeof(void*), mtClass); - memmove(saved_vtbl, vtbl_list, vtbl_list_size * sizeof(void*)); - memset(vtbl_list, 0, vtbl_list_size * sizeof(void*)); + // The vtable clones contain addresses of the current process. + // We don't want to write these addresses into the archive. + MetaspaceShared::zero_cpp_vtable_clones_for_writing(); // Create and write the archive file that maps the shared spaces. FileMapInfo* mapinfo = new FileMapInfo(); mapinfo->populate_header(MetaspaceShared::max_alignment()); - mapinfo->set_misc_data_patching_start((char*)vtbl_list); + mapinfo->set_misc_data_patching_start(vtbl_list); mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers()); mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size()); @@ -757,8 +908,8 @@ void VM_PopulateDumpSharedSpace::doit() { mapinfo->close(); - memmove(vtbl_list, saved_vtbl, vtbl_list_size * sizeof(void*)); - os::free(saved_vtbl); + // Restore the vtable in case we invoke any virtual methods. + MetaspaceShared::clone_cpp_vtables((intptr_t*)vtbl_list); if (PrintSharedSpaces) { DumpAllocClosure dac; @@ -1134,19 +1285,7 @@ void MetaspaceShared::initialize_shared_spaces() { _cds_i2i_entry_code_buffers_size = mapinfo->cds_i2i_entry_code_buffers_size(); char* buffer = mapinfo->misc_data_patching_start(); - // Skip over (reserve space for) a list of addresses of C++ vtables - // for Klass objects. They get filled in later. - - void** vtbl_list = (void**)buffer; - buffer += MetaspaceShared::vtbl_list_size * sizeof(void*); - Universe::init_self_patching_vtbl_list(vtbl_list, vtbl_list_size); - - // Skip over (reserve space for) dummy C++ vtables Klass objects. - // They are used as is. - - intptr_t vtable_size = *(intptr_t*)buffer; - buffer += sizeof(intptr_t); - buffer += vtable_size; + buffer = (char*)clone_cpp_vtables((intptr_t*)buffer); int sharedDictionaryLen = *(intptr_t*)buffer; buffer += sizeof(intptr_t); diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index cb96021af66..fd08f038c78 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,17 +32,6 @@ #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" -#define DEFAULT_VTBL_LIST_SIZE (17) // number of entries in the shared space vtable list. -#define DEFAULT_VTBL_VIRTUALS_COUNT (200) // maximum number of virtual functions -// If virtual functions are added to Metadata, -// this number needs to be increased. Also, -// SharedMiscCodeSize will need to be increased. -// The following 2 sizes were based on -// MetaspaceShared::generate_vtable_methods() -#define DEFAULT_VTBL_METHOD_SIZE (16) // conservative size of the mov1 and jmp instructions -// for the x64 platform -#define DEFAULT_VTBL_COMMON_CODE_SIZE (1*K) // conservative size of the "common_code" for the x64 platform - #define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) #define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) @@ -134,13 +123,6 @@ class MetaspaceShared : AllStatic { static SharedMiscRegion _mc; static SharedMiscRegion _od; public: - enum { - vtbl_list_size = DEFAULT_VTBL_LIST_SIZE, - num_virtuals = DEFAULT_VTBL_VIRTUALS_COUNT, - vtbl_method_size = DEFAULT_VTBL_METHOD_SIZE, - vtbl_common_code_size = DEFAULT_VTBL_COMMON_CODE_SIZE - }; - enum { ro = 0, // read-only shared space in the heap rw = 1, // read-write shared space in the heap @@ -194,10 +176,12 @@ class MetaspaceShared : AllStatic { static bool is_string_region(int idx) NOT_CDS_RETURN_(false); - static void generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, char* md_end, - char** mc_top, char* mc_end); + static intptr_t* allocate_cpp_vtable_clones(intptr_t* top, intptr_t* end); + static intptr_t* clone_cpp_vtables(intptr_t* p); + static void zero_cpp_vtable_clones_for_writing(); + static void patch_cpp_vtable_pointers(); + static bool is_valid_shared_method(const Method* m); + static void serialize(SerializeClosure* sc, GrowableArray *string_space, size_t* space_size); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index ab66c902094..eade3bb0408 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -410,30 +410,6 @@ void Universe::genesis(TRAPS) { } -// CDS support for patching vtables in metadata in the shared archive. -// All types inherited from Metadata have vtables, but not types inherited -// from MetaspaceObj, because the latter does not have virtual functions. -// If the metadata type has a vtable, it cannot be shared in the read-only -// section of the CDS archive, because the vtable pointer is patched. -static inline void add_vtable(void** list, int* n, void* o, int count) { - guarantee((*n) < count, "vtable list too small"); - void* vtable = dereference_vptr(o); - assert(*(void**)(vtable) != NULL, "invalid vtable"); - list[(*n)++] = vtable; -} - -void Universe::init_self_patching_vtbl_list(void** list, int count) { - int n = 0; - { InstanceKlass o; add_vtable(list, &n, &o, count); } - { InstanceClassLoaderKlass o; add_vtable(list, &n, &o, count); } - { InstanceMirrorKlass o; add_vtable(list, &n, &o, count); } - { InstanceRefKlass o; add_vtable(list, &n, &o, count); } - { TypeArrayKlass o; add_vtable(list, &n, &o, count); } - { ObjArrayKlass o; add_vtable(list, &n, &o, count); } - { Method o; add_vtable(list, &n, &o, count); } - { ConstantPool o; add_vtable(list, &n, &o, count); } -} - void Universe::initialize_basic_type_mirrors(TRAPS) { assert(_int_mirror==NULL, "basic type mirrors already initialized"); _int_mirror = diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 2ded08fc801..03d87637a1e 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -480,9 +480,6 @@ class Universe: AllStatic { // SystemDictionary). static void basic_type_classes_do(void f(Klass*)); - // For sharing -- fill in a list of known vtable pointers. - static void init_self_patching_vtbl_list(void** list, int count); - // Debugging enum VERIFY_FLAGS { Verify_Threads = 1, diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index d50351e1b9e..10effc78dba 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -152,6 +152,7 @@ void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data, // CDS support. Create a new resolved_references array. void ConstantPool::restore_unshareable_info(TRAPS) { + assert(is_constantPool(), "ensure C++ vtable is restored"); // Only create the new resolved references array if it hasn't been attempted before if (resolved_references() != NULL) return; diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 38a71f525d2..9c5976f5695 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -715,6 +715,11 @@ class ConstantPool : public Metadata { friend class ClassFileParser; friend class SystemDictionary; + // Used by CDS. These classes need to access the private ConstantPool() constructor. + template friend class CppVtableTesterA; + template friend class CppVtableTesterB; + template friend class CppVtableCloner; + // Used by compiler to prevent classloading. static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which); static bool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index d789bd04e1c..eaa40839ee7 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -168,7 +168,7 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word // "Normal" instantiation is preceeded by a MetaspaceObj allocation // which zeros out memory - calloc equivalent. -// The constructor is also used from init_self_patching_vtbl_list, +// The constructor is also used from CppVtableCloner, // which doesn't zero out the memory before calling the constructor. // Need to set the _java_mirror field explicitly to not hit an assert that the field // should be NULL before setting it. @@ -501,6 +501,7 @@ void Klass::remove_unshareable_info() { } void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { + assert(is_klass(), "ensure C++ vtable is restored"); TRACE_RESTORE_ID(this); // If an exception happened during CDS restore, some of these fields may already be diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index beed68bed8e..8dcfa68c703 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1101,12 +1101,11 @@ address Method::make_adapters(methodHandle mh, TRAPS) { } void Method::restore_unshareable_info(TRAPS) { + assert(is_method() && is_valid_method(), "ensure C++ vtable is restored"); + // Since restore_unshareable_info can be called more than once for a method, don't // redo any work. if (adapter() == NULL) { - // Restore Method's C++ vtable by calling a virtual function - restore_vtable(); - methodHandle mh(THREAD, this); link_method(mh, CHECK); } @@ -2166,7 +2165,6 @@ void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { bool Method::has_method_vptr(const void* ptr) { Method m; // This assumes that the vtbl pointer is the first word of a C++ object. - // This assumption is also in universe.cpp patch_klass_vtble return dereference_vptr(&m) == dereference_vptr(ptr); } @@ -2177,10 +2175,12 @@ bool Method::is_valid_method() const { } else if ((intptr_t(this) & (wordSize-1)) != 0) { // Quick sanity check on pointer. return false; - } else if (!is_metaspace_object()) { - return false; - } else { + } else if (MetaspaceShared::is_in_shared_space(this)) { + return MetaspaceShared::is_valid_shared_method(this); + } else if (Metaspace::contains_non_shared(this)) { return has_method_vptr((const void*)this); + } else { + return false; } } diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index ebd5f0feef2..a3e636388cd 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -122,11 +122,6 @@ class Method : public Metadata { // CDS and vtbl checking can create an empty Method to get vtbl pointer. Method(){} - // The Method vtable is restored by this call when the Method is in the - // shared archive. See patch_klass_vtables() in metaspaceShared.cpp for - // all the gory details. SA, dtrace and pstack helpers distinguish metadata - // by their vtable. - void restore_vtable() { guarantee(is_method(), "vtable restored by this call"); } bool is_method() const volatile { return true; } void restore_unshareable_info(TRAPS); From 43a771e998f72ba75cdf55dc3cec498cb545f5f0 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 13 Mar 2017 12:13:09 +0100 Subject: [PATCH 54/86] 8176441: assert(false) failed: modified node was not processed by IGVN.transform_old() The shiftNode needs to be added to the IGVN worklist after being modified. Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/opto/mulnode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 5a74bed0999..91f94af74de 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -648,6 +648,7 @@ static int maskShiftAmount(PhaseGVN *phase, Node *shiftNode, int nBits) { if (shift != maskedShift) { shiftNode->set_req(2, phase->intcon(maskedShift)); // Replace shift count with masked value. + phase->igvn_rehash_node_delayed(shiftNode); } return maskedShift; From fcb59082302d4c4aa82d7d75a6c5116f58c86f5e Mon Sep 17 00:00:00 2001 From: Zoltan Majo Date: Mon, 13 Mar 2017 13:01:47 +0100 Subject: [PATCH 55/86] 8159734: Consistency check fails with -XX:-ProfileInterpreter Re-establish the consistency of profiling information also with -XX:-ProfileInterpreter. Reviewed-by: kvn --- hotspot/src/share/vm/ci/ciMethod.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 4860427786f..5b1ad8d41db 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -504,10 +504,11 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) { morphism++; } int epsilon = 0; - if (TieredCompilation && ProfileInterpreter) { - // Interpreter and C1 treat final and special invokes differently. - // C1 will record a type, whereas the interpreter will just - // increment the count. Detect this case. + if (TieredCompilation) { + // For a call, it is assumed that either the type of the receiver(s) + // is recorded or an associated counter is incremented, but not both. With + // tiered compilation, however, both can happen due to the interpreter and + // C1 profiling invocations differently. Address that inconsistency here. if (morphism == 1 && count > 0) { epsilon = count; count = 0; @@ -525,8 +526,8 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) { // we will set result._method also. } // Determine call site's morphism. - // The call site count is 0 with known morphism (onlt 1 or 2 receivers) - // or < 0 in the case of a type check failured for checkcast, aastore, instanceof. + // The call site count is 0 with known morphism (only 1 or 2 receivers) + // or < 0 in the case of a type check failure for checkcast, aastore, instanceof. // The call site count is > 0 in the case of a polymorphic virtual call. if (morphism > 0 && morphism == result._limit) { // The morphism <= MorphismLimit. From 35d5d1c53d2157e57fd8a517502c6f879f856e91 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 13 Mar 2017 20:23:11 +0100 Subject: [PATCH 56/86] 8173848: realpath is unsafe Fix occurrences of realpath in hotspot to use safe POSIX.1-2008 form. Reviewed-by: dsamersoff, dholmes, clanger --- hotspot/src/os/aix/vm/os_aix.cpp | 2 +- hotspot/src/os/bsd/vm/os_bsd.cpp | 8 ++--- hotspot/src/os/linux/vm/os_linux.cpp | 8 ++--- hotspot/src/os/posix/vm/os_posix.cpp | 44 +++++++++++++++++++++++- hotspot/src/os/posix/vm/os_posix.hpp | 9 ++++- hotspot/src/os/solaris/vm/os_solaris.cpp | 12 +++++-- 6 files changed, 69 insertions(+), 14 deletions(-) diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 014d306e37f..61847a2474f 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1576,7 +1576,7 @@ void os::jvm_path(char *buf, jint buflen) { Dl_info dlinfo; int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); assert(ret != 0, "cannot locate libjvm"); - char* rp = realpath((char *)dlinfo.dli_fname, buf); + char* rp = os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen); assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?"); strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path)); diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 926144074f9..1273b6a9348 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -1754,7 +1754,7 @@ void os::jvm_path(char *buf, jint buflen) { assert(ret, "cannot locate libjvm"); char *rp = NULL; if (ret && dli_fname[0] != '\0') { - rp = realpath(dli_fname, buf); + rp = os::Posix::realpath(dli_fname, buf, buflen); } if (rp == NULL) { return; @@ -1786,7 +1786,7 @@ void os::jvm_path(char *buf, jint buflen) { p = strrchr(buf, '/'); assert(strstr(p, "/libjvm") == p, "invalid library name"); - rp = realpath(java_home_var, buf); + rp = os::Posix::realpath(java_home_var, buf, buflen); if (rp == NULL) { return; } @@ -1820,7 +1820,7 @@ void os::jvm_path(char *buf, jint buflen) { snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX); } else { // Fall back to path of current library - rp = realpath(dli_fname, buf); + rp = os::Posix::realpath(dli_fname, buf, buflen); if (rp == NULL) { return; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index bcce508e098..c91dbe15f6b 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -2318,7 +2318,7 @@ void os::jvm_path(char *buf, jint buflen) { assert(ret, "cannot locate libjvm"); char *rp = NULL; if (ret && dli_fname[0] != '\0') { - rp = realpath(dli_fname, buf); + rp = os::Posix::realpath(dli_fname, buf, buflen); } if (rp == NULL) { return; @@ -2352,7 +2352,7 @@ void os::jvm_path(char *buf, jint buflen) { } assert(strstr(p, "/libjvm") == p, "invalid library name"); - rp = realpath(java_home_var, buf); + rp = os::Posix::realpath(java_home_var, buf, buflen); if (rp == NULL) { return; } @@ -2373,7 +2373,7 @@ void os::jvm_path(char *buf, jint buflen) { snprintf(buf + len, buflen-len, "/hotspot/libjvm.so"); } else { // Go back to path of .so - rp = realpath(dli_fname, buf); + rp = os::Posix::realpath(dli_fname, buf, buflen); if (rp == NULL) { return; } diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 5885906f670..44d2d7ca84e 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -1105,6 +1105,48 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a return buf; } +char* os::Posix::realpath(const char* filename, char* outbuf, size_t outbuflen) { + + if (filename == NULL || outbuf == NULL || outbuflen < 1) { + assert(false, "os::Posix::realpath: invalid arguments."); + errno = EINVAL; + return NULL; + } + + char* result = NULL; + + // This assumes platform realpath() is implemented according to POSIX.1-2008. + // POSIX.1-2008 allows to specify NULL for the output buffer, in which case + // output buffer is dynamically allocated and must be ::free()'d by the caller. + char* p = ::realpath(filename, NULL); + if (p != NULL) { + if (strlen(p) < outbuflen) { + strcpy(outbuf, p); + result = outbuf; + } else { + errno = ENAMETOOLONG; + } + ::free(p); // *not* os::free + } else { + // Fallback for platforms struggling with modern Posix standards (AIX 5.3, 6.1). If realpath + // returns EINVAL, this may indicate that realpath is not POSIX.1-2008 compatible and + // that it complains about the NULL we handed down as user buffer. + // In this case, use the user provided buffer but at least check whether realpath caused + // a memory overwrite. + if (errno == EINVAL) { + outbuf[outbuflen - 1] = '\0'; + p = ::realpath(filename, outbuf); + if (p != NULL) { + guarantee(outbuf[outbuflen - 1] == '\0', "realpath buffer overwrite detected."); + result = p; + } + } + } + return result; + +} + + // Check minimum allowable stack sizes for thread creation and to initialize // the java system classes, including StackOverflowError - depends on page // size. diff --git a/hotspot/src/os/posix/vm/os_posix.hpp b/hotspot/src/os/posix/vm/os_posix.hpp index ccd42fd94ac..1df1ba8247a 100644 --- a/hotspot/src/os/posix/vm/os_posix.hpp +++ b/hotspot/src/os/posix/vm/os_posix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -96,6 +96,13 @@ public: // to buf with len buflen; buf is returned. static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr); + // A safe implementation of realpath which will not cause a buffer overflow if the resolved path + // is longer than PATH_MAX. + // On success, returns 'outbuf', which now contains the path. + // On error, it will return NULL and set errno. The content of 'outbuf' is undefined. + // On truncation error ('outbuf' too small), it will return NULL and set errno to ENAMETOOLONG. + static char* realpath(const char* filename, char* outbuf, size_t outbuflen); + }; /* diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index adbec4e459e..e93b0ed119a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2034,7 +2034,9 @@ void os::jvm_path(char *buf, jint buflen) { int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); assert(ret != 0, "cannot locate libjvm"); if (ret != 0 && dlinfo.dli_fname != NULL) { - realpath((char *)dlinfo.dli_fname, buf); + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) { + return; + } } else { buf[0] = '\0'; return; @@ -2065,7 +2067,9 @@ void os::jvm_path(char *buf, jint buflen) { p = strrchr(buf, '/'); assert(strstr(p, "/libjvm") == p, "invalid library name"); - realpath(java_home_var, buf); + if (os::Posix::realpath(java_home_var, buf, buflen) == NULL) { + return; + } // determine if this is a legacy image or modules image // modules image doesn't have "jre" subdirectory len = strlen(buf); @@ -2082,7 +2086,9 @@ void os::jvm_path(char *buf, jint buflen) { snprintf(buf + len, buflen-len, "/hotspot/libjvm.so"); } else { // Go back to path of .so - realpath((char *)dlinfo.dli_fname, buf); + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) { + return; + } } } } From 7bca46378904aedbe57d6c83bd7680d6c578d754 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 15 Mar 2017 11:44:46 +0100 Subject: [PATCH 57/86] 8168467: Use TaskEntry as task mark queue elements Change the mark stack to use TaskEntry queue elements to improve type safety instead of casting around raw pointers. Reviewed-by: kbarrett, sangheki --- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 106 ++++++++-------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 119 +++++++++++++----- .../vm/gc/g1/g1ConcurrentMark.inline.hpp | 51 ++++---- .../g1/g1ConcurrentMarkObjArrayProcessor.cpp | 29 ++--- .../g1/g1ConcurrentMarkObjArrayProcessor.hpp | 16 +-- 5 files changed, 181 insertions(+), 140 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index d64714cb435..afd56a50561 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -145,15 +145,15 @@ bool G1CMMarkStack::resize(size_t new_capacity) { assert(new_capacity <= _max_chunk_capacity, "Trying to resize stack to " SIZE_FORMAT " chunks when the maximum is " SIZE_FORMAT, new_capacity, _max_chunk_capacity); - OopChunk* new_base = MmapArrayAllocator::allocate_or_null(new_capacity); + TaskQueueEntryChunk* new_base = MmapArrayAllocator::allocate_or_null(new_capacity); if (new_base == NULL) { - log_warning(gc)("Failed to reserve memory for new overflow mark stack with " SIZE_FORMAT " chunks and size " SIZE_FORMAT "B.", new_capacity, new_capacity * sizeof(OopChunk)); + log_warning(gc)("Failed to reserve memory for new overflow mark stack with " SIZE_FORMAT " chunks and size " SIZE_FORMAT "B.", new_capacity, new_capacity * sizeof(TaskQueueEntryChunk)); return false; } // Release old mapping. if (_base != NULL) { - MmapArrayAllocator::free(_base, _chunk_capacity); + MmapArrayAllocator::free(_base, _chunk_capacity); } _base = new_base; @@ -165,16 +165,16 @@ bool G1CMMarkStack::resize(size_t new_capacity) { } size_t G1CMMarkStack::capacity_alignment() { - return (size_t)lcm(os::vm_allocation_granularity(), sizeof(OopChunk)) / sizeof(void*); + return (size_t)lcm(os::vm_allocation_granularity(), sizeof(TaskQueueEntryChunk)) / sizeof(G1TaskQueueEntry); } bool G1CMMarkStack::initialize(size_t initial_capacity, size_t max_capacity) { guarantee(_max_chunk_capacity == 0, "G1CMMarkStack already initialized."); - size_t const OopChunkSizeInVoidStar = sizeof(OopChunk) / sizeof(void*); + size_t const TaskEntryChunkSizeInVoidStar = sizeof(TaskQueueEntryChunk) / sizeof(G1TaskQueueEntry); - _max_chunk_capacity = (size_t)align_size_up(max_capacity, capacity_alignment()) / OopChunkSizeInVoidStar; - size_t initial_chunk_capacity = (size_t)align_size_up(initial_capacity, capacity_alignment()) / OopChunkSizeInVoidStar; + _max_chunk_capacity = (size_t)align_size_up(max_capacity, capacity_alignment()) / TaskEntryChunkSizeInVoidStar; + size_t initial_chunk_capacity = (size_t)align_size_up(initial_capacity, capacity_alignment()) / TaskEntryChunkSizeInVoidStar; guarantee(initial_chunk_capacity <= _max_chunk_capacity, "Maximum chunk capacity " SIZE_FORMAT " smaller than initial capacity " SIZE_FORMAT, @@ -210,49 +210,49 @@ void G1CMMarkStack::expand() { G1CMMarkStack::~G1CMMarkStack() { if (_base != NULL) { - MmapArrayAllocator::free(_base, _chunk_capacity); + MmapArrayAllocator::free(_base, _chunk_capacity); } } -void G1CMMarkStack::add_chunk_to_list(OopChunk* volatile* list, OopChunk* elem) { +void G1CMMarkStack::add_chunk_to_list(TaskQueueEntryChunk* volatile* list, TaskQueueEntryChunk* elem) { elem->next = *list; *list = elem; } -void G1CMMarkStack::add_chunk_to_chunk_list(OopChunk* elem) { +void G1CMMarkStack::add_chunk_to_chunk_list(TaskQueueEntryChunk* elem) { MutexLockerEx x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag); add_chunk_to_list(&_chunk_list, elem); _chunks_in_chunk_list++; } -void G1CMMarkStack::add_chunk_to_free_list(OopChunk* elem) { +void G1CMMarkStack::add_chunk_to_free_list(TaskQueueEntryChunk* elem) { MutexLockerEx x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag); add_chunk_to_list(&_free_list, elem); } -G1CMMarkStack::OopChunk* G1CMMarkStack::remove_chunk_from_list(OopChunk* volatile* list) { - OopChunk* result = *list; +G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::remove_chunk_from_list(TaskQueueEntryChunk* volatile* list) { + TaskQueueEntryChunk* result = *list; if (result != NULL) { *list = (*list)->next; } return result; } -G1CMMarkStack::OopChunk* G1CMMarkStack::remove_chunk_from_chunk_list() { +G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::remove_chunk_from_chunk_list() { MutexLockerEx x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag); - OopChunk* result = remove_chunk_from_list(&_chunk_list); + TaskQueueEntryChunk* result = remove_chunk_from_list(&_chunk_list); if (result != NULL) { _chunks_in_chunk_list--; } return result; } -G1CMMarkStack::OopChunk* G1CMMarkStack::remove_chunk_from_free_list() { +G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::remove_chunk_from_free_list() { MutexLockerEx x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag); return remove_chunk_from_list(&_free_list); } -G1CMMarkStack::OopChunk* G1CMMarkStack::allocate_new_chunk() { +G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::allocate_new_chunk() { // This dirty read of _hwm is okay because we only ever increase the _hwm in parallel code. // Further this limits _hwm to a value of _chunk_capacity + #threads, avoiding // wraparound of _hwm. @@ -265,14 +265,14 @@ G1CMMarkStack::OopChunk* G1CMMarkStack::allocate_new_chunk() { return NULL; } - OopChunk* result = ::new (&_base[cur_idx]) OopChunk; + TaskQueueEntryChunk* result = ::new (&_base[cur_idx]) TaskQueueEntryChunk; result->next = NULL; return result; } -bool G1CMMarkStack::par_push_chunk(oop* ptr_arr) { +bool G1CMMarkStack::par_push_chunk(G1TaskQueueEntry* ptr_arr) { // Get a new chunk. - OopChunk* new_chunk = remove_chunk_from_free_list(); + TaskQueueEntryChunk* new_chunk = remove_chunk_from_free_list(); if (new_chunk == NULL) { // Did not get a chunk from the free list. Allocate from backing memory. @@ -283,21 +283,21 @@ bool G1CMMarkStack::par_push_chunk(oop* ptr_arr) { } } - Copy::conjoint_memory_atomic(ptr_arr, new_chunk->data, OopsPerChunk * sizeof(oop)); + Copy::conjoint_memory_atomic(ptr_arr, new_chunk->data, EntriesPerChunk * sizeof(G1TaskQueueEntry)); add_chunk_to_chunk_list(new_chunk); return true; } -bool G1CMMarkStack::par_pop_chunk(oop* ptr_arr) { - OopChunk* cur = remove_chunk_from_chunk_list(); +bool G1CMMarkStack::par_pop_chunk(G1TaskQueueEntry* ptr_arr) { + TaskQueueEntryChunk* cur = remove_chunk_from_chunk_list(); if (cur == NULL) { return false; } - Copy::conjoint_memory_atomic(cur->data, ptr_arr, OopsPerChunk * sizeof(oop)); + Copy::conjoint_memory_atomic(cur->data, ptr_arr, EntriesPerChunk * sizeof(G1TaskQueueEntry)); add_chunk_to_free_list(cur); return true; @@ -1995,13 +1995,17 @@ public: _info(info) { } - void operator()(oop obj) const { - guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || obj->is_oop(), + void operator()(G1TaskQueueEntry task_entry) const { + if (task_entry.is_array_slice()) { + guarantee(_g1h->is_in_reserved(task_entry.slice()), "Slice " PTR_FORMAT " must be in heap.", p2i(task_entry.slice())); + return; + } + guarantee(task_entry.obj()->is_oop(), "Non-oop " PTR_FORMAT ", phase: %s, info: %d", - p2i(obj), _phase, _info); - guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_in_cset(obj), + p2i(task_entry.obj()), _phase, _info); + guarantee(!_g1h->is_in_cset(task_entry.obj()), "obj: " PTR_FORMAT " in CSet, phase: %s, info: %d", - p2i(obj), _phase, _info); + p2i(task_entry.obj()), _phase, _info); } }; @@ -2195,7 +2199,7 @@ public: // We move that task's local finger along. _task->move_finger_to(addr); - _task->scan_object(oop(addr)); + _task->scan_task_entry(G1TaskQueueEntry::from_oop(oop(addr))); // we only partially drain the local queue and global stack _task->drain_local_queue(true); _task->drain_global_stack(true); @@ -2386,16 +2390,16 @@ void G1CMTask::decrease_limits() { void G1CMTask::move_entries_to_global_stack() { // Local array where we'll store the entries that will be popped // from the local queue. - oop buffer[G1CMMarkStack::OopsPerChunk]; + G1TaskQueueEntry buffer[G1CMMarkStack::EntriesPerChunk]; size_t n = 0; - oop obj; - while (n < G1CMMarkStack::OopsPerChunk && _task_queue->pop_local(obj)) { - buffer[n] = obj; + G1TaskQueueEntry task_entry; + while (n < G1CMMarkStack::EntriesPerChunk && _task_queue->pop_local(task_entry)) { + buffer[n] = task_entry; ++n; } - if (n < G1CMMarkStack::OopsPerChunk) { - buffer[n] = NULL; + if (n < G1CMMarkStack::EntriesPerChunk) { + buffer[n] = G1TaskQueueEntry(); } if (n > 0) { @@ -2411,20 +2415,20 @@ void G1CMTask::move_entries_to_global_stack() { bool G1CMTask::get_entries_from_global_stack() { // Local array where we'll store the entries that will be popped // from the global stack. - oop buffer[G1CMMarkStack::OopsPerChunk]; + G1TaskQueueEntry buffer[G1CMMarkStack::EntriesPerChunk]; if (!_cm->mark_stack_pop(buffer)) { return false; } // We did actually pop at least one entry. - for (size_t i = 0; i < G1CMMarkStack::OopsPerChunk; ++i) { - oop elem = buffer[i]; - if (elem == NULL) { + for (size_t i = 0; i < G1CMMarkStack::EntriesPerChunk; ++i) { + G1TaskQueueEntry task_entry = buffer[i]; + if (task_entry.is_null()) { break; } - assert(G1CMObjArrayProcessor::is_array_slice(elem) || elem->is_oop(), "Element " PTR_FORMAT " must be an array slice or oop", p2i(elem)); - bool success = _task_queue->push(elem); + assert(task_entry.is_array_slice() || task_entry.obj()->is_oop(), "Element " PTR_FORMAT " must be an array slice or oop", p2i(task_entry.obj())); + bool success = _task_queue->push(task_entry); // We only call this when the local queue is empty or under a // given target limit. So, we do not expect this push to fail. assert(success, "invariant"); @@ -2451,14 +2455,14 @@ void G1CMTask::drain_local_queue(bool partially) { } if (_task_queue->size() > target_size) { - oop obj; - bool ret = _task_queue->pop_local(obj); + G1TaskQueueEntry entry; + bool ret = _task_queue->pop_local(entry); while (ret) { - scan_object(obj); + scan_task_entry(entry); if (_task_queue->size() <= target_size || has_aborted()) { ret = false; } else { - ret = _task_queue->pop_local(obj); + ret = _task_queue->pop_local(entry); } } } @@ -2539,8 +2543,8 @@ void G1CMTask::print_stats() { _step_times_ms.maximum(), _step_times_ms.sum()); } -bool G1ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) { - return _task_queues->steal(worker_id, hash_seed, obj); +bool G1ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, G1TaskQueueEntry& task_entry) { + return _task_queues->steal(worker_id, hash_seed, task_entry); } /***************************************************************************** @@ -2863,9 +2867,9 @@ void G1CMTask::do_marking_step(double time_target_ms, assert(_cm->out_of_regions() && _task_queue->size() == 0, "only way to reach here"); while (!has_aborted()) { - oop obj; - if (_cm->try_stealing(_worker_id, &_hash_seed, obj)) { - scan_object(obj); + G1TaskQueueEntry entry; + if (_cm->try_stealing(_worker_id, &_hash_seed, entry)) { + scan_task_entry(entry); // And since we're towards the end, let's totally drain the // local queue and global stack. diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index fa0bfc58e2a..dae7338e94c 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -38,7 +38,62 @@ class G1ConcurrentMark; class ConcurrentGCTimer; class G1OldTracer; class G1SurvivorRegions; -typedef GenericTaskQueue G1CMTaskQueue; + +#ifdef _MSC_VER +#pragma warning(push) +// warning C4522: multiple assignment operators specified +#pragma warning(disable:4522) +#endif + +// This is a container class for either an oop or a continuation address for +// mark stack entries. Both are pushed onto the mark stack. +class G1TaskQueueEntry VALUE_OBJ_CLASS_SPEC { +private: + void* _holder; + + static const uintptr_t ArraySliceBit = 1; + + G1TaskQueueEntry(oop obj) : _holder(obj) { + assert(_holder != NULL, "Not allowed to set NULL task queue element"); + } + G1TaskQueueEntry(HeapWord* addr) : _holder((void*)((uintptr_t)addr | ArraySliceBit)) { } +public: + G1TaskQueueEntry(const G1TaskQueueEntry& other) { _holder = other._holder; } + G1TaskQueueEntry() : _holder(NULL) { } + + static G1TaskQueueEntry from_slice(HeapWord* what) { return G1TaskQueueEntry(what); } + static G1TaskQueueEntry from_oop(oop obj) { return G1TaskQueueEntry(obj); } + + G1TaskQueueEntry& operator=(const G1TaskQueueEntry& t) { + _holder = t._holder; + return *this; + } + + volatile G1TaskQueueEntry& operator=(const volatile G1TaskQueueEntry& t) volatile { + _holder = t._holder; + return *this; + } + + oop obj() const { + assert(!is_array_slice(), "Trying to read array slice " PTR_FORMAT " as oop", p2i(_holder)); + return (oop)_holder; + } + + HeapWord* slice() const { + assert(is_array_slice(), "Trying to read oop " PTR_FORMAT " as array slice", p2i(_holder)); + return (HeapWord*)((uintptr_t)_holder & ~ArraySliceBit); + } + + bool is_oop() const { return !is_array_slice(); } + bool is_array_slice() const { return ((uintptr_t)_holder & ArraySliceBit) != 0; } + bool is_null() const { return _holder == NULL; } +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +typedef GenericTaskQueue G1CMTaskQueue; typedef GenericTaskQueueSet G1CMTaskQueueSet; // Closure used by CM during concurrent reference discovery @@ -165,44 +220,44 @@ class G1CMBitMap : public G1CMBitMapRO { // list connecting all empty chunks. class G1CMMarkStack VALUE_OBJ_CLASS_SPEC { public: - // Number of oops that can fit in a single chunk. - static const size_t OopsPerChunk = 1024 - 1 /* One reference for the next pointer */; + // Number of TaskQueueEntries that can fit in a single chunk. + static const size_t EntriesPerChunk = 1024 - 1 /* One reference for the next pointer */; private: - struct OopChunk { - OopChunk* next; - oop data[OopsPerChunk]; + struct TaskQueueEntryChunk { + TaskQueueEntryChunk* next; + G1TaskQueueEntry data[EntriesPerChunk]; }; - size_t _max_chunk_capacity; // Maximum number of OopChunk elements on the stack. + size_t _max_chunk_capacity; // Maximum number of TaskQueueEntryChunk elements on the stack. - OopChunk* _base; // Bottom address of allocated memory area. - size_t _chunk_capacity; // Current maximum number of OopChunk elements. + TaskQueueEntryChunk* _base; // Bottom address of allocated memory area. + size_t _chunk_capacity; // Current maximum number of TaskQueueEntryChunk elements. char _pad0[DEFAULT_CACHE_LINE_SIZE]; - OopChunk* volatile _free_list; // Linked list of free chunks that can be allocated by users. - char _pad1[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*)]; - OopChunk* volatile _chunk_list; // List of chunks currently containing data. + TaskQueueEntryChunk* volatile _free_list; // Linked list of free chunks that can be allocated by users. + char _pad1[DEFAULT_CACHE_LINE_SIZE - sizeof(TaskQueueEntryChunk*)]; + TaskQueueEntryChunk* volatile _chunk_list; // List of chunks currently containing data. volatile size_t _chunks_in_chunk_list; - char _pad2[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*) - sizeof(size_t)]; + char _pad2[DEFAULT_CACHE_LINE_SIZE - sizeof(TaskQueueEntryChunk*) - sizeof(size_t)]; volatile size_t _hwm; // High water mark within the reserved space. char _pad4[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)]; // Allocate a new chunk from the reserved memory, using the high water mark. Returns // NULL if out of memory. - OopChunk* allocate_new_chunk(); + TaskQueueEntryChunk* allocate_new_chunk(); // Atomically add the given chunk to the list. - void add_chunk_to_list(OopChunk* volatile* list, OopChunk* elem); + void add_chunk_to_list(TaskQueueEntryChunk* volatile* list, TaskQueueEntryChunk* elem); // Atomically remove and return a chunk from the given list. Returns NULL if the // list is empty. - OopChunk* remove_chunk_from_list(OopChunk* volatile* list); + TaskQueueEntryChunk* remove_chunk_from_list(TaskQueueEntryChunk* volatile* list); - void add_chunk_to_chunk_list(OopChunk* elem); - void add_chunk_to_free_list(OopChunk* elem); + void add_chunk_to_chunk_list(TaskQueueEntryChunk* elem); + void add_chunk_to_free_list(TaskQueueEntryChunk* elem); - OopChunk* remove_chunk_from_chunk_list(); - OopChunk* remove_chunk_from_free_list(); + TaskQueueEntryChunk* remove_chunk_from_chunk_list(); + TaskQueueEntryChunk* remove_chunk_from_free_list(); bool _should_expand; @@ -220,17 +275,17 @@ private: // Allocate and initialize the mark stack with the given number of oops. bool initialize(size_t initial_capacity, size_t max_capacity); - // Pushes the given buffer containing at most OopsPerChunk elements on the mark - // stack. If less than OopsPerChunk elements are to be pushed, the array must + // Pushes the given buffer containing at most EntriesPerChunk elements on the mark + // stack. If less than EntriesPerChunk elements are to be pushed, the array must // be terminated with a NULL. // Returns whether the buffer contents were successfully pushed to the global mark // stack. - bool par_push_chunk(oop* buffer); + bool par_push_chunk(G1TaskQueueEntry* buffer); // Pops a chunk from this mark stack, copying them into the given buffer. This - // chunk may contain up to OopsPerChunk elements. If there are less, the last + // chunk may contain up to EntriesPerChunk elements. If there are less, the last // element in the array is a NULL pointer. - bool par_pop_chunk(oop* buffer); + bool par_pop_chunk(G1TaskQueueEntry* buffer); // Return whether the chunk list is empty. Racy due to unsynchronized access to // _chunk_list. @@ -246,7 +301,7 @@ private: // Return the approximate number of oops on this mark stack. Racy due to // unsynchronized access to _chunks_in_chunk_list. - size_t size() const { return _chunks_in_chunk_list * OopsPerChunk; } + size_t size() const { return _chunks_in_chunk_list * EntriesPerChunk; } void set_empty(); @@ -526,14 +581,14 @@ public: // Manipulation of the global mark stack. // The push and pop operations are used by tasks for transfers // between task-local queues and the global mark stack. - bool mark_stack_push(oop* arr) { + bool mark_stack_push(G1TaskQueueEntry* arr) { if (!_global_mark_stack.par_push_chunk(arr)) { set_has_overflown(); return false; } return true; } - bool mark_stack_pop(oop* arr) { + bool mark_stack_pop(G1TaskQueueEntry* arr) { return _global_mark_stack.par_pop_chunk(arr); } size_t mark_stack_size() { return _global_mark_stack.size(); } @@ -567,7 +622,7 @@ public: } // Attempts to steal an object from the task queues of other tasks - bool try_stealing(uint worker_id, int* hash_seed, oop& obj); + bool try_stealing(uint worker_id, int* hash_seed, G1TaskQueueEntry& task_entry); G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, @@ -822,7 +877,7 @@ private: // mark bitmap scan, and so needs to be pushed onto the mark stack. bool is_below_finger(oop obj, HeapWord* global_finger) const; - template void process_grey_object(oop obj); + template void process_grey_task_entry(G1TaskQueueEntry task_entry); public: // Apply the closure on the given area of the objArray. Return the number of words // scanned. @@ -887,10 +942,10 @@ public: inline void deal_with_reference(oop obj); // It scans an object and visits its children. - inline void scan_object(oop obj); + inline void scan_task_entry(G1TaskQueueEntry task_entry); // It pushes an object on the local queue. - inline void push(oop obj); + inline void push(G1TaskQueueEntry task_entry); // Move entries to the global stack. void move_entries_to_global_stack(); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 13bd0b56167..8561b10c3cb 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -97,12 +97,12 @@ inline void G1CMMarkStack::iterate(Fn fn) const { size_t num_chunks = 0; - OopChunk* cur = _chunk_list; + TaskQueueEntryChunk* cur = _chunk_list; while (cur != NULL) { guarantee(num_chunks <= _chunks_in_chunk_list, "Found " SIZE_FORMAT " oop chunks which is more than there should be", num_chunks); - for (size_t i = 0; i < OopsPerChunk; ++i) { - if (cur->data[i] == NULL) { + for (size_t i = 0; i < EntriesPerChunk; ++i) { + if (cur->data[i].is_null()) { break; } fn(cur->data[i]); @@ -114,17 +114,16 @@ inline void G1CMMarkStack::iterate(Fn fn) const { #endif // It scans an object and visits its children. -inline void G1CMTask::scan_object(oop obj) { process_grey_object(obj); } +inline void G1CMTask::scan_task_entry(G1TaskQueueEntry task_entry) { process_grey_task_entry(task_entry); } -inline void G1CMTask::push(oop obj) { - HeapWord* objAddr = (HeapWord*) obj; - assert(G1CMObjArrayProcessor::is_array_slice(obj) || _g1h->is_in_g1_reserved(objAddr), "invariant"); - assert(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_on_master_free_list( - _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant"); - assert(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_obj_ill(obj), "invariant"); - assert(G1CMObjArrayProcessor::is_array_slice(obj) || _nextMarkBitMap->isMarked(objAddr), "invariant"); +inline void G1CMTask::push(G1TaskQueueEntry task_entry) { + assert(task_entry.is_array_slice() || _g1h->is_in_g1_reserved(task_entry.obj()), "invariant"); + assert(task_entry.is_array_slice() || !_g1h->is_on_master_free_list( + _g1h->heap_region_containing(task_entry.obj())), "invariant"); + assert(task_entry.is_array_slice() || !_g1h->is_obj_ill(task_entry.obj()), "invariant"); // FIXME!!! + assert(task_entry.is_array_slice() || _nextMarkBitMap->isMarked((HeapWord*)task_entry.obj()), "invariant"); - if (!_task_queue->push(obj)) { + if (!_task_queue->push(task_entry)) { // The local task queue looks full. We need to push some entries // to the global stack. move_entries_to_global_stack(); @@ -132,7 +131,7 @@ inline void G1CMTask::push(oop obj) { // this should succeed since, even if we overflow the global // stack, we should have definitely removed some entries from the // local queue. So, there must be space on it. - bool success = _task_queue->push(obj); + bool success = _task_queue->push(task_entry); assert(success, "invariant"); } } @@ -168,18 +167,21 @@ inline bool G1CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { } template -inline void G1CMTask::process_grey_object(oop obj) { - assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray"); - assert(G1CMObjArrayProcessor::is_array_slice(obj) || _nextMarkBitMap->isMarked((HeapWord*) obj), +inline void G1CMTask::process_grey_task_entry(G1TaskQueueEntry task_entry) { + assert(scan || (task_entry.is_oop() && task_entry.obj()->is_typeArray()), "Skipping scan of grey non-typeArray"); + assert(task_entry.is_array_slice() || _nextMarkBitMap->isMarked((HeapWord*)task_entry.obj()), "Any stolen object should be a slice or marked"); if (scan) { - if (G1CMObjArrayProcessor::is_array_slice(obj)) { - _words_scanned += _objArray_processor.process_slice(obj); - } else if (G1CMObjArrayProcessor::should_be_sliced(obj)) { - _words_scanned += _objArray_processor.process_obj(obj); + if (task_entry.is_array_slice()) { + _words_scanned += _objArray_processor.process_slice(task_entry.slice()); } else { - _words_scanned += obj->oop_iterate_size(_cm_oop_closure);; + oop obj = task_entry.obj(); + if (G1CMObjArrayProcessor::should_be_sliced(obj)) { + _words_scanned += _objArray_processor.process_obj(obj); + } else { + _words_scanned += obj->oop_iterate_size(_cm_oop_closure);; + } } } check_limits(); @@ -210,6 +212,7 @@ inline void G1CMTask::make_reference_grey(oop obj) { // be pushed on the stack. So, some duplicate work, but no // correctness problems. if (is_below_finger(obj, global_finger)) { + G1TaskQueueEntry entry = G1TaskQueueEntry::from_oop(obj); if (obj->is_typeArray()) { // Immediately process arrays of primitive types, rather // than pushing on the mark stack. This keeps us from @@ -221,9 +224,9 @@ inline void G1CMTask::make_reference_grey(oop obj) { // by only doing a bookkeeping update and avoiding the // actual scan of the object - a typeArray contains no // references, and the metadata is built-in. - process_grey_object(obj); + process_grey_task_entry(entry); } else { - push(obj); + push(entry); } } } diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp index d74bbd79bc0..05c3c9ecd66 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,18 +26,8 @@ #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp" -oop G1CMObjArrayProcessor::encode_array_slice(HeapWord* addr) { - return oop((void*)((uintptr_t)addr | ArraySliceBit)); -} - -HeapWord* G1CMObjArrayProcessor::decode_array_slice(oop value) { - assert(is_array_slice(value), "Given value " PTR_FORMAT " is not an array slice", p2i(value)); - return (HeapWord*)((uintptr_t)(void*)value & ~ArraySliceBit); -} - void G1CMObjArrayProcessor::push_array_slice(HeapWord* what) { - oop obj = encode_array_slice(what); - _task->push(obj); + _task->push(G1TaskQueueEntry::from_slice(what)); } size_t G1CMObjArrayProcessor::process_array_slice(objArrayOop obj, HeapWord* start_from, size_t remaining) { @@ -58,30 +48,29 @@ size_t G1CMObjArrayProcessor::process_obj(oop obj) { return process_array_slice(objArrayOop(obj), (HeapWord*)obj, (size_t)objArrayOop(obj)->size()); } -size_t G1CMObjArrayProcessor::process_slice(oop obj) { - HeapWord* const decoded_address = decode_array_slice(obj); +size_t G1CMObjArrayProcessor::process_slice(HeapWord* slice) { // Find the start address of the objArrayOop. // Shortcut the BOT access if the given address is from a humongous object. The BOT // slide is fast enough for "smaller" objects in non-humongous regions, but is slower // than directly using heap region table. G1CollectedHeap* g1h = G1CollectedHeap::heap(); - HeapRegion* r = g1h->heap_region_containing(decoded_address); + HeapRegion* r = g1h->heap_region_containing(slice); HeapWord* const start_address = r->is_humongous() ? r->humongous_start_region()->bottom() : - g1h->block_start(decoded_address); + g1h->block_start(slice); assert(oop(start_address)->is_objArray(), "Address " PTR_FORMAT " does not refer to an object array ", p2i(start_address)); - assert(start_address < decoded_address, + assert(start_address < slice, "Object start address " PTR_FORMAT " must be smaller than decoded address " PTR_FORMAT, p2i(start_address), - p2i(decoded_address)); + p2i(slice)); objArrayOop objArray = objArrayOop(start_address); - size_t already_scanned = decoded_address - start_address; + size_t already_scanned = slice - start_address; size_t remaining = objArray->size() - already_scanned; - return process_array_slice(objArray, decoded_address, remaining); + return process_array_slice(objArray, slice, remaining); } diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp index 9e16e98629c..3528a32ed0a 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -36,32 +36,22 @@ class G1CMTask; // This allows incremental processing of large objects. class G1CMObjArrayProcessor VALUE_OBJ_CLASS_SPEC { private: - // The bit mask for the continuation indicator of elements on the mark stack. - static const size_t ArraySliceBit = 1; - // Reference to the task for doing the actual work. G1CMTask* _task; - // Encodes the given address as a continuation "oop". - oop encode_array_slice(HeapWord* addr); - // Remove the continuation marker from the given oop from the mark stack. - HeapWord* decode_array_slice(oop value); - // Push the continuation at the given address onto the mark stack. void push_array_slice(HeapWord* addr); // Process (apply the closure) on the given continuation of the given objArray. size_t process_array_slice(objArrayOop const obj, HeapWord* start_from, size_t remaining); public: - static bool is_array_slice(void* obj) { return ((uintptr_t)obj & ArraySliceBit) != 0; } - static bool should_be_sliced(oop obj); G1CMObjArrayProcessor(G1CMTask* task) : _task(task) { } - // Process the given continuation "oop". Returns the number of words scanned. - size_t process_slice(oop obj); + // Process the given continuation. Returns the number of words scanned. + size_t process_slice(HeapWord* slice); // Start processing the given objArrayOop by scanning the header and pushing its // continuation. size_t process_obj(oop obj); From 4b9562288f4585fb1fd7d5dbbf4e603e2bc38819 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 15 Mar 2017 10:25:37 -0400 Subject: [PATCH 58/86] 8155672: Remove instanceKlassHandles and KlassHandles Use unhandled pointers for Klass and InstanceKlass, remove handles with no implementation. Reviewed-by: dholmes, lfoltan, vlivanov, sspitsyn --- .../cpu/aarch64/vm/methodHandles_aarch64.cpp | 4 +- hotspot/src/cpu/arm/vm/methodHandles_arm.cpp | 4 +- hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp | 4 +- .../src/cpu/s390/vm/methodHandles_s390.cpp | 4 +- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 4 +- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 4 +- hotspot/src/share/vm/aot/aotCodeHeap.cpp | 36 +- hotspot/src/share/vm/aot/aotCodeHeap.hpp | 8 +- .../src/share/vm/aot/aotCompiledMethod.cpp | 5 +- .../src/share/vm/aot/aotCompiledMethod.hpp | 4 +- hotspot/src/share/vm/aot/aotLoader.cpp | 6 +- hotspot/src/share/vm/aot/aotLoader.hpp | 6 +- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 19 +- hotspot/src/share/vm/ci/ciArrayKlass.cpp | 4 +- hotspot/src/share/vm/ci/ciArrayKlass.hpp | 4 +- hotspot/src/share/vm/ci/ciEnv.cpp | 32 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 8 +- hotspot/src/share/vm/ci/ciInstanceKlass.hpp | 4 +- hotspot/src/share/vm/ci/ciKlass.cpp | 12 +- hotspot/src/share/vm/ci/ciKlass.hpp | 6 +- hotspot/src/share/vm/ci/ciMethod.cpp | 26 +- hotspot/src/share/vm/ci/ciObjArrayKlass.cpp | 4 +- hotspot/src/share/vm/ci/ciObjArrayKlass.hpp | 4 +- hotspot/src/share/vm/ci/ciObjectFactory.cpp | 7 +- hotspot/src/share/vm/ci/ciReplay.cpp | 10 +- hotspot/src/share/vm/ci/ciType.cpp | 6 +- hotspot/src/share/vm/ci/ciType.hpp | 4 +- hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp | 4 +- hotspot/src/share/vm/ci/ciTypeArrayKlass.hpp | 4 +- .../share/vm/classfile/classFileParser.cpp | 15 +- .../src/share/vm/classfile/classLoader.cpp | 33 +- .../src/share/vm/classfile/classLoader.hpp | 4 +- .../share/vm/classfile/classLoaderData.cpp | 2 +- .../src/share/vm/classfile/classLoaderExt.hpp | 12 +- hotspot/src/share/vm/classfile/dictionary.cpp | 40 +- hotspot/src/share/vm/classfile/dictionary.hpp | 40 +- .../src/share/vm/classfile/javaAssertions.cpp | 4 +- .../src/share/vm/classfile/javaClasses.cpp | 93 +++-- .../src/share/vm/classfile/javaClasses.hpp | 16 +- .../src/share/vm/classfile/klassFactory.cpp | 43 +- .../src/share/vm/classfile/klassFactory.hpp | 20 +- .../share/vm/classfile/loaderConstraints.cpp | 41 +- .../share/vm/classfile/loaderConstraints.hpp | 38 +- .../src/share/vm/classfile/moduleEntry.cpp | 2 +- .../src/share/vm/classfile/placeholders.hpp | 8 +- .../share/vm/classfile/systemDictionary.cpp | 367 +++++++++--------- .../share/vm/classfile/systemDictionary.hpp | 90 ++--- .../vm/classfile/systemDictionaryShared.hpp | 14 +- .../share/vm/classfile/verificationType.cpp | 18 +- .../share/vm/classfile/verificationType.hpp | 4 +- hotspot/src/share/vm/classfile/verifier.cpp | 30 +- hotspot/src/share/vm/classfile/verifier.hpp | 20 +- hotspot/src/share/vm/code/codeCache.cpp | 12 +- hotspot/src/share/vm/code/codeCache.hpp | 8 +- hotspot/src/share/vm/code/compiledIC.cpp | 8 +- hotspot/src/share/vm/code/compiledIC.hpp | 4 +- hotspot/src/share/vm/code/dependencies.hpp | 8 +- .../src/share/vm/compiler/compileBroker.cpp | 4 +- .../src/share/vm/gc/shared/allocTracer.cpp | 10 +- .../src/share/vm/gc/shared/allocTracer.hpp | 6 +- .../src/share/vm/gc/shared/collectedHeap.cpp | 4 +- .../src/share/vm/gc/shared/collectedHeap.hpp | 28 +- .../vm/gc/shared/collectedHeap.inline.hpp | 36 +- .../vm/interpreter/interpreterRuntime.cpp | 23 +- .../src/share/vm/interpreter/linkResolver.cpp | 338 ++++++++-------- .../src/share/vm/interpreter/linkResolver.hpp | 84 ++-- hotspot/src/share/vm/interpreter/rewriter.cpp | 8 +- hotspot/src/share/vm/interpreter/rewriter.hpp | 8 +- .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 40 +- .../src/share/vm/jvmci/jvmciCompilerToVM.hpp | 2 +- hotspot/src/share/vm/jvmci/jvmciEnv.cpp | 123 +++--- hotspot/src/share/vm/jvmci/jvmciEnv.hpp | 44 +-- hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 14 +- hotspot/src/share/vm/memory/universe.cpp | 50 ++- hotspot/src/share/vm/memory/universe.hpp | 2 +- hotspot/src/share/vm/oops/arrayKlass.cpp | 4 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 4 +- hotspot/src/share/vm/oops/constantPool.cpp | 39 +- hotspot/src/share/vm/oops/constantPool.hpp | 6 +- hotspot/src/share/vm/oops/cpCache.cpp | 4 +- hotspot/src/share/vm/oops/cpCache.hpp | 4 +- hotspot/src/share/vm/oops/fieldStreams.hpp | 14 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 157 ++++---- hotspot/src/share/vm/oops/instanceKlass.hpp | 32 +- .../src/share/vm/oops/instanceMirrorKlass.cpp | 14 +- .../src/share/vm/oops/instanceMirrorKlass.hpp | 6 +- hotspot/src/share/vm/oops/klass.cpp | 7 +- hotspot/src/share/vm/oops/klassVtable.cpp | 63 ++- hotspot/src/share/vm/oops/klassVtable.hpp | 24 +- hotspot/src/share/vm/oops/method.cpp | 13 +- hotspot/src/share/vm/oops/method.hpp | 5 +- hotspot/src/share/vm/oops/objArrayKlass.cpp | 53 ++- hotspot/src/share/vm/oops/objArrayKlass.hpp | 8 +- hotspot/src/share/vm/oops/typeArrayKlass.cpp | 7 +- hotspot/src/share/vm/prims/jni.cpp | 110 +++--- hotspot/src/share/vm/prims/jvm.cpp | 84 ++-- .../vm/prims/jvmtiClassFileReconstituter.cpp | 60 +-- .../vm/prims/jvmtiClassFileReconstituter.hpp | 16 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 88 ++--- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 6 +- hotspot/src/share/vm/prims/jvmtiExport.cpp | 49 ++- hotspot/src/share/vm/prims/jvmtiExport.hpp | 8 +- hotspot/src/share/vm/prims/jvmtiImpl.cpp | 10 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 139 ++++--- .../share/vm/prims/jvmtiRedefineClasses.hpp | 44 +-- hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 46 +-- hotspot/src/share/vm/prims/jvmtiTagMap.hpp | 8 +- .../src/share/vm/prims/jvmtiThreadState.hpp | 30 +- hotspot/src/share/vm/prims/methodHandles.cpp | 71 ++-- hotspot/src/share/vm/prims/methodHandles.hpp | 6 +- hotspot/src/share/vm/prims/nativeLookup.cpp | 11 +- hotspot/src/share/vm/prims/stackwalk.cpp | 2 +- hotspot/src/share/vm/prims/unsafe.cpp | 13 +- hotspot/src/share/vm/prims/whitebox.cpp | 20 +- .../src/share/vm/runtime/deoptimization.cpp | 16 +- .../src/share/vm/runtime/fieldDescriptor.hpp | 6 +- hotspot/src/share/vm/runtime/handles.cpp | 5 - hotspot/src/share/vm/runtime/handles.hpp | 42 -- .../src/share/vm/runtime/handles.inline.hpp | 2 +- hotspot/src/share/vm/runtime/javaCalls.cpp | 30 +- hotspot/src/share/vm/runtime/javaCalls.hpp | 28 +- .../share/vm/runtime/jfieldIDWorkaround.hpp | 6 +- hotspot/src/share/vm/runtime/os.cpp | 13 +- hotspot/src/share/vm/runtime/reflection.cpp | 36 +- hotspot/src/share/vm/runtime/reflection.hpp | 4 +- .../src/share/vm/runtime/reflectionUtils.cpp | 8 +- .../src/share/vm/runtime/reflectionUtils.hpp | 22 +- .../src/share/vm/runtime/serviceThread.cpp | 4 +- .../src/share/vm/runtime/sharedRuntime.cpp | 22 +- hotspot/src/share/vm/runtime/statSampler.cpp | 4 +- hotspot/src/share/vm/runtime/thread.cpp | 54 ++- hotspot/src/share/vm/runtime/vframe.cpp | 4 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 8 +- .../src/share/vm/runtime/vm_operations.hpp | 4 +- .../src/share/vm/services/attachListener.cpp | 25 +- .../share/vm/services/classLoadingService.cpp | 15 +- .../share/vm/services/classLoadingService.hpp | 21 +- .../share/vm/services/diagnosticCommand.cpp | 20 +- .../share/vm/services/diagnosticFramework.cpp | 4 +- hotspot/src/share/vm/services/gcNotifier.cpp | 26 +- hotspot/src/share/vm/services/heapDumper.cpp | 24 +- .../share/vm/services/lowMemoryDetector.cpp | 8 +- hotspot/src/share/vm/services/management.cpp | 90 ++--- hotspot/src/share/vm/services/management.hpp | 50 +-- .../src/share/vm/services/memoryManager.cpp | 4 +- hotspot/src/share/vm/services/memoryPool.cpp | 5 +- .../src/share/vm/services/memoryService.cpp | 5 +- .../src/share/vm/services/threadService.cpp | 7 +- hotspot/src/share/vm/shark/sharkRuntime.cpp | 11 +- hotspot/src/share/vm/utilities/exceptions.cpp | 5 +- hotspot/src/share/vm/utilities/xmlstream.cpp | 10 +- hotspot/src/share/vm/utilities/xmlstream.hpp | 6 +- 152 files changed, 1892 insertions(+), 2112 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp index dedabb6729b..ce958fcff40 100644 --- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -63,7 +63,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rscratch2; Register temp2 = rscratch1; // used by MacroAssembler::cmpptr Label L_ok, L_bad; diff --git a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp index 15317969319..45e609bff39 100644 --- a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp +++ b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -67,7 +67,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, Register temp1, Register temp2, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj); diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp index a4bb111d9e0..b6c7b1d5914 100644 --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj_reg); diff --git a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp index e2f0d32cc8a..af7c511b36e 100644 --- a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp +++ b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -73,7 +73,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + KLass* klass = SystemDictionary::well_known_klass(klass_id); assert(temp_reg != Z_R0 && // Is used as base register! temp_reg != noreg && temp2_reg != noreg, "need valid registers!"); diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index f93dbf17212..4f10fd42a2f 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); bool did_save = false; if (temp_reg == noreg || temp2_reg == noreg) { temp_reg = L1; diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 399172b5a15..99c62d470d6 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -65,7 +65,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rdi; Register temp2 = noreg; LP64_ONLY(temp2 = rscratch1); // used by MacroAssembler::cmpptr diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.cpp b/hotspot/src/share/vm/aot/aotCodeHeap.cpp index 2fd8c9bbb82..f2902d83e86 100644 --- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp +++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp @@ -560,7 +560,7 @@ void AOTCodeHeap::print_statistics() { } #endif -Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char* method_name) { +Method* AOTCodeHeap::find_method(Klass* klass, Thread* thread, const char* method_name) { int method_name_len = build_u2_from((address)method_name); method_name += 2; const char* signature_name = method_name + method_name_len; @@ -578,14 +578,14 @@ Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char* name == vmSymbols::class_initializer_name()) { // Never search superclasses for constructors if (klass->is_instance_klass()) { - m = InstanceKlass::cast(klass())->find_method(name, signature); + m = InstanceKlass::cast(klass)->find_method(name, signature); } else { m = NULL; } } else { m = klass->lookup_method(name, signature); if (m == NULL && klass->is_instance_klass()) { - m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature); + m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name, signature); } } if (m == NULL) { @@ -669,28 +669,28 @@ void AOTCodeHeap::sweep_dependent_methods(AOTKlassData* klass_data) { } } -bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) { +bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) { ResourceMark rm; NOT_PRODUCT( klasses_seen++; ) - AOTKlassData* klass_data = find_klass(kh()); + AOTKlassData* klass_data = find_klass(ik); if (klass_data == NULL) { return false; } - if (!kh->has_passed_fingerprint_check()) { + if (!ik->has_passed_fingerprint_check()) { NOT_PRODUCT( aot_klasses_fp_miss++; ) log_trace(aot, class, fingerprint)("class %s%s has bad fingerprint in %s tid=" INTPTR_FORMAT, - kh->internal_name(), kh->is_shared() ? " (shared)" : "", + ik->internal_name(), ik->is_shared() ? " (shared)" : "", _lib->name(), p2i(thread)); sweep_dependent_methods(klass_data); return false; } - if (kh->has_been_redefined()) { + if (ik->has_been_redefined()) { log_trace(aot, class, load)("class %s%s in %s has been redefined tid=" INTPTR_FORMAT, - kh->internal_name(), kh->is_shared() ? " (shared)" : "", + ik->internal_name(), ik->is_shared() ? " (shared)" : "", _lib->name(), p2i(thread)); sweep_dependent_methods(klass_data); return false; @@ -698,26 +698,26 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) { assert(klass_data->_class_id < _class_count, "invalid class id"); AOTClass* aot_class = &_classes[klass_data->_class_id]; - if (aot_class->_classloader != NULL && aot_class->_classloader != kh->class_loader_data()) { + if (aot_class->_classloader != NULL && aot_class->_classloader != ik->class_loader_data()) { log_trace(aot, class, load)("class %s in %s already loaded for classloader %p vs %p tid=" INTPTR_FORMAT, - kh->internal_name(), _lib->name(), aot_class->_classloader, kh->class_loader_data(), p2i(thread)); + ik->internal_name(), _lib->name(), aot_class->_classloader, ik->class_loader_data(), p2i(thread)); NOT_PRODUCT( aot_klasses_cl_miss++; ) return false; } - if (_lib->config()->_omitAssertions && JavaAssertions::enabled(kh->name()->as_C_string(), kh->class_loader() == NULL)) { - log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", kh->internal_name(), _lib->name()); + if (_lib->config()->_omitAssertions && JavaAssertions::enabled(ik->name()->as_C_string(), ik->class_loader() == NULL)) { + log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", ik->internal_name(), _lib->name()); sweep_dependent_methods(klass_data); return false; } NOT_PRODUCT( aot_klasses_found++; ) - log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread)); + log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, ik->internal_name(), _lib->name(), ik->class_loader_data(), p2i(thread)); - aot_class->_classloader = kh->class_loader_data(); + aot_class->_classloader = ik->class_loader_data(); // Set klass's Resolve (second) got cell. - _metaspace_got[klass_data->_got_index] = kh(); + _metaspace_got[klass_data->_got_index] = ik; // Initialize global symbols of the DSO to the corresponding VM symbol values. link_global_lib_symbols(); @@ -745,7 +745,7 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) { // aot_name format: "Ljava/lang/ThreadGroup;addUnstarted()V" int klass_len = build_u2_from((address)aot_name); const char* method_name = aot_name + 2 + klass_len; - Method* m = AOTCodeHeap::find_method(kh, thread, method_name); + Method* m = AOTCodeHeap::find_method(ik, thread, method_name); methodHandle mh(thread, m); if (mh->code() != NULL) { // Does it have already compiled code? continue; // Don't overwrite @@ -866,7 +866,7 @@ int AOTCodeHeap::verify_icholder_relocations() { } #endif -void AOTCodeHeap::flush_evol_dependents_on(instanceKlassHandle dependee) { +void AOTCodeHeap::flush_evol_dependents_on(InstanceKlass* dependee) { for (int index = 0; index < _method_count; index++) { if (_code_to_aot[index]._state != in_use) { continue; // Skip uninitialized entries. diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.hpp b/hotspot/src/share/vm/aot/aotCodeHeap.hpp index 5c803cc0903..9643abb7313 100644 --- a/hotspot/src/share/vm/aot/aotCodeHeap.hpp +++ b/hotspot/src/share/vm/aot/aotCodeHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -253,7 +253,7 @@ public: virtual void* next(void *p) const; AOTKlassData* find_klass(InstanceKlass* ik); - bool load_klass_data(instanceKlassHandle kh, Thread* thread); + bool load_klass_data(InstanceKlass* ik, Thread* thread); Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method); void sweep_dependent_methods(AOTKlassData* klass_data); bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot); @@ -289,13 +289,13 @@ public: return NULL; } - static Method* find_method(KlassHandle klass, Thread* thread, const char* method_name); + static Method* find_method(Klass* klass, Thread* thread, const char* method_name); void cleanup_inline_caches(); DEBUG_ONLY( int verify_icholder_relocations(); ) - void flush_evol_dependents_on(instanceKlassHandle dependee); + void flush_evol_dependents_on(InstanceKlass* dependee); void alive_methods_do(void f(CompiledMethod* nm)); diff --git a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp index b38362ff065..72f82811a80 100644 --- a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp +++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp @@ -143,9 +143,8 @@ Metadata* AOTCompiledMethod::metadata_at(int index) const { int full_len = 2 + klass_len + 2 + method_name_len + 2 + signature_len; if (!klass_matched || memcmp(_name, meta_name, full_len) != 0) { // Does not match? Thread* thread = Thread::current(); - KlassHandle klass = KlassHandle(thread, k); const char* method_name = klass_name + klass_len; - m = AOTCodeHeap::find_method(klass, thread, method_name); + m = AOTCodeHeap::find_method(k, thread, method_name); } meta = ((intptr_t)m) | 1; *entry = (Metadata*)meta; // Should be atomic on x64 @@ -239,7 +238,7 @@ bool AOTCompiledMethod::make_entrant() { // We don't have full dependencies for AOT methods, so flushing is // more conservative than for nmethods. -void AOTCompiledMethod::flush_evol_dependents_on(instanceKlassHandle dependee) { +void AOTCompiledMethod::flush_evol_dependents_on(InstanceKlass* dependee) { if (is_java_method()) { cleanup_inline_caches(); mark_for_deoptimization(); diff --git a/hotspot/src/share/vm/aot/aotCompiledMethod.hpp b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp index 723bbdb8d30..cea01c8f568 100644 --- a/hotspot/src/share/vm/aot/aotCompiledMethod.hpp +++ b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -240,7 +240,7 @@ private: #ifdef HOTSWAP // Flushing and deoptimization in case of evolution - void flush_evol_dependents_on(instanceKlassHandle dependee); + void flush_evol_dependents_on(InstanceKlass* dependee); #endif // HOTSWAP virtual void metadata_do(void f(Metadata*)); diff --git a/hotspot/src/share/vm/aot/aotLoader.cpp b/hotspot/src/share/vm/aot/aotLoader.cpp index 1d0bb1be1d6..679550b9d03 100644 --- a/hotspot/src/share/vm/aot/aotLoader.cpp +++ b/hotspot/src/share/vm/aot/aotLoader.cpp @@ -37,10 +37,10 @@ GrowableArray* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) // Iterate over all AOT Libraries #define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator lib = libraries()->begin(); lib != libraries()->end(); ++lib) -void AOTLoader::load_for_klass(instanceKlassHandle kh, Thread* thread) { +void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) { if (UseAOT) { FOR_ALL_AOT_HEAPS(heap) { - (*heap)->load_klass_data(kh, thread); + (*heap)->load_klass_data(ik, thread); } } } @@ -98,7 +98,7 @@ address AOTLoader::exception_begin(JavaThread* thread, CodeBlob* blob, address r } // Flushing and deoptimization in case of evolution -void AOTLoader::flush_evol_dependents_on(instanceKlassHandle dependee) { +void AOTLoader::flush_evol_dependents_on(InstanceKlass* dependee) { // make non entrant and mark for deoptimization FOR_ALL_AOT_HEAPS(heap) { (*heap)->flush_evol_dependents_on(dependee); diff --git a/hotspot/src/share/vm/aot/aotLoader.hpp b/hotspot/src/share/vm/aot/aotLoader.hpp index b556eb5980c..fd5dead348f 100644 --- a/hotspot/src/share/vm/aot/aotLoader.hpp +++ b/hotspot/src/share/vm/aot/aotLoader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -58,7 +58,7 @@ public: static void universe_init() NOT_AOT_RETURN; static void set_narrow_klass_shift() NOT_AOT_RETURN; static bool contains(address p) NOT_AOT({ return false; }); - static void load_for_klass(instanceKlassHandle, Thread* thread) NOT_AOT_RETURN; + static void load_for_klass(InstanceKlass* ik, Thread* thread) NOT_AOT_RETURN; static bool find_klass(InstanceKlass* ik) NOT_AOT({ return false; }); static uint64_t get_saved_fingerprint(InstanceKlass* ik) NOT_AOT({ return 0; }); static void oops_do(OopClosure* f) NOT_AOT_RETURN; @@ -69,7 +69,7 @@ public: #ifdef HOTSWAP // Flushing and deoptimization in case of evolution - static void flush_evol_dependents_on(instanceKlassHandle dependee) NOT_AOT_RETURN; + static void flush_evol_dependents_on(InstanceKlass* dependee) NOT_AOT_RETURN; #endif // HOTSWAP }; diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index e353b2f7544..6c3360925e7 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -331,7 +331,7 @@ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* thread, Klass* klass)) assert(klass->is_klass(), "not a class"); Handle holder(THREAD, klass->klass_holder()); // keep the klass alive - instanceKlassHandle h(thread, klass); + InstanceKlass* h = InstanceKlass::cast(klass); h->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized h->initialize(CHECK); @@ -857,8 +857,8 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i bool deoptimize_for_volatile = false; bool deoptimize_for_atomic = false; int patch_field_offset = -1; - KlassHandle init_klass(THREAD, NULL); // klass needed by load_klass_patching code - KlassHandle load_klass(THREAD, NULL); // klass needed by load_klass_patching code + Klass* init_klass = NULL; // klass needed by load_klass_patching code + Klass* load_klass = NULL; // klass needed by load_klass_patching code Handle mirror(THREAD, NULL); // oop needed by load_mirror_patching code Handle appendix(THREAD, NULL); // oop needed by appendix_patching code bool load_klass_or_mirror_patch_id = @@ -905,7 +905,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i case Bytecodes::_putstatic: case Bytecodes::_getstatic: { Klass* klass = resolve_field_return_klass(caller_method, bci, CHECK); - init_klass = KlassHandle(THREAD, klass); + init_klass = klass; mirror = Handle(THREAD, klass->java_mirror()); } break; @@ -945,8 +945,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i break; default: fatal("unexpected bytecode for load_klass_or_mirror_patch_id"); } - // convert to handle - load_klass = KlassHandle(THREAD, k); + load_klass = k; } else if (stub_id == load_appendix_patching_id) { Bytecode_invoke bytecode(caller_method, bci); Bytecodes::Code bc = bytecode.invoke_code(); @@ -1067,7 +1066,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i // initializing thread are forced to come into the VM and // block. do_patch = (code != Bytecodes::_getstatic && code != Bytecodes::_putstatic) || - InstanceKlass::cast(init_klass())->is_initialized(); + InstanceKlass::cast(init_klass)->is_initialized(); NativeGeneralJump* jump = nativeGeneralJump_at(instr_pc); if (jump->jump_destination() == being_initialized_entry) { assert(do_patch == true, "initialization must be complete at this point"); @@ -1079,8 +1078,8 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i n_copy->data() == (intptr_t)Universe::non_oop_word(), "illegal init value"); if (stub_id == Runtime1::load_klass_patching_id) { - assert(load_klass() != NULL, "klass not set"); - n_copy->set_data((intx) (load_klass())); + assert(load_klass != NULL, "klass not set"); + n_copy->set_data((intx) (load_klass)); } else { assert(mirror() != NULL, "klass not set"); // Don't need a G1 pre-barrier here since we assert above that data isn't an oop. @@ -1131,7 +1130,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id"); metadata_Relocation* r = mds.metadata_reloc(); Metadata** metadata_adr = r->metadata_addr(); - *metadata_adr = load_klass(); + *metadata_adr = load_klass; r->fix_metadata_relocation(); found = true; } diff --git a/hotspot/src/share/vm/ci/ciArrayKlass.cpp b/hotspot/src/share/vm/ci/ciArrayKlass.cpp index ebff3a90d90..e4d66f247a4 100644 --- a/hotspot/src/share/vm/ci/ciArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -37,7 +37,7 @@ // ciArrayKlass::ciArrayKlass // // Loaded array klass. -ciArrayKlass::ciArrayKlass(KlassHandle h_k) : ciKlass(h_k) { +ciArrayKlass::ciArrayKlass(Klass* k) : ciKlass(k) { assert(get_Klass()->is_array_klass(), "wrong type"); _dimension = get_ArrayKlass()->dimension(); } diff --git a/hotspot/src/share/vm/ci/ciArrayKlass.hpp b/hotspot/src/share/vm/ci/ciArrayKlass.hpp index e5c74e8865c..afb55bb5e44 100644 --- a/hotspot/src/share/vm/ci/ciArrayKlass.hpp +++ b/hotspot/src/share/vm/ci/ciArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -37,7 +37,7 @@ private: jint _dimension; protected: - ciArrayKlass(KlassHandle h_k); + ciArrayKlass(Klass* k); ciArrayKlass(ciSymbol* name, int dimension, BasicType bt); ArrayKlass* get_ArrayKlass() { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 6f754de1c21..2320714d287 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -426,7 +426,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, } else { fail_type = _unloaded_ciinstance_klass; } - KlassHandle found_klass; + Klass* found_klass; { ttyUnlocker ttyul; // release tty lock to avoid ordering problems MutexLocker ml(Compile_lock); @@ -438,7 +438,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, KILL_COMPILE_ON_FATAL_(fail_type)); } - found_klass = KlassHandle(THREAD, kls); + found_klass = kls; } // If we fail to find an array klass, look again for its element type. @@ -467,22 +467,22 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, } } - if (found_klass() == NULL && !cpool.is_null() && cpool->has_preresolution()) { + if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) { // Look inside the constant pool for pre-resolved class entries. for (int i = cpool->length() - 1; i >= 1; i--) { if (cpool->tag_at(i).is_klass()) { Klass* kls = cpool->resolved_klass_at(i); if (kls->name() == sym) { - found_klass = KlassHandle(THREAD, kls); + found_klass = kls; break; } } } } - if (found_klass() != NULL) { + if (found_klass != NULL) { // Found it. Build a CI handle. - return get_klass(found_klass()); + return get_klass(found_klass); } if (require_local) return NULL; @@ -512,21 +512,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, bool& is_accessible, ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - KlassHandle klass; // = NULL; + Klass* klass = NULL; Symbol* klass_name = NULL; if (cpool->tag_at(index).is_symbol()) { klass_name = cpool->symbol_at(index); } else { // Check if it's resolved if it's not a symbol constant pool entry. - klass = KlassHandle(THREAD, ConstantPool::klass_at_if_loaded(cpool, index)); + klass = ConstantPool::klass_at_if_loaded(cpool, index); // Try to look it up by name. - if (klass.is_null()) { + if (klass == NULL) { klass_name = cpool->klass_name_at(index); - } + } } - if (klass.is_null()) { + if (klass == NULL) { // Not found in constant pool. Use the name to do the lookup. ciKlass* k = get_klass_by_name_impl(accessor, cpool, @@ -548,7 +548,7 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, // Check for prior unloaded klass. The SystemDictionary's answers // can vary over time but the compiler needs consistency. - ciSymbol* name = get_symbol(klass()->name()); + ciSymbol* name = get_symbol(klass->name()); ciKlass* unloaded_klass = check_get_unloaded_klass(accessor, name); if (unloaded_klass != NULL) { is_accessible = false; @@ -557,7 +557,7 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, // It is known to be accessible, since it was found in the constant pool. is_accessible = true; - return get_klass(klass()); + return get_klass(klass); } // ------------------------------------------------------------------ @@ -713,10 +713,10 @@ Method* ciEnv::lookup_method(ciInstanceKlass* accessor, // Accessibility checks are performed in ciEnv::get_method_by_index_impl. assert(check_klass_accessibility(accessor, holder->get_Klass()), "holder not accessible"); - KlassHandle h_accessor(accessor->get_instanceKlass()); - KlassHandle h_holder(holder->get_Klass()); + InstanceKlass* accessor_klass = accessor->get_instanceKlass(); + Klass* holder_klass = holder->get_Klass(); methodHandle dest_method; - LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); + LinkInfo link_info(holder_klass, name, sig, accessor_klass, LinkInfo::needs_access_check, tag); switch (bc) { case Bytecodes::_invokestatic: dest_method = diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index b8133ab754e..f627a3324a1 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -44,8 +44,8 @@ // ciInstanceKlass::ciInstanceKlass // // Loaded instance klass. -ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : - ciKlass(h_k) +ciInstanceKlass::ciInstanceKlass(Klass* k) : + ciKlass(k) { assert(get_Klass()->is_instance_klass(), "wrong type"); assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); @@ -83,7 +83,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : _java_mirror = NULL; if (is_shared()) { - if (h_k() != SystemDictionary::Object_klass()) { + if (k != SystemDictionary::Object_klass()) { super(); } //compute_nonstatic_fields(); // done outside of constructor diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp index 1215c089ff4..aff14499449 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -77,7 +77,7 @@ private: bool compute_injected_fields_helper(); protected: - ciInstanceKlass(KlassHandle h_k); + ciInstanceKlass(Klass* k); ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain); InstanceKlass* get_instanceKlass() const { diff --git a/hotspot/src/share/vm/ci/ciKlass.cpp b/hotspot/src/share/vm/ci/ciKlass.cpp index ab980fafafc..6a0a4ffeba6 100644 --- a/hotspot/src/share/vm/ci/ciKlass.cpp +++ b/hotspot/src/share/vm/ci/ciKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -35,11 +35,11 @@ // ------------------------------------------------------------------ // ciKlass::ciKlass -ciKlass::ciKlass(KlassHandle h_k) : ciType(h_k) { +ciKlass::ciKlass(Klass* k) : ciType(k) { assert(get_Klass()->is_klass(), "wrong type"); - Klass* k = get_Klass(); - _layout_helper = k->layout_helper(); - Symbol* klass_name = k->name(); + Klass* klass = get_Klass(); + _layout_helper = klass->layout_helper(); + Symbol* klass_name = klass->name(); assert(klass_name != NULL, "wrong ciKlass constructor"); _name = CURRENT_ENV->get_symbol(klass_name); } @@ -48,7 +48,7 @@ ciKlass::ciKlass(KlassHandle h_k) : ciType(h_k) { // ciKlass::ciKlass // // Nameless klass variant. -ciKlass::ciKlass(KlassHandle h_k, ciSymbol* name) : ciType(h_k) { +ciKlass::ciKlass(Klass* k, ciSymbol* name) : ciType(k) { assert(get_Klass()->is_klass(), "wrong type"); _name = name; _layout_helper = Klass::_lh_neutral_value; diff --git a/hotspot/src/share/vm/ci/ciKlass.hpp b/hotspot/src/share/vm/ci/ciKlass.hpp index 1ee57b76299..896f489453a 100644 --- a/hotspot/src/share/vm/ci/ciKlass.hpp +++ b/hotspot/src/share/vm/ci/ciKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -51,7 +51,7 @@ private: jint _layout_helper; protected: - ciKlass(KlassHandle k_h, ciSymbol* name); + ciKlass(Klass* k, ciSymbol* name); ciKlass(ciSymbol* name, BasicType bt); Klass* get_Klass() const { @@ -72,7 +72,7 @@ protected: void print_impl(outputStream* st); public: - ciKlass(KlassHandle k_h); + ciKlass(Klass* k); // What is the name of this klass? ciSymbol* name() const { return _name; } diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index c4c183c56f3..74a4cdd8dd2 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -783,24 +783,24 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo check_is_loaded(); VM_ENTRY_MARK; - KlassHandle caller_klass (THREAD, caller->get_Klass()); - KlassHandle h_recv (THREAD, exact_receiver->get_Klass()); - KlassHandle h_resolved (THREAD, holder()->get_Klass()); + Klass* caller_klass = caller->get_Klass(); + Klass* recv = exact_receiver->get_Klass(); + Klass* resolved = holder()->get_Klass(); Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, + LinkInfo link_info(resolved, h_name, h_signature, caller_klass, check_access ? LinkInfo::needs_access_check : LinkInfo::skip_access_check); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. - if (h_recv->is_array_klass() + if (recv->is_array_klass() || - InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) { + InstanceKlass::cast(recv)->is_linked() && !exact_receiver->is_interface()) { if (holder()->is_interface()) { - m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info); + m = LinkResolver::resolve_interface_call_or_null(recv, link_info); } else { - m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info); + m = LinkResolver::resolve_virtual_call_or_null(recv, link_info); } } @@ -839,13 +839,13 @@ int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) { receiver->as_instance_klass()->is_linked())) { VM_ENTRY_MARK; - KlassHandle caller_klass (THREAD, caller->get_Klass()); - KlassHandle h_recv (THREAD, receiver->get_Klass()); + Klass* caller_klass = caller->get_Klass(); + Klass* recv = receiver->get_Klass(); Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - LinkInfo link_info(h_recv, h_name, h_signature, caller_klass); - vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info); + LinkInfo link_info(recv, h_name, h_signature, caller_klass); + vtable_index = LinkResolver::resolve_virtual_vtable_index(recv, link_info); if (vtable_index == Method::nonvirtual_vtable_index) { // A statically bound method. Return "no such index". vtable_index = Method::invalid_vtable_index; diff --git a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp index d1946659fb7..7e477d8a15a 100644 --- a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -38,7 +38,7 @@ // ciObjArrayKlass::ciObjArrayKlass // // Constructor for loaded object array klasses. -ciObjArrayKlass::ciObjArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) { +ciObjArrayKlass::ciObjArrayKlass(Klass* k) : ciArrayKlass(k) { assert(get_Klass()->is_objArray_klass(), "wrong type"); Klass* element_Klass = get_ObjArrayKlass()->bottom_klass(); _base_element_klass = CURRENT_ENV->get_klass(element_Klass); diff --git a/hotspot/src/share/vm/ci/ciObjArrayKlass.hpp b/hotspot/src/share/vm/ci/ciObjArrayKlass.hpp index e50814c0f8e..264fa66ced3 100644 --- a/hotspot/src/share/vm/ci/ciObjArrayKlass.hpp +++ b/hotspot/src/share/vm/ci/ciObjArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -40,7 +40,7 @@ private: ciKlass* _base_element_klass; protected: - ciObjArrayKlass(KlassHandle h_k); + ciObjArrayKlass(Klass* k); ciObjArrayKlass(ciSymbol* array_name, ciKlass* base_element_klass, int dimension); diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index 50ab44ebb0d..494f9c52c3e 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -377,14 +377,13 @@ ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { } if (o->is_klass()) { - KlassHandle h_k(THREAD, (Klass*)o); Klass* k = (Klass*)o; if (k->is_instance_klass()) { - return new (arena()) ciInstanceKlass(h_k); + return new (arena()) ciInstanceKlass(k); } else if (k->is_objArray_klass()) { - return new (arena()) ciObjArrayKlass(h_k); + return new (arena()) ciObjArrayKlass(k); } else if (k->is_typeArray_klass()) { - return new (arena()) ciTypeArrayKlass(h_k); + return new (arena()) ciTypeArrayKlass(k); } } else if (o->is_method()) { methodHandle h_m(THREAD, (Method*)o); diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index 5fed56977b1..323cde6baf6 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -799,8 +799,8 @@ class CompileReplay : public StackObj { } else if (strcmp(field_signature, "[J") == 0) { value = oopFactory::new_longArray(length, CHECK); } else if (field_signature[0] == '[' && field_signature[1] == 'L') { - KlassHandle kelem = resolve_klass(field_signature + 1, CHECK); - value = oopFactory::new_objArray(kelem(), length, CHECK); + Klass* kelem = resolve_klass(field_signature + 1, CHECK); + value = oopFactory::new_objArray(kelem, length, CHECK); } else { report_error("unhandled array staticfield"); } @@ -840,8 +840,8 @@ class CompileReplay : public StackObj { Handle value = java_lang_String::create_from_str(string_value, CHECK); java_mirror->obj_field_put(fd.offset(), value()); } else if (field_signature[0] == 'L') { - KlassHandle k = resolve_klass(string_value, CHECK); - oop value = InstanceKlass::cast(k())->allocate_instance(CHECK); + Klass* k = resolve_klass(string_value, CHECK); + oop value = InstanceKlass::cast(k)->allocate_instance(CHECK); java_mirror->obj_field_put(fd.offset(), value); } else { report_error("unhandled staticfield"); diff --git a/hotspot/src/share/vm/ci/ciType.cpp b/hotspot/src/share/vm/ci/ciType.cpp index 7c3ffdb4a33..695cb70a549 100644 --- a/hotspot/src/share/vm/ci/ciType.cpp +++ b/hotspot/src/share/vm/ci/ciType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -45,8 +45,8 @@ ciType::ciType(BasicType basic_type) : ciMetadata() { _basic_type = basic_type; } -ciType::ciType(KlassHandle k) : ciMetadata(k()) { - _basic_type = k()->is_array_klass() ? T_ARRAY : T_OBJECT; +ciType::ciType(Klass* k) : ciMetadata(k) { + _basic_type = k->is_array_klass() ? T_ARRAY : T_OBJECT; } diff --git a/hotspot/src/share/vm/ci/ciType.hpp b/hotspot/src/share/vm/ci/ciType.hpp index c3901e4b06f..ad8718da664 100644 --- a/hotspot/src/share/vm/ci/ciType.hpp +++ b/hotspot/src/share/vm/ci/ciType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -40,7 +40,7 @@ private: BasicType _basic_type; ciType(BasicType t); // for primitive and unloaded types - ciType(KlassHandle k); // for subclasses (reference types) + ciType(Klass* k); // for subclasses (reference types) const char* type_string() { return "ciType"; } diff --git a/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp b/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp index 4b1e4ba603b..41e369985c6 100644 --- a/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ // ------------------------------------------------------------------ // ciTypeArrayKlass::ciTypeArrayKlass -ciTypeArrayKlass::ciTypeArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) { +ciTypeArrayKlass::ciTypeArrayKlass(Klass* k) : ciArrayKlass(k) { assert(get_Klass()->is_typeArray_klass(), "wrong type"); assert(element_type() == get_TypeArrayKlass()->element_type(), ""); } diff --git a/hotspot/src/share/vm/ci/ciTypeArrayKlass.hpp b/hotspot/src/share/vm/ci/ciTypeArrayKlass.hpp index 607c00cc50b..fe06621068a 100644 --- a/hotspot/src/share/vm/ci/ciTypeArrayKlass.hpp +++ b/hotspot/src/share/vm/ci/ciTypeArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -35,7 +35,7 @@ class ciTypeArrayKlass : public ciArrayKlass { CI_PACKAGE_ACCESS protected: - ciTypeArrayKlass(KlassHandle h_k); + ciTypeArrayKlass(Klass* k); TypeArrayKlass* get_TypeArrayKlass() { return (TypeArrayKlass*)get_Klass(); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 32b07e28c85..8f0c2de297f 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -815,13 +815,13 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, int index; for (index = 0; index < itfs_len; index++) { const u2 interface_index = stream->get_u2(CHECK); - KlassHandle interf; + Klass* interf; check_property( valid_klass_reference_at(interface_index), "Interface name has bad constant pool index %u in class file %s", interface_index, CHECK); if (cp->tag_at(interface_index).is_klass()) { - interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index)); + interf = cp->resolved_klass_at(interface_index); } else { Symbol* const unresolved_klass = cp->klass_name_at(interface_index); @@ -831,25 +831,24 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, "Bad interface name in class file %s", CHECK); // Call resolve_super so classcircularity is checked - const Klass* const k = - SystemDictionary::resolve_super_or_fail(_class_name, + interf = SystemDictionary::resolve_super_or_fail( + _class_name, unresolved_klass, Handle(THREAD, _loader_data->class_loader()), _protection_domain, false, CHECK); - interf = KlassHandle(THREAD, k); } - if (!interf()->is_interface()) { + if (!interf->is_interface()) { THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class"); } - if (InstanceKlass::cast(interf())->has_nonstatic_concrete_methods()) { + if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) { *has_nonstatic_concrete_methods = true; } - _local_interfaces->at_put(index, interf()); + _local_interfaces->at_put(index, interf); } if (!_need_verify || itfs_len <= 1) { diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 3dd5d59d7ab..10bf5890b87 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -1405,7 +1405,7 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArrayis_Java_thread(), "must be a JavaThread"); @@ -1512,13 +1512,13 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; - instanceKlassHandle result = KlassFactory::create_from_stream(stream, - name, - loader_data, - protection_domain, - NULL, // host_klass - NULL, // cp_patches - THREAD); + InstanceKlass* result = KlassFactory::create_from_stream(stream, + name, + loader_data, + protection_domain, + NULL, // host_klass + NULL, // cp_patches + THREAD); if (HAS_PENDING_EXCEPTION) { if (DumpSharedSpaces) { tty->print_cr("Preload Error: Failed to load %s", class_name); @@ -1891,15 +1891,15 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { // Construct name without extension TempNewSymbol sym = SymbolTable::new_symbol(buffer, CHECK); // Use loader to load and initialize class - Klass* ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD); - instanceKlassHandle k (THREAD, ik); - if (k.not_null() && !HAS_PENDING_EXCEPTION) { + Klass* k = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD); + if (k != NULL && !HAS_PENDING_EXCEPTION) { k->initialize(THREAD); } bool exception_occurred = HAS_PENDING_EXCEPTION; clear_pending_exception_if_not_oom(CHECK); - if (CompileTheWorldPreloadClasses && k.not_null()) { - ConstantPool::preload_and_initialize_all_classes(k->constants(), THREAD); + if (CompileTheWorldPreloadClasses && k != NULL) { + InstanceKlass* ik = InstanceKlass::cast(k); + ConstantPool::preload_and_initialize_all_classes(ik->constants(), THREAD); if (HAS_PENDING_EXCEPTION) { // If something went wrong in preloading we just ignore it clear_pending_exception_if_not_oom(CHECK); @@ -1908,7 +1908,7 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { } if (_compile_the_world_class_counter >= CompileTheWorldStartAt) { - if (k.is_null() || exception_occurred) { + if (k == NULL || exception_occurred) { // If something went wrong (e.g. ExceptionInInitializerError) we skip this class tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_class_counter, buffer); } else { @@ -1916,8 +1916,9 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { // Preload all classes to get around uncommon traps // Iterate over all methods in class int comp_level = CompilationPolicy::policy()->initial_compile_level(); - for (int n = 0; n < k->methods()->length(); n++) { - methodHandle m (THREAD, k->methods()->at(n)); + InstanceKlass* ik = InstanceKlass::cast(k); + for (int n = 0; n < ik->methods()->length(); n++) { + methodHandle m (THREAD, ik->methods()->at(n)); if (can_be_compiled(m, comp_level)) { if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) { // Give sweeper a chance to keep up with CTW diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 473e2eeb398..13fcfd4dd4c 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -371,7 +371,7 @@ class ClassLoader: AllStatic { const char* const file_name, TRAPS); // Load individual .class file - static instanceKlassHandle load_class(Symbol* class_name, bool search_append_only, TRAPS); + static InstanceKlass* load_class(Symbol* class_name, bool search_append_only, TRAPS); // If the specified package has been loaded by the system, then returns // the name of the directory or ZIP file that the package was loaded from. diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index bec172abc3a..51df446471c 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -760,7 +760,7 @@ void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRA // Include the result of loader.toString() in the output. This allows // the user of the log to identify the class loader instance. JavaValue result(T_OBJECT); - KlassHandle spec_klass(THREAD, SystemDictionary::ClassLoader_klass()); + Klass* spec_klass = SystemDictionary::ClassLoader_klass(); JavaCalls::call_virtual(&result, loader, spec_klass, diff --git a/hotspot/src/share/vm/classfile/classLoaderExt.hpp b/hotspot/src/share/vm/classfile/classLoaderExt.hpp index 1f0b1b6128d..63ad9ac097e 100644 --- a/hotspot/src/share/vm/classfile/classLoaderExt.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -49,10 +49,10 @@ public: return false; } - instanceKlassHandle record_result(Symbol* class_name, - ClassPathEntry* e, - const s2 classpath_index, - instanceKlassHandle result, TRAPS) { + InstanceKlass* record_result(Symbol* class_name, + ClassPathEntry* e, + const s2 classpath_index, + InstanceKlass* result, TRAPS) { if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) { #if INCLUDE_CDS if (DumpSharedSpaces) { @@ -64,7 +64,7 @@ public: #endif return result; } else { - return instanceKlassHandle(); // NULL + return NULL; } } }; diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 338e9229068..ebf878addce 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -46,7 +46,7 @@ size_t Dictionary::entry_size() { } Dictionary::Dictionary(int table_size) - : TwoOopHashtable(table_size, (int)entry_size()) { + : TwoOopHashtable(table_size, (int)entry_size()) { _current_class_index = 0; _current_class_entry = NULL; _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize); @@ -55,7 +55,7 @@ Dictionary::Dictionary(int table_size) Dictionary::Dictionary(int table_size, HashtableBucket* t, int number_of_entries) - : TwoOopHashtable(table_size, (int)entry_size(), t, number_of_entries) { + : TwoOopHashtable(table_size, (int)entry_size(), t, number_of_entries) { _current_class_index = 0; _current_class_entry = NULL; _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize); @@ -65,9 +65,9 @@ ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) { return _pd_cache_table->get(protection_domain); } -DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass, +DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass, ClassLoaderData* loader_data) { - DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass); + DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass); entry->set_loader_data(loader_data); entry->set_pd_set(NULL); assert(klass->is_instance_klass(), "Must be"); @@ -85,7 +85,7 @@ void Dictionary::free_entry(DictionaryEntry* entry) { entry->set_pd_set(to_delete->next()); delete to_delete; } - Hashtable::free_entry(entry); + Hashtable::free_entry(entry); } @@ -351,10 +351,10 @@ void Dictionary::unlink(BoolObjectClosure* is_alive) { _pd_cache_table->unlink(is_alive); } -Klass* Dictionary::try_get_next_class() { +InstanceKlass* Dictionary::try_get_next_class() { while (true) { if (_current_class_entry != NULL) { - Klass* k = _current_class_entry->klass(); + InstanceKlass* k = _current_class_entry->klass(); _current_class_entry = _current_class_entry->next(); return k; } @@ -371,15 +371,15 @@ Klass* Dictionary::try_get_next_class() { // by the compilers. void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data, - KlassHandle obj) { + InstanceKlass* obj) { assert_locked_or_safepoint(SystemDictionary_lock); - assert(obj() != NULL, "adding NULL obj"); - assert(obj()->name() == class_name, "sanity check on name"); + assert(obj != NULL, "adding NULL obj"); + assert(obj->name() == class_name, "sanity check on name"); assert(loader_data != NULL, "Must be non-NULL"); unsigned int hash = compute_hash(class_name, loader_data); int index = hash_to_index(hash); - DictionaryEntry* entry = new_entry(hash, obj(), loader_data); + DictionaryEntry* entry = new_entry(hash, obj, loader_data); add_entry(index, entry); } @@ -410,8 +410,8 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, } -Klass* Dictionary::find(int index, unsigned int hash, Symbol* name, - ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { +InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name, + ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { DictionaryEntry* entry = get_entry(index, hash, name, loader_data); if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { return entry->klass(); @@ -421,30 +421,30 @@ Klass* Dictionary::find(int index, unsigned int hash, Symbol* name, } -Klass* Dictionary::find_class(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data) { +InstanceKlass* Dictionary::find_class(int index, unsigned int hash, + Symbol* name, ClassLoaderData* loader_data) { assert_locked_or_safepoint(SystemDictionary_lock); assert (index == index_for(name, loader_data), "incorrect index?"); DictionaryEntry* entry = get_entry(index, hash, name, loader_data); - return (entry != NULL) ? entry->klass() : (Klass*)NULL; + return (entry != NULL) ? entry->klass() : NULL; } // Variant of find_class for shared classes. No locking required, as // that table is static. -Klass* Dictionary::find_shared_class(int index, unsigned int hash, - Symbol* name) { +InstanceKlass* Dictionary::find_shared_class(int index, unsigned int hash, + Symbol* name) { assert (index == index_for(name, NULL), "incorrect index?"); DictionaryEntry* entry = get_entry(index, hash, name, NULL); - return (entry != NULL) ? entry->klass() : (Klass*)NULL; + return (entry != NULL) ? entry->klass() : NULL; } void Dictionary::add_protection_domain(int index, unsigned int hash, - instanceKlassHandle klass, + InstanceKlass* klass, ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { Symbol* klass_name = klass->name(); diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index f1c11d68cdb..7a9e48e8c10 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -41,7 +41,7 @@ class BoolObjectClosure; // The data structure for the system dictionary (and the shared system // dictionary). -class Dictionary : public TwoOopHashtable { +class Dictionary : public TwoOopHashtable { friend class VMStructs; private: // current iteration index. @@ -56,16 +56,16 @@ private: protected: DictionaryEntry* bucket(int i) const { - return (DictionaryEntry*)Hashtable::bucket(i); + return (DictionaryEntry*)Hashtable::bucket(i); } // The following method is not MT-safe and must be done under lock. DictionaryEntry** bucket_addr(int i) { - return (DictionaryEntry**)Hashtable::bucket_addr(i); + return (DictionaryEntry**)Hashtable::bucket_addr(i); } void add_entry(int index, DictionaryEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)new_entry); } static size_t entry_size(); @@ -73,21 +73,21 @@ public: Dictionary(int table_size); Dictionary(int table_size, HashtableBucket* t, int number_of_entries); - DictionaryEntry* new_entry(unsigned int hash, Klass* klass, ClassLoaderData* loader_data); + DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass, ClassLoaderData* loader_data); DictionaryEntry* new_entry(); void free_entry(DictionaryEntry* entry); - void add_klass(Symbol* class_name, ClassLoaderData* loader_data,KlassHandle obj); + void add_klass(Symbol* class_name, ClassLoaderData* loader_data, InstanceKlass* obj); - Klass* find_class(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data); + InstanceKlass* find_class(int index, unsigned int hash, + Symbol* name, ClassLoaderData* loader_data); - Klass* find_shared_class(int index, unsigned int hash, Symbol* name); + InstanceKlass* find_shared_class(int index, unsigned int hash, Symbol* name); // Compiler support - Klass* try_get_next_class(); + InstanceKlass* try_get_next_class(); // GC support void oops_do(OopClosure* f); @@ -116,13 +116,13 @@ public: void do_unloading(); // Protection domains - Klass* find(int index, unsigned int hash, Symbol* name, - ClassLoaderData* loader_data, Handle protection_domain, TRAPS); + InstanceKlass* find(int index, unsigned int hash, Symbol* name, + ClassLoaderData* loader_data, Handle protection_domain, TRAPS); bool is_valid_protection_domain(int index, unsigned int hash, Symbol* name, ClassLoaderData* loader_data, Handle protection_domain); void add_protection_domain(int index, unsigned int hash, - instanceKlassHandle klass, ClassLoaderData* loader_data, + InstanceKlass* klass, ClassLoaderData* loader_data, Handle protection_domain, TRAPS); // Sharing support @@ -243,9 +243,9 @@ class ProtectionDomainEntry :public CHeapObj { }; // An entry in the system dictionary, this describes a class as -// { Klass*, loader, protection_domain }. +// { InstanceKlass*, loader, protection_domain }. -class DictionaryEntry : public HashtableEntry { +class DictionaryEntry : public HashtableEntry { friend class VMStructs; private: // Contains the set of approved protection domains that can access @@ -277,15 +277,15 @@ class DictionaryEntry : public HashtableEntry { // Adds a protection domain to the approved set. void add_protection_domain(Dictionary* dict, Handle protection_domain); - Klass* klass() const { return (Klass*)literal(); } - Klass** klass_addr() { return (Klass**)literal_addr(); } + InstanceKlass* klass() const { return (InstanceKlass*)literal(); } + InstanceKlass** klass_addr() { return (InstanceKlass**)literal_addr(); } DictionaryEntry* next() const { - return (DictionaryEntry*)HashtableEntry::next(); + return (DictionaryEntry*)HashtableEntry::next(); } DictionaryEntry** next_addr() { - return (DictionaryEntry**)HashtableEntry::next_addr(); + return (DictionaryEntry**)HashtableEntry::next_addr(); } ClassLoaderData* loader_data() const { return _loader_data; } @@ -323,7 +323,7 @@ class DictionaryEntry : public HashtableEntry { } bool equals(const Symbol* class_name, ClassLoaderData* loader_data) const { - Klass* klass = (Klass*)literal(); + InstanceKlass* klass = (InstanceKlass*)literal(); return (klass->name() == class_name && _loader_data == loader_data); } diff --git a/hotspot/src/share/vm/classfile/javaAssertions.cpp b/hotspot/src/share/vm/classfile/javaAssertions.cpp index 5c3c8c9c0e3..745e5d1ba2c 100644 --- a/hotspot/src/share/vm/classfile/javaAssertions.cpp +++ b/hotspot/src/share/vm/classfile/javaAssertions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -96,7 +96,7 @@ void JavaAssertions::addOption(const char* name, bool enable) { oop JavaAssertions::createAssertionStatusDirectives(TRAPS) { Symbol* asd_sym = vmSymbols::java_lang_AssertionStatusDirectives(); Klass* k = SystemDictionary::resolve_or_fail(asd_sym, true, CHECK_NULL); - instanceKlassHandle asd_klass (THREAD, k); + InstanceKlass* asd_klass = InstanceKlass::cast(k); asd_klass->initialize(CHECK_NULL); Handle h = asd_klass->allocate_instance_handle(CHECK_NULL); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 0104318ff11..6ab0a222887 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -735,7 +735,7 @@ static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) { } -void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { +void java_lang_Class::fixup_mirror(Klass* k, TRAPS) { assert(InstanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already"); // If the offset was read from the shared archive, it was fixed up already @@ -744,7 +744,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { // During bootstrap, java.lang.Class wasn't loaded so static field // offsets were computed without the size added it. Go back and // update all the static field offsets to included the size. - for (JavaFieldStream fs(InstanceKlass::cast(k())); !fs.done(); fs.next()) { + for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { int real_offset = fs.offset() + InstanceMirrorKlass::offset_of_static_fields(); fs.set_offset(real_offset); @@ -755,7 +755,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { create_mirror(k, Handle(), Handle(), Handle(), CHECK); } -void java_lang_Class::initialize_mirror_fields(KlassHandle k, +void java_lang_Class::initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS) { @@ -769,11 +769,11 @@ void java_lang_Class::initialize_mirror_fields(KlassHandle k, set_protection_domain(mirror(), protection_domain()); // Initialize static fields - InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK); + InstanceKlass::cast(k)->do_local_static_fields(&initialize_static_field, mirror, CHECK); } // Set the java.lang.reflect.Module module field in the java_lang_Class mirror -void java_lang_Class::set_mirror_module_field(KlassHandle k, Handle mirror, Handle module, TRAPS) { +void java_lang_Class::set_mirror_module_field(Klass* k, Handle mirror, Handle module, TRAPS) { if (module.is_null()) { // During startup, the module may be NULL only if java.base has not been defined yet. // Put the class on the fixup_module_list to patch later when the java.lang.reflect.Module @@ -791,7 +791,7 @@ void java_lang_Class::set_mirror_module_field(KlassHandle k, Handle mirror, Hand set_fixup_module_field_list(list); } k->class_loader_data()->inc_keep_alive(); - fixup_module_field_list()->push(k()); + fixup_module_field_list()->push(k); } else { javabase_was_defined = true; } @@ -814,7 +814,7 @@ void java_lang_Class::set_mirror_module_field(KlassHandle k, Handle mirror, Hand } } -void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, +void java_lang_Class::create_mirror(Klass* k, Handle class_loader, Handle module, Handle protection_domain, TRAPS) { assert(k->java_mirror() == NULL, "should only assign mirror once"); // Use this moment of initialization to cache modifier_flags also, @@ -831,8 +831,8 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, Handle mirror(THREAD, mirror_oop); // Setup indirection from mirror->klass - if (!k.is_null()) { - java_lang_Class::set_klass(mirror(), k()); + if (k != NULL) { + java_lang_Class::set_klass(mirror(), k); } InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); @@ -844,11 +844,11 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, if (k->is_array_klass()) { oop comp_mirror; if (k->is_typeArray_klass()) { - BasicType type = TypeArrayKlass::cast(k())->element_type(); + BasicType type = TypeArrayKlass::cast(k)->element_type(); comp_mirror = Universe::java_mirror(type); } else { assert(k->is_objArray_klass(), "Must be"); - Klass* element_klass = ObjArrayKlass::cast(k())->element_klass(); + Klass* element_klass = ObjArrayKlass::cast(k)->element_klass(); assert(element_klass != NULL, "Must have an element klass"); comp_mirror = element_klass->java_mirror(); } @@ -857,7 +857,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, // Two-way link between the array klass and its component mirror: // (array_klass) k -> mirror -> component_mirror -> array_klass -> k set_component_mirror(mirror(), comp_mirror); - set_array_klass(comp_mirror, k()); + set_array_klass(comp_mirror, k); } else { assert(k->is_instance_klass(), "Must be"); @@ -881,7 +881,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, // Setup indirection from klass->mirror last // after any exceptions can happen during allocations. - if (!k.is_null()) { + if (k != NULL) { k->set_java_mirror(mirror()); } } else { @@ -890,11 +890,11 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, new (ResourceObj::C_HEAP, mtClass) GrowableArray(40, true); set_fixup_mirror_list(list); } - fixup_mirror_list()->push(k()); + fixup_mirror_list()->push(k); } } -void java_lang_Class::fixup_module_field(KlassHandle k, Handle module) { +void java_lang_Class::fixup_module_field(Klass* k, Handle module) { assert(_module_offset != 0, "must have been computed already"); java_lang_Class::set_module(k->java_mirror(), module()); } @@ -1876,7 +1876,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) JavaValue cause(T_OBJECT); JavaCalls::call_virtual(&cause, throwable, - KlassHandle(THREAD, throwable->klass()), + throwable->klass(), vmSymbols::getCause_name(), vmSymbols::void_throwable_signature(), THREAD); @@ -1904,7 +1904,7 @@ void java_lang_Throwable::java_printStackTrace(Handle throwable, TRAPS) { JavaValue result(T_VOID); JavaCalls::call_virtual(&result, throwable, - KlassHandle(THREAD, SystemDictionary::Throwable_klass()), + SystemDictionary::Throwable_klass(), vmSymbols::printStackTrace_name(), vmSymbols::void_method_signature(), THREAD); @@ -2153,14 +2153,13 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable, oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance - Klass* k = SystemDictionary::StackTraceElement_klass(); + InstanceKlass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); - instanceKlassHandle ik (THREAD, k); - if (ik->should_be_initialized()) { - ik->initialize(CHECK_0); + if (k->should_be_initialized()) { + k->initialize(CHECK_0); } - Handle element = ik->allocate_instance_handle(CHECK_0); + Handle element = k->allocate_instance_handle(CHECK_0); int version = method->constants()->version(); fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0); @@ -2489,10 +2488,10 @@ Handle java_lang_reflect_Constructor::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); Symbol* name = vmSymbols::java_lang_reflect_Constructor(); Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); // Ensure it is initialized - klass->initialize(CHECK_NH); - return klass->allocate_instance_handle(THREAD); + ik->initialize(CHECK_NH); + return ik->allocate_instance_handle(THREAD); } oop java_lang_reflect_Constructor::clazz(oop reflect) { @@ -2629,10 +2628,10 @@ Handle java_lang_reflect_Field::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); Symbol* name = vmSymbols::java_lang_reflect_Field(); Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); // Ensure it is initialized - klass->initialize(CHECK_NH); - return klass->allocate_instance_handle(THREAD); + ik->initialize(CHECK_NH); + return ik->allocate_instance_handle(THREAD); } oop java_lang_reflect_Field::clazz(oop reflect) { @@ -2756,10 +2755,10 @@ Handle java_lang_reflect_Parameter::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); Symbol* name = vmSymbols::java_lang_reflect_Parameter(); Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); // Ensure it is initialized - klass->initialize(CHECK_NH); - return klass->allocate_instance_handle(THREAD); + ik->initialize(CHECK_NH); + return ik->allocate_instance_handle(THREAD); } oop java_lang_reflect_Parameter::name(oop param) { @@ -2812,11 +2811,10 @@ Handle java_lang_reflect_Module::create(Handle loader, Handle module_name, TRAPS Symbol* name = vmSymbols::java_lang_reflect_Module(); Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); - instanceKlassHandle klass (THREAD, k); - - Handle jlrmh = klass->allocate_instance_handle(CHECK_NH); + InstanceKlass* ik = InstanceKlass::cast(k); + Handle jlrmh = ik->allocate_instance_handle(CHECK_NH); JavaValue result(T_VOID); - JavaCalls::call_special(&result, jlrmh, KlassHandle(THREAD, klass()), + JavaCalls::call_special(&result, jlrmh, ik, vmSymbols::object_initializer_name(), vmSymbols::java_lang_reflect_module_init_signature(), loader, module_name, CHECK_NH); @@ -2879,11 +2877,10 @@ void java_lang_reflect_Module::set_module_entry(oop module, ModuleEntry* module_ Handle reflect_ConstantPool::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - Klass* k = SystemDictionary::reflect_ConstantPool_klass(); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass(); // Ensure it is initialized - klass->initialize(CHECK_NH); - return klass->allocate_instance_handle(THREAD); + k->initialize(CHECK_NH); + return k->allocate_instance_handle(THREAD); } @@ -2921,9 +2918,9 @@ void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) { Klass* k = SystemDictionary::box_klass(type); if (k == NULL) return NULL; - instanceKlassHandle h (THREAD, k); - if (!h->is_initialized()) h->initialize(CHECK_0); - return h->allocate_instance(THREAD); + InstanceKlass* ik = InstanceKlass::cast(k); + if (!ik->is_initialized()) ik->initialize(CHECK_0); + return ik->allocate_instance(THREAD); } @@ -3894,10 +3891,10 @@ bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, con fieldDescriptor fd; TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); - instanceKlassHandle h_klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); - if (!h_klass->find_local_field(f_name, f_sig, &fd)) { + if (!ik->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Nonstatic field %s.%s not found", klass_name, field_name); return false; } @@ -3920,10 +3917,10 @@ bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offs fieldDescriptor fd; TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); - instanceKlassHandle h_klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); - if (!h_klass->find_local_field(f_name, f_sig, &fd)) { + if (!ik->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Static field %s.%s not found", klass_name, field_name); return false; } @@ -3945,10 +3942,10 @@ bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, fieldDescriptor fd; TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); - instanceKlassHandle h_klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); - if (!h_klass->find_local_field(f_name, f_sig, &fd)) { + if (!ik->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Static field %s.%s not found", klass_name, field_name); return false; } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 7faca4f1556..8e125bb73c0 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -209,29 +209,23 @@ class java_lang_Class : AllStatic { static void set_protection_domain(oop java_class, oop protection_domain); static void set_class_loader(oop java_class, oop class_loader); static void set_component_mirror(oop java_class, oop comp_mirror); - static void initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS); - static void set_mirror_module_field(KlassHandle K, Handle mirror, Handle module, TRAPS); + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); + static void set_mirror_module_field(Klass* K, Handle mirror, Handle module, TRAPS); public: static void compute_offsets(); // Instance creation - static void create_mirror(KlassHandle k, Handle class_loader, Handle module, + static void create_mirror(Klass* k, Handle class_loader, Handle module, Handle protection_domain, TRAPS); - static void fixup_mirror(KlassHandle k, TRAPS); + static void fixup_mirror(Klass* k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); - static void fixup_module_field(KlassHandle k, Handle module); + static void fixup_module_field(Klass* k, Handle module); // Conversion static Klass* as_Klass(oop java_class); static void set_klass(oop java_class, Klass* klass); static BasicType as_BasicType(oop java_class, Klass** reference_klass = NULL); - static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) { - Klass* refk_oop = NULL; - BasicType result = as_BasicType(java_class, &refk_oop); - (*reference_klass) = KlassHandle(refk_oop); - return result; - } static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS); static void print_signature(oop java_class, outputStream *st); static const char* as_external_name(oop java_class); diff --git a/hotspot/src/share/vm/classfile/klassFactory.cpp b/hotspot/src/share/vm/classfile/klassFactory.cpp index 41ff031d488..74836b3246e 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.cpp +++ b/hotspot/src/share/vm/classfile/klassFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2017, 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 @@ -37,14 +37,14 @@ #include "trace/traceMacros.hpp" // called during initial loading of a shared class -instanceKlassHandle KlassFactory::check_shared_class_file_load_hook( - instanceKlassHandle ik, +InstanceKlass* KlassFactory::check_shared_class_file_load_hook( + InstanceKlass* ik, Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { #if INCLUDE_CDS && INCLUDE_JVMTI - assert(ik.not_null(), "sanity"); - assert(ik()->is_shared(), "expecting a shared class"); + assert(ik != NULL, "sanity"); + assert(ik->is_shared(), "expecting a shared class"); if (JvmtiExport::should_post_class_file_load_hook()) { assert(THREAD->is_Java_thread(), "must be JavaThread"); @@ -84,8 +84,8 @@ instanceKlassHandle KlassFactory::check_shared_class_file_load_hook( NULL, ClassFileParser::BROADCAST, // publicity level CHECK_NULL); - instanceKlassHandle new_ik = parser.create_instance_klass(true /* changed_by_loadhook */, - CHECK_NULL); + InstanceKlass* new_ik = parser.create_instance_klass(true /* changed_by_loadhook */, + CHECK_NULL); if (cached_class_file != NULL) { new_ik->set_cached_class_file(cached_class_file); } @@ -128,14 +128,11 @@ static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream, JvmtiThreadState* state = jt->jvmti_thread_state(); if (state != NULL) { - KlassHandle* h_class_being_redefined = - state->get_class_being_redefined(); + Klass* k = state->get_class_being_redefined(); - if (h_class_being_redefined != NULL) { - instanceKlassHandle ikh_class_being_redefined = - instanceKlassHandle(THREAD, (*h_class_being_redefined)()); - - *cached_class_file = ikh_class_being_redefined->get_cached_class_file(); + if (k != NULL) { + InstanceKlass* class_being_redefined = InstanceKlass::cast(k); + *cached_class_file = class_being_redefined->get_cached_class_file(); } } @@ -163,13 +160,13 @@ static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream, } -instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream, - Symbol* name, - ClassLoaderData* loader_data, - Handle protection_domain, - const InstanceKlass* host_klass, - GrowableArray* cp_patches, - TRAPS) { +InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, + Symbol* name, + ClassLoaderData* loader_data, + Handle protection_domain, + const InstanceKlass* host_klass, + GrowableArray* cp_patches, + TRAPS) { assert(stream != NULL, "invariant"); assert(loader_data != NULL, "invariant"); assert(THREAD->is_Java_thread(), "must be a JavaThread"); @@ -200,10 +197,10 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream, ClassFileParser::BROADCAST, // publicity level CHECK_NULL); - instanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL); + InstanceKlass* result = parser.create_instance_klass(old_stream != stream, CHECK_NULL); assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant"); - if (result.is_null()) { + if (result == NULL) { return NULL; } diff --git a/hotspot/src/share/vm/classfile/klassFactory.hpp b/hotspot/src/share/vm/classfile/klassFactory.hpp index 6624e31658e..cb3ed851dd9 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.hpp +++ b/hotspot/src/share/vm/classfile/klassFactory.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,16 +68,16 @@ class KlassFactory : AllStatic { friend class SystemDictionary; private: - static instanceKlassHandle create_from_stream(ClassFileStream* stream, - Symbol* name, - ClassLoaderData* loader_data, - Handle protection_domain, - const InstanceKlass* host_klass, - GrowableArray* cp_patches, - TRAPS); + static InstanceKlass* create_from_stream(ClassFileStream* stream, + Symbol* name, + ClassLoaderData* loader_data, + Handle protection_domain, + const InstanceKlass* host_klass, + GrowableArray* cp_patches, + TRAPS); public: - static instanceKlassHandle check_shared_class_file_load_hook( - instanceKlassHandle ik, + static InstanceKlass* check_shared_class_file_load_hook( + InstanceKlass* ik, Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.cpp b/hotspot/src/share/vm/classfile/loaderConstraints.cpp index 5dfe4e33ae4..41a9c525756 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -36,15 +36,15 @@ void LoaderConstraintEntry::set_loader(int i, oop p) { } LoaderConstraintTable::LoaderConstraintTable(int nof_buckets) - : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {}; + : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {}; LoaderConstraintEntry* LoaderConstraintTable::new_entry( unsigned int hash, Symbol* name, - Klass* klass, int num_loaders, + InstanceKlass* klass, int num_loaders, int max_loaders) { LoaderConstraintEntry* entry; - entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass); + entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass); entry->set_name(name); entry->set_num_loaders(num_loaders); entry->set_max_loaders(max_loaders); @@ -54,7 +54,7 @@ LoaderConstraintEntry* LoaderConstraintTable::new_entry( void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) { // decrement name refcount before freeing entry->name()->decrement_refcount(); - Hashtable::free_entry(entry); + Hashtable::free_entry(entry); } // Enhanced Class Redefinition support @@ -106,7 +106,7 @@ void LoaderConstraintTable::purge_loader_constraints() { LoaderConstraintEntry** p = bucket_addr(index); while(*p) { LoaderConstraintEntry* probe = *p; - Klass* klass = probe->klass(); + InstanceKlass* klass = probe->klass(); // Remove klass that is no longer alive if (klass != NULL && klass->class_loader_data()->is_unloading()) { @@ -186,14 +186,14 @@ void LoaderConstraintTable::purge_loader_constraints() { } bool LoaderConstraintTable::add_entry(Symbol* class_name, - Klass* klass1, Handle class_loader1, - Klass* klass2, Handle class_loader2) { + InstanceKlass* klass1, Handle class_loader1, + InstanceKlass* klass2, Handle class_loader2) { int failure_code = 0; // encode different reasons for failing if (klass1 != NULL && klass2 != NULL && klass1 != klass2) { failure_code = 1; } else { - Klass* klass = klass1 != NULL ? klass1 : klass2; + InstanceKlass* klass = klass1 != NULL ? klass1 : klass2; LoaderConstraintEntry** pp1 = find_loader_constraint(class_name, class_loader1); @@ -295,11 +295,11 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, // return true if the constraint was updated, false if the constraint is // violated -bool LoaderConstraintTable::check_or_update(instanceKlassHandle k, - Handle loader, - Symbol* name) { +bool LoaderConstraintTable::check_or_update(InstanceKlass* k, + Handle loader, + Symbol* name) { LoaderConstraintEntry* p = *(find_loader_constraint(name, loader)); - if (p && p->klass() != NULL && p->klass() != k()) { + if (p && p->klass() != NULL && p->klass() != k) { if (log_is_enabled(Info, class, loader, constraints)) { ResourceMark rm; outputStream* out = Log(class, loader, constraints)::info_stream(); @@ -311,7 +311,7 @@ bool LoaderConstraintTable::check_or_update(instanceKlassHandle k, return false; } else { if (p && p->klass() == NULL) { - p->set_klass(k()); + p->set_klass(k); if (log_is_enabled(Info, class, loader, constraints)) { ResourceMark rm; outputStream* out = Log(class, loader, constraints)::info_stream(); @@ -325,11 +325,12 @@ bool LoaderConstraintTable::check_or_update(instanceKlassHandle k, } } -Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name, +InstanceKlass* LoaderConstraintTable::find_constrained_klass(Symbol* name, Handle loader) { LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); if (p != NULL && p->klass() != NULL) { - if (p->klass()->is_instance_klass() && !InstanceKlass::cast(p->klass())->is_loaded()) { + assert(p->klass()->is_instance_klass(), "sanity"); + if (p->klass()->is_loaded()) { // Only return fully loaded classes. Classes found through the // constraints might still be in the process of loading. return NULL; @@ -357,7 +358,7 @@ void LoaderConstraintTable::ensure_loader_constraint_capacity( void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p, Handle loader, - Klass* klass) { + InstanceKlass* klass) { ensure_loader_constraint_capacity(p, 1); int num = p->num_loaders(); p->set_loader(num, loader()); @@ -383,7 +384,7 @@ void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p, void LoaderConstraintTable::merge_loader_constraints( LoaderConstraintEntry** pp1, LoaderConstraintEntry** pp2, - Klass* klass) { + InstanceKlass* klass) { // make sure *pp1 has higher capacity if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) { LoaderConstraintEntry** tmp = pp2; @@ -447,13 +448,13 @@ void LoaderConstraintTable::verify(Dictionary* dictionary, probe != NULL; probe = probe->next()) { if (probe->klass() != NULL) { - InstanceKlass* ik = InstanceKlass::cast(probe->klass()); + InstanceKlass* ik = probe->klass(); guarantee(ik->name() == probe->name(), "name should match"); Symbol* name = ik->name(); ClassLoaderData* loader_data = ik->class_loader_data(); unsigned int d_hash = dictionary->compute_hash(name, loader_data); int d_index = dictionary->hash_to_index(d_hash); - Klass* k = dictionary->find_class(d_index, d_hash, name, loader_data); + InstanceKlass* k = dictionary->find_class(d_index, d_hash, name, loader_data); if (k != NULL) { // We found the class in the system dictionary, so we should // make sure that the Klass* matches what we already have. diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.hpp b/hotspot/src/share/vm/classfile/loaderConstraints.hpp index 2b6d9b57af1..75b6a41b2e0 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ class LoaderConstraintEntry; class Symbol; -class LoaderConstraintTable : public Hashtable { +class LoaderConstraintTable : public Hashtable { friend class VMStructs; private: @@ -49,43 +49,41 @@ public: LoaderConstraintTable(int nof_buckets); LoaderConstraintEntry* new_entry(unsigned int hash, Symbol* name, - Klass* klass, int num_loaders, + InstanceKlass* klass, int num_loaders, int max_loaders); void free_entry(LoaderConstraintEntry *entry); LoaderConstraintEntry* bucket(int i) { - return (LoaderConstraintEntry*)Hashtable::bucket(i); + return (LoaderConstraintEntry*)Hashtable::bucket(i); } LoaderConstraintEntry** bucket_addr(int i) { - return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); + return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); } // Enhanced Class Redefinition support void classes_do(KlassClosure* f); // Check class loader constraints - bool add_entry(Symbol* name, Klass* klass1, Handle loader1, - Klass* klass2, Handle loader2); + bool add_entry(Symbol* name, InstanceKlass* klass1, Handle loader1, + InstanceKlass* klass2, Handle loader2); // Note: The main entry point for this module is via SystemDictionary. // SystemDictionary::check_signature_loaders(Symbol* signature, // Handle loader1, Handle loader2, // bool is_method, TRAPS) - Klass* find_constrained_klass(Symbol* name, Handle loader); + InstanceKlass* find_constrained_klass(Symbol* name, Handle loader); // Class loader constraints void ensure_loader_constraint_capacity(LoaderConstraintEntry *p, int nfree); void extend_loader_constraint(LoaderConstraintEntry* p, Handle loader, - Klass* klass); + InstanceKlass* klass); void merge_loader_constraints(LoaderConstraintEntry** pp1, - LoaderConstraintEntry** pp2, Klass* klass); - - bool check_or_update(instanceKlassHandle k, Handle loader, - Symbol* name); + LoaderConstraintEntry** pp2, InstanceKlass* klass); + bool check_or_update(InstanceKlass* k, Handle loader, Symbol* name); void purge_loader_constraints(); @@ -95,7 +93,7 @@ public: #endif }; -class LoaderConstraintEntry : public HashtableEntry { +class LoaderConstraintEntry : public HashtableEntry { friend class VMStructs; private: Symbol* _name; // class name @@ -108,19 +106,19 @@ private: public: - Klass* klass() { return literal(); } - Klass** klass_addr() { return literal_addr(); } - void set_klass(Klass* k) { set_literal(k); } + InstanceKlass* klass() { return literal(); } + InstanceKlass** klass_addr() { return literal_addr(); } + void set_klass(InstanceKlass* k) { set_literal(k); } LoaderConstraintEntry* next() { - return (LoaderConstraintEntry*)HashtableEntry::next(); + return (LoaderConstraintEntry*)HashtableEntry::next(); } LoaderConstraintEntry** next_addr() { - return (LoaderConstraintEntry**)HashtableEntry::next_addr(); + return (LoaderConstraintEntry**)HashtableEntry::next_addr(); } void set_next(LoaderConstraintEntry* next) { - HashtableEntry::set_next(next); + HashtableEntry::set_next(next); } Symbol* name() { return _name; } diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index 8ebb8bdef16..aa6b14c732e 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -428,7 +428,7 @@ void ModuleEntryTable::patch_javabase_entries(Handle module_handle) { for (int i = 0; i < list_length; i++) { Klass* k = list->at(i); assert(k->is_klass(), "List should only hold classes"); - java_lang_Class::fixup_module_field(KlassHandle(k), module_handle); + java_lang_Class::fixup_module_field(k, module_handle); k->class_loader_data()->dec_keep_alive(); } diff --git a/hotspot/src/share/vm/classfile/placeholders.hpp b/hotspot/src/share/vm/classfile/placeholders.hpp index f5fc9b40845..1ce9871fafb 100644 --- a/hotspot/src/share/vm/classfile/placeholders.hpp +++ b/hotspot/src/share/vm/classfile/placeholders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -163,7 +163,7 @@ class PlaceholderEntry : public HashtableEntry { bool _havesupername; // distinguish between null supername, and unknown Symbol* _supername; Thread* _definer; // owner of define token - Klass* _instanceKlass; // InstanceKlass from successful define + InstanceKlass* _instanceKlass; // InstanceKlass from successful define SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class SeenThread* _loadInstanceThreadQ; // loadInstance thread // can be multiple threads if classloader object lock broken by application @@ -193,8 +193,8 @@ class PlaceholderEntry : public HashtableEntry { Thread* definer() const {return _definer; } void set_definer(Thread* definer) { _definer = definer; } - Klass* instance_klass() const {return _instanceKlass; } - void set_instance_klass(Klass* ik) { _instanceKlass = ik; } + InstanceKlass* instance_klass() const {return _instanceKlass; } + void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; } SeenThread* superThreadQ() const { return _superThreadQ; } void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 30b1552d936..34115ebcd8f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -120,10 +120,10 @@ oop SystemDictionary::java_system_loader() { } void SystemDictionary::compute_java_system_loader(TRAPS) { - KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass)); + Klass* system_klass = WK_KLASS(ClassLoader_klass); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)), + WK_KLASS(ClassLoader_klass), vmSymbols::getSystemClassLoader_name(), vmSymbols::void_classloader_signature(), CHECK); @@ -184,16 +184,15 @@ bool SystemDictionary::is_platform_class_loader(oop class_loader) { Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS) { Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD); if (HAS_PENDING_EXCEPTION || klass == NULL) { - KlassHandle k_h(THREAD, klass); // can return a null klass - klass = handle_resolution_exception(class_name, throw_error, k_h, THREAD); + klass = handle_resolution_exception(class_name, throw_error, klass, THREAD); } return klass; } Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, bool throw_error, - KlassHandle klass_h, TRAPS) { + Klass* klass, TRAPS) { if (HAS_PENDING_EXCEPTION) { // If we have a pending exception we forward it to the caller, unless throw_error is true, // in which case we have to check whether the pending exception is a ClassNotFoundException, @@ -201,7 +200,7 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, // And chain the original ClassNotFoundException if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) { ResourceMark rm(THREAD); - assert(klass_h() == NULL, "Should not have result with exception pending"); + assert(klass == NULL, "Should not have result with exception pending"); Handle e(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); @@ -210,7 +209,7 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, } } // Class not found, throw appropriate error or exception depending on value of throw_error - if (klass_h() == NULL) { + if (klass == NULL) { ResourceMark rm(THREAD); if (throw_error) { THROW_MSG_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); @@ -218,7 +217,7 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); } } - return (Klass*)klass_h(); + return klass; } @@ -256,9 +255,9 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, TRAPS) { // Forwards to resolve_instance_class_or_null Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - TRAPS) { + Handle class_loader, + Handle protection_domain, + TRAPS) { assert(FieldType::is_array(class_name), "must be array"); Klass* k = NULL; FieldArrayInfo fd; @@ -398,11 +397,9 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, assert(class_name != NULL, "null super class for resolving"); // Resolve the super class or interface, check results on return Klass* superk = SystemDictionary::resolve_or_null(class_name, - class_loader, - protection_domain, - THREAD); - - KlassHandle superk_h(THREAD, superk); + class_loader, + protection_domain, + THREAD); // Clean up of placeholders moved so that each classloadAction registrar self-cleans up // It is no longer necessary to keep the placeholder table alive until update_dictionary @@ -415,15 +412,15 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, placeholders()->find_and_remove(p_index, p_hash, child_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); SystemDictionary_lock->notify_all(); } - if (HAS_PENDING_EXCEPTION || superk_h() == NULL) { + if (HAS_PENDING_EXCEPTION || superk == NULL) { // can null superk - superk_h = KlassHandle(THREAD, handle_resolution_exception(class_name, true, superk_h, THREAD)); + superk = handle_resolution_exception(class_name, true, superk, THREAD); } - return superk_h(); + return superk; } -void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, +void SystemDictionary::validate_protection_domain(InstanceKlass* klass, Handle class_loader, Handle protection_domain, TRAPS) { @@ -438,11 +435,11 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, log->print_cr("Checking package access"); log->print("class loader: "); class_loader()->print_value_on(log); log->print(" protection domain: "); protection_domain()->print_value_on(log); - log->print(" loading: "); klass()->print_value_on(log); + log->print(" loading: "); klass->print_value_on(log); log->cr(); } - KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); + InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass(); JavaCalls::call_special(&result, class_loader, system_loader, @@ -540,11 +537,10 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { // Returns non-null Klass* if other thread has completed load // and we are done, // If return null Klass* and no pending exception, the caller must load the class -instanceKlassHandle SystemDictionary::handle_parallel_super_load( +InstanceKlass* SystemDictionary::handle_parallel_super_load( Symbol* name, Symbol* superclassname, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS) { - instanceKlassHandle nh = instanceKlassHandle(); // null Handle ClassLoaderData* loader_data = class_loader_data(class_loader); unsigned int d_hash = dictionary()->compute_hash(name, loader_data); int d_index = dictionary()->hash_to_index(d_hash); @@ -564,20 +560,14 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( class_loader, protection_domain, true, - CHECK_(nh)); + CHECK_NULL); // parallelCapable class loaders do NOT wait for parallel superclass loads to complete // Serial class loaders and bootstrap classloader do wait for superclass loads if (!class_loader.is_null() && is_parallelCapable(class_loader)) { MutexLocker mu(SystemDictionary_lock, THREAD); // Check if classloading completed while we were loading superclass or waiting - Klass* check = find_class(d_index, d_hash, name, loader_data); - if (check != NULL) { - // Klass is already loaded, so just return it - return(instanceKlassHandle(THREAD, check)); - } else { - return nh; - } + return find_class(d_index, d_hash, name, loader_data); } // must loop to both handle other placeholder updates @@ -587,10 +577,10 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( while (super_load_in_progress) { MutexLocker mu(SystemDictionary_lock, THREAD); // Check if classloading completed while we were loading superclass or waiting - Klass* check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { // Klass is already loaded, so just return it - return(instanceKlassHandle(THREAD, check)); + return check; } else { placeholder = placeholders()->get_entry(p_index, p_hash, name, loader_data); if (placeholder && placeholder->super_load_in_progress() ){ @@ -619,17 +609,17 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( } } } - return (nh); + return NULL; } static void post_class_load_event(const Ticks& start_time, - instanceKlassHandle k, + InstanceKlass* k, const ClassLoaderData* init_cld) { #if INCLUDE_TRACE EventClassLoad event(UNTIMED); if (event.should_commit()) { event.set_starttime(start_time); - event.set_loadedClass(k()); + event.set_loadedClass(k); event.set_definingClassLoader(k->class_loader_data()); event.set_initiatingClassLoader(init_cld); event.commit(); @@ -637,12 +627,12 @@ static void post_class_load_event(const Ticks& start_time, #endif // INCLUDE_TRACE } -static void class_define_event(instanceKlassHandle k, +static void class_define_event(InstanceKlass* k, const ClassLoaderData* def_cld) { #if INCLUDE_TRACE EventClassDefine event; if (event.should_commit()) { - event.set_definedClass(k()); + event.set_definedClass(k); event.set_definingClassLoader(def_cld); event.commit(); } @@ -708,17 +698,17 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, bool class_has_been_loaded = false; bool super_load_in_progress = false; bool havesupername = false; - instanceKlassHandle k; + InstanceKlass* k = NULL; PlaceholderEntry* placeholder; Symbol* superclassname = NULL; { MutexLocker mu(SystemDictionary_lock, THREAD); - Klass* check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { // Klass is already loaded, so just return it class_has_been_loaded = true; - k = instanceKlassHandle(THREAD, check); + k = check; } else { placeholder = placeholders()->get_entry(p_index, p_hash, name, loader_data); if (placeholder && placeholder->super_load_in_progress()) { @@ -733,12 +723,15 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // If the class is in the placeholder table, class loading is in progress if (super_load_in_progress && havesupername==true) { - k = SystemDictionary::handle_parallel_super_load(name, superclassname, - class_loader, protection_domain, lockObject, THREAD); + k = handle_parallel_super_load(name, + superclassname, + class_loader, + protection_domain, + lockObject, THREAD); if (HAS_PENDING_EXCEPTION) { return NULL; } - if (!k.is_null()) { + if (k != NULL) { class_has_been_loaded = true; } } @@ -795,10 +788,10 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, double_lock_wait(lockObject, THREAD); } // Check if classloading completed while we were waiting - Klass* check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { // Klass is already loaded, so just return it - k = instanceKlassHandle(THREAD, check); + k = check; class_has_been_loaded = true; } // check if other thread failed to load and cleaned up @@ -820,10 +813,10 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL // one final check if the load has already completed // class loaders holding the ObjectLock shouldn't find the class here - Klass* check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { // Klass is already loaded, so return it after checking/adding protection domain - k = instanceKlassHandle(THREAD, check); + k = check; class_has_been_loaded = true; } } @@ -850,13 +843,13 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // with the new cleaner mechanism, even with AllowParallelDefineClass // Bootstrap goes through here to allow for an extra guarantee check if (UnsyncloadClass || (class_loader.is_null())) { - if (k.is_null() && HAS_PENDING_EXCEPTION + if (k == NULL && HAS_PENDING_EXCEPTION && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { MutexLocker mu(SystemDictionary_lock, THREAD); - Klass* check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { // Klass is already loaded, so just use it - k = instanceKlassHandle(THREAD, check); + k = check; CLEAR_PENDING_EXCEPTION; guarantee((!class_loader.is_null()), "dup definition for bootstrap loader?"); } @@ -865,7 +858,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. - if (!HAS_PENDING_EXCEPTION && !k.is_null() && + if (!HAS_PENDING_EXCEPTION && k != NULL && k->class_loader() != class_loader()) { check_constraints(d_index, d_hash, k, class_loader, false, THREAD); @@ -883,7 +876,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, if (JvmtiExport::should_post_class_load()) { Thread *thread = THREAD; assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) thread, k()); + JvmtiExport::post_class_load((JavaThread *) thread, k); } } } @@ -899,7 +892,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, } } - if (HAS_PENDING_EXCEPTION || k.is_null()) { + if (HAS_PENDING_EXCEPTION || k == NULL) { return NULL; } @@ -910,12 +903,12 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, ClassLoaderData* loader_data = k->class_loader_data(); MutexLocker mu(SystemDictionary_lock, THREAD); Klass* kk = find_class(name, loader_data); - assert(kk == k(), "should be present in dictionary"); + assert(kk == k, "should be present in dictionary"); } #endif // return if the protection domain in NULL - if (protection_domain() == NULL) return k(); + if (protection_domain() == NULL) return k; // Check the protection domain has the right access { @@ -930,14 +923,14 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, if (dictionary()->is_valid_protection_domain(d_index, d_hash, name, loader_data, protection_domain)) { - return k(); + return k; } } // Verify protection domain. If it fails an exception is thrown validate_protection_domain(k, class_loader, protection_domain, CHECK_NULL); - return k(); + return k; } @@ -1019,13 +1012,13 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name, // does not publish the classes via the SystemDictionary. // Handles unsafe_DefineAnonymousClass and redefineclasses // RedefinedClasses do not add to the class hierarchy -Klass* SystemDictionary::parse_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - const InstanceKlass* host_klass, - GrowableArray* cp_patches, - TRAPS) { +InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, + const InstanceKlass* host_klass, + GrowableArray* cp_patches, + TRAPS) { Ticks class_load_start_time = Ticks::now(); @@ -1049,15 +1042,15 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // already be present in the SystemDictionary, otherwise we would not // throw potential ClassFormatErrors. - instanceKlassHandle k = KlassFactory::create_from_stream(st, - class_name, - loader_data, - protection_domain, - host_klass, - cp_patches, - CHECK_NULL); + InstanceKlass* k = KlassFactory::create_from_stream(st, + class_name, + loader_data, + protection_domain, + host_klass, + cp_patches, + CHECK_NULL); - if (host_klass != NULL && k.not_null()) { + if (host_klass != NULL && k != NULL) { // If it's anonymous, initialize it now, since nobody else will. { @@ -1083,7 +1076,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // notify jvmti if (JvmtiExport::should_post_class_load()) { assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, k()); + JvmtiExport::post_class_load((JavaThread *) THREAD, k); } post_class_load_event(class_load_start_time, k, loader_data); @@ -1091,7 +1084,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, assert(host_klass != NULL || NULL == cp_patches, "cp_patches only found with host_klass"); - return k(); + return k; } // Add a klass to the system from a stream (called by jni_DefineClass and @@ -1099,11 +1092,11 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // Note: class_name can be NULL. In that case we do not know the name of // the class until we have parsed the stream. -Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - TRAPS) { +InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, + TRAPS) { HandleMark hm(THREAD); @@ -1127,9 +1120,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, // Note that we do this even though this klass might // already be present in the SystemDictionary, otherwise we would not // throw potential ClassFormatErrors. - // - - instanceKlassHandle k; + InstanceKlass* k = NULL; #if INCLUDE_CDS k = SystemDictionaryShared::lookup_from_stream(class_name, @@ -1139,7 +1130,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, CHECK_NULL); #endif - if (k.is_null()) { + if (k == NULL) { if (st->buffer() == NULL) { return NULL; } @@ -1152,7 +1143,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, CHECK_NULL); } - assert(k.not_null(), "no klass created"); + assert(k != NULL, "no klass created"); Symbol* h_name = k->name(); assert(class_name == NULL || class_name == h_name, "name mismatch"); @@ -1160,11 +1151,11 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, // If a class loader supports parallel classloading handle parallel define requests // find_or_define_instance_class may return a different InstanceKlass if (is_parallelCapable(class_loader)) { - instanceKlassHandle defined_k = find_or_define_instance_class(h_name, class_loader, k, THREAD); - if (!HAS_PENDING_EXCEPTION && defined_k() != k()) { + InstanceKlass* defined_k = find_or_define_instance_class(h_name, class_loader, k, THREAD); + if (!HAS_PENDING_EXCEPTION && defined_k != k) { // If a parallel capable class loader already defined this class, register 'k' for cleanup. - assert(defined_k.not_null(), "Should have a klass if there's no exception"); - loader_data->add_to_deallocate_list(k()); + assert(defined_k != NULL, "Should have a klass if there's no exception"); + loader_data->add_to_deallocate_list(k); k = defined_k; } } else { @@ -1173,8 +1164,8 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, // If defining the class throws an exception register 'k' for cleanup. if (HAS_PENDING_EXCEPTION) { - assert(k.not_null(), "Must have an instance klass here!"); - loader_data->add_to_deallocate_list(k()); + assert(k != NULL, "Must have an instance klass here!"); + loader_data->add_to_deallocate_list(k); return NULL; } @@ -1183,10 +1174,10 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, MutexLocker mu(SystemDictionary_lock, THREAD); Klass* check = find_class(h_name, k->class_loader_data()); - assert(check == k(), "should be present in the dictionary"); + assert(check == k, "should be present in the dictionary"); } ); - return k(); + return k; } #if INCLUDE_CDS @@ -1201,7 +1192,7 @@ void SystemDictionary::set_shared_dictionary(HashtableBucket* t, int le // If there is a shared dictionary, then find the entry for the // given shared system class, if any. -Klass* SystemDictionary::find_shared_class(Symbol* class_name) { +InstanceKlass* SystemDictionary::find_shared_class(Symbol* class_name) { if (shared_dictionary() != NULL) { unsigned int d_hash = shared_dictionary()->compute_hash(class_name, NULL); int d_index = shared_dictionary()->hash_to_index(d_hash); @@ -1219,16 +1210,16 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) { // subclasses (yet). [Classes in the shared space are not part of the // object hierarchy until loaded.] -instanceKlassHandle SystemDictionary::load_shared_class( +InstanceKlass* SystemDictionary::load_shared_class( Symbol* class_name, Handle class_loader, TRAPS) { - instanceKlassHandle ik (THREAD, find_shared_class(class_name)); + InstanceKlass* ik = find_shared_class(class_name); // Make sure we only return the boot class for the NULL classloader. - if (ik.not_null() && + if (ik != NULL && ik->is_shared_boot_class() && class_loader.is_null()) { Handle protection_domain; return load_shared_class(ik, class_loader, protection_domain, THREAD); } - return instanceKlassHandle(); + return NULL; } // Check if a shared class can be loaded by the specific classloader: @@ -1238,7 +1229,7 @@ instanceKlassHandle SystemDictionary::load_shared_class( // - Class from -Xbootclasspath/a. The class has no defined PackageEntry, or must // be defined in an unnamed module. bool SystemDictionary::is_shared_class_visible(Symbol* class_name, - instanceKlassHandle ik, + InstanceKlass* ik, Handle class_loader, TRAPS) { assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(), "Cannot use sharing if java.base is patched"); @@ -1315,18 +1306,17 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name, } } -instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, - Handle class_loader, - Handle protection_domain, TRAPS) { - instanceKlassHandle nh = instanceKlassHandle(); // null Handle +InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, + Handle class_loader, + Handle protection_domain, TRAPS) { - if (ik.not_null()) { + if (ik != NULL) { Symbol* class_name = ik->name(); bool visible = is_shared_class_visible( - class_name, ik, class_loader, CHECK_(nh)); + class_name, ik, class_loader, CHECK_NULL); if (!visible) { - return nh; + return NULL; } // Resolve the superclass and interfaces. They must be the same @@ -1339,11 +1329,11 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, if (ik->super() != NULL) { Symbol* cn = ik->super()->name(); Klass *s = resolve_super_or_fail(class_name, cn, - class_loader, protection_domain, true, CHECK_(nh)); + class_loader, protection_domain, true, CHECK_NULL); if (s != ik->super()) { // The dynamically resolved super class is not the same as the one we used during dump time, // so we cannot use ik. - return nh; + return NULL; } else { assert(s->is_shared(), "must be"); } @@ -1354,19 +1344,19 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, for (int index = 0; index < num_interfaces; index++) { Klass* k = interfaces->at(index); Symbol* name = k->name(); - Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh)); + Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_NULL); if (k != i) { // The dynamically resolved interface class is not the same as the one we used during dump time, // so we cannot use ik. - return nh; + return NULL; } else { assert(i->is_shared(), "must be"); } } - instanceKlassHandle new_ik = KlassFactory::check_shared_class_file_load_hook( - ik, class_name, class_loader, protection_domain, CHECK_(nh)); - if (new_ik.not_null()) { + InstanceKlass* new_ik = KlassFactory::check_shared_class_file_load_hook( + ik, class_name, class_loader, protection_domain, CHECK_NULL); + if (new_ik != NULL) { // The class is changed by CFLH. Return the new class. The shared class is // not used. return new_ik; @@ -1391,16 +1381,16 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, ObjectLocker ol(lockObject, THREAD, true); // prohibited package check assumes all classes loaded from archive call // restore_unshareable_info which calls ik->set_package() - ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh)); + ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL); } if (log_is_enabled(Info, class, load)) { - ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL); + ik->print_loading_log(LogLevel::Info, loader_data, NULL, NULL); } // No 'else' here as logging levels are not mutually exclusive if (log_is_enabled(Debug, class, load)) { - ik()->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL); + ik->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL); } // For boot loader, ensure that GetSystemPackage knows that a class in this @@ -1421,12 +1411,12 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, } // notify a class loaded from shared object - ClassLoadingService::notify_class_loaded(ik(), true /* shared class */); + ClassLoadingService::notify_class_loaded(ik, true /* shared class */); } ik->set_has_passed_fingerprint_check(false); if (UseAOT && ik->supers_have_passed_fingerprint_checks()) { - uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik()); + uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik); uint64_t cds_fp = ik->get_stored_fingerprint(); if (aot_fp != 0 && aot_fp == cds_fp) { // This class matches with a class saved in an AOT library @@ -1440,8 +1430,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, } #endif // INCLUDE_CDS -instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { - instanceKlassHandle nh = instanceKlassHandle(); // null Handle +InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { if (class_loader.is_null()) { ResourceMark rm; @@ -1473,14 +1462,14 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha // and its package will be checked later by // ModuleEntryTable::verify_javabase_packages. if (ModuleEntryTable::javabase_defined()) { - return nh; + return NULL; } } else { // Check that the class' package is defined within java.base. ModuleEntry* mod_entry = pkg_entry->module(); Symbol* mod_entry_name = mod_entry->name(); if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) { - return nh; + return NULL; } } } @@ -1506,7 +1495,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha // Search the shared system dictionary for classes preloaded into the // shared spaces. - instanceKlassHandle k; + InstanceKlass* k = NULL; { #if INCLUDE_CDS PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); @@ -1514,24 +1503,24 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha #endif } - if (k.is_null()) { + if (k == NULL) { // Use VM class loader PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time()); - k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh)); + k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_NULL); } // find_or_define_instance_class may return a different InstanceKlass - if (!k.is_null()) { - instanceKlassHandle defined_k = + if (k != NULL) { + InstanceKlass* defined_k = find_or_define_instance_class(class_name, class_loader, k, THREAD); - if (!HAS_PENDING_EXCEPTION && defined_k() != k()) { + if (!HAS_PENDING_EXCEPTION && defined_k != k) { // If a parallel capable class loader already defined this class, register 'k' for cleanup. - assert(defined_k.not_null(), "Should have a klass if there's no exception"); - loader_data->add_to_deallocate_list(k()); + assert(defined_k != NULL, "Should have a klass if there's no exception"); + loader_data->add_to_deallocate_list(k); k = defined_k; } else if (HAS_PENDING_EXCEPTION) { - loader_data->add_to_deallocate_list(k()); - return nh; + loader_data->add_to_deallocate_list(k); + return NULL; } } return k; @@ -1549,13 +1538,13 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha jt->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); - Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nh)); + Handle s = java_lang_String::create_from_symbol(class_name, CHECK_NULL); // Translate to external class name format, i.e., convert '/' chars to '.' - Handle string = java_lang_String::externalize_classname(s, CHECK_(nh)); + Handle string = java_lang_String::externalize_classname(s, CHECK_NULL); JavaValue result(T_OBJECT); - KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass()); + InstanceKlass* spec_klass = SystemDictionary::ClassLoader_klass(); // Call public unsynchronized loadClass(String) directly for all class loaders // for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will @@ -1581,7 +1570,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature(), string, - CHECK_(nh)); + CHECK_NULL); } else { JavaCalls::call_virtual(&result, class_loader, @@ -1589,7 +1578,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha vmSymbols::loadClass_name(), vmSymbols::string_class_signature(), string, - CHECK_(nh)); + CHECK_NULL); } assert(result.get_type() == T_OBJECT, "just checking"); @@ -1598,8 +1587,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha // Primitive classes return null since forName() can not be // used to obtain any of the Class objects representing primitives or void if ((obj != NULL) && !(java_lang_Class::is_primitive(obj))) { - instanceKlassHandle k = - instanceKlassHandle(THREAD, java_lang_Class::as_Klass(obj)); + InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(obj)); // For user defined Java class loaders, check that the name returned is // the same as that requested. This check is done for the bootstrap // loader when parsing the class file. @@ -1608,11 +1596,11 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha } } // Class is not found or has the wrong name, return NULL - return nh; + return NULL; } } -void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { +void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { HandleMark hm(THREAD); ClassLoaderData* loader_data = k->class_loader_data(); @@ -1677,7 +1665,7 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { // notify jvmti if (JvmtiExport::should_post_class_load()) { assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, k()); + JvmtiExport::post_class_load((JavaThread *) THREAD, k); } class_define_event(k, loader_data); @@ -1703,16 +1691,16 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { // placeholders()->find_and_add(PlaceholderTable::DEFINE_CLASS), // you need to find_and_remove it before returning. // So be careful to not exit with a CHECK_ macro betweeen these calls. -instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) { +InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, + InstanceKlass* k, TRAPS) { - instanceKlassHandle nh = instanceKlassHandle(); // null Handle Symbol* name_h = k->name(); // passed in class_name may be null ClassLoaderData* loader_data = class_loader_data(class_loader); unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data); int d_index = dictionary()->hash_to_index(d_hash); -// Hold SD lock around find_class and placeholder creation for DEFINE_CLASS + // Hold SD lock around find_class and placeholder creation for DEFINE_CLASS unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data); int p_index = placeholders()->hash_to_index(p_hash); PlaceholderEntry* probe; @@ -1721,9 +1709,9 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas MutexLocker mu(SystemDictionary_lock, THREAD); // First check if class already defined if (UnsyncloadClass || (is_parallelDefine(class_loader))) { - Klass* check = find_class(d_index, d_hash, name_h, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data); if (check != NULL) { - return(instanceKlassHandle(THREAD, check)); + return check; } } @@ -1743,10 +1731,10 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); #ifdef ASSERT - Klass* check = find_class(d_index, d_hash, name_h, loader_data); + InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data); assert(check != NULL, "definer missed recording success"); #endif - return(instanceKlassHandle(THREAD, probe->instance_klass())); + return probe->instance_klass(); } else { // This thread will define the class (even if earlier thread tried and had an error) probe->set_definer(THREAD); @@ -1767,7 +1755,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas linkage_exception = Handle(THREAD,PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; } else { - probe->set_instance_klass(k()); + probe->set_instance_klass(k); } probe->set_definer(NULL); placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); @@ -1777,7 +1765,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas // Can't throw exception while holding lock due to rank ordering if (linkage_exception() != NULL) { - THROW_OOP_(linkage_exception(), nh); // throws exception and returns + THROW_OOP_(linkage_exception(), NULL); // throws exception and returns } return k; @@ -1817,15 +1805,14 @@ void SystemDictionary::check_loader_lock_contention(Handle loader_lock, TRAPS) { // ---------------------------------------------------------------------------- // Lookup -Klass* SystemDictionary::find_class(int index, unsigned int hash, - Symbol* class_name, - ClassLoaderData* loader_data) { +InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash, + Symbol* class_name, + ClassLoaderData* loader_data) { assert_locked_or_safepoint(SystemDictionary_lock); assert (index == dictionary()->index_for(class_name, loader_data), "incorrect index?"); - Klass* k = dictionary()->find_class(index, hash, class_name, loader_data); - return k; + return dictionary()->find_class(index, hash, class_name, loader_data); } @@ -1840,7 +1827,7 @@ Symbol* SystemDictionary::find_placeholder(Symbol* class_name, // Used for assertions and verification only -Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) { +InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) { #ifndef ASSERT guarantee(VerifyBeforeGC || VerifyDuringGC || @@ -1868,8 +1855,8 @@ Klass* SystemDictionary::try_get_next_class() { // is held, to ensure that the compiler is not using the class hierachy, and that deoptimization will kick in // before a new class is used. -void SystemDictionary::add_to_hierarchy(instanceKlassHandle k, TRAPS) { - assert(k.not_null(), "just checking"); +void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { + assert(k != NULL, "just checking"); assert_locked_or_safepoint(Compile_lock); // Link into hierachy. Make sure the vtables are initialized before linking into @@ -2150,8 +2137,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { if (UseSharedSpaces) { initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Object_klass), scan, CHECK); // Initialize the constant pool for the Object_class - InstanceKlass* ik = InstanceKlass::cast(Object_klass()); - ik->constants()->restore_unshareable_info(CHECK); + Object_klass()->constants()->restore_unshareable_info(CHECK); initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); } else { initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); @@ -2231,7 +2217,7 @@ BasicType SystemDictionary::box_klass_type(Klass* k) { // if initiating loader, then ok if InstanceKlass matches existing entry void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, - instanceKlassHandle k, + InstanceKlass* k, Handle class_loader, bool defining, TRAPS) { const char *linkage_error1 = NULL; @@ -2242,8 +2228,8 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, MutexLocker mu(SystemDictionary_lock, THREAD); - Klass* check = find_class(d_index, d_hash, name, loader_data); - if (check != (Klass*)NULL) { + InstanceKlass* check = find_class(d_index, d_hash, name, loader_data); + if (check != NULL) { // if different InstanceKlass - duplicate class definition, // else - ok, class loaded by a different thread in parallel, // we should only have found it if it was done loading and ok to use @@ -2251,9 +2237,9 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, // also holds array classes assert(check->is_instance_klass(), "noninstance in systemdictionary"); - if ((defining == true) || (k() != check)) { - linkage_error1 = "loader (instance of "; - linkage_error2 = "): attempted duplicate class definition for name: \""; + if ((defining == true) || (k != check)) { + linkage_error1 = "loader (instance of "; + linkage_error2 = "): attempted duplicate class definition for name: \""; } else { return; } @@ -2292,7 +2278,7 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, // have been called. void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, int p_index, unsigned int p_hash, - instanceKlassHandle k, + InstanceKlass* k, Handle class_loader, TRAPS) { // Compile_lock prevents systemDictionary updates during compilations @@ -2324,7 +2310,7 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, } // Make a new system dictionary entry. - Klass* sd_check = find_class(d_index, d_hash, name, loader_data); + InstanceKlass* sd_check = find_class(d_index, d_hash, name, loader_data); if (sd_check == NULL) { dictionary()->add_klass(name, loader_data, k); notice_modification(); @@ -2415,8 +2401,8 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name, // Better never do a GC while we're holding these oops NoSafepointVerifier nosafepoint; - Klass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1); - Klass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2); + InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1); + InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2); return constraints()->add_entry(constraint_name, klass1, class_loader1, klass2, class_loader2); } @@ -2576,7 +2562,7 @@ methodHandle SystemDictionary::find_method_handle_intrinsic(vmIntrinsics::ID iid // Helper for unpacking the return value from linkMethod and linkCallSite. static methodHandle unpack_method_and_appendix(Handle mname, - KlassHandle accessing_klass, + Klass* accessing_klass, objArrayHandle appendix_box, Handle* appendix_result, TRAPS) { @@ -2600,7 +2586,7 @@ static methodHandle unpack_method_and_appendix(Handle mname, // MethodName is dropped we need a way to make sure the // class_loader containing this method is kept alive. // FIXME: the appendix might also preserve this dependency. - ClassLoaderData* this_key = InstanceKlass::cast(accessing_klass())->class_loader_data(); + ClassLoaderData* this_key = accessing_klass->class_loader_data(); this_key->record_dependency(m->method_holder(), CHECK_NULL); // Can throw OOM return methodHandle(THREAD, m); } @@ -2609,10 +2595,10 @@ static methodHandle unpack_method_and_appendix(Handle mname, return empty; } -methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass, +methodHandle SystemDictionary::find_method_handle_invoker(Klass* klass, Symbol* name, Symbol* signature, - KlassHandle accessing_klass, + Klass* accessing_klass, Handle *appendix_result, Handle *method_type_result, TRAPS) { @@ -2628,15 +2614,15 @@ methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass, assert(appendix_box->obj_at(0) == NULL, ""); // This should not happen. JDK code should take care of that. - if (accessing_klass.is_null() || method_type.is_null()) { + if (accessing_klass == NULL || method_type.is_null()) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokehandle", empty); } // call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName JavaCallArguments args; - args.push_oop(Handle(THREAD, accessing_klass()->java_mirror())); + args.push_oop(Handle(THREAD, accessing_klass->java_mirror())); args.push_int(ref_kind); - args.push_oop(Handle(THREAD, klass()->java_mirror())); + args.push_oop(Handle(THREAD, klass->java_mirror())); args.push_oop(name_str); args.push_oop(method_type); args.push_oop(appendix_box); @@ -2675,7 +2661,7 @@ static bool is_always_visible_class(oop mirror) { // Because of class loader constraints, all method handle usage must be // consistent with this loader. Handle SystemDictionary::find_method_handle_type(Symbol* signature, - KlassHandle accessing_klass, + Klass* accessing_klass, TRAPS) { Handle empty; vmIntrinsics::ID null_iid = vmIntrinsics::_none; // distinct from all method handle invoker intrinsics @@ -2691,9 +2677,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, } Handle class_loader, protection_domain; - if (accessing_klass.not_null()) { - class_loader = Handle(THREAD, InstanceKlass::cast(accessing_klass())->class_loader()); - protection_domain = Handle(THREAD, InstanceKlass::cast(accessing_klass())->protection_domain()); + if (accessing_klass != NULL) { + class_loader = Handle(THREAD, accessing_klass->class_loader()); + protection_domain = Handle(THREAD, accessing_klass->protection_domain()); } bool can_be_cached = true; int npts = ArgumentCount(signature).size(); @@ -2724,15 +2710,14 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, pts->obj_at_put(arg++, mirror); // Check accessibility. - if (ss.is_object() && accessing_klass.not_null()) { + if (ss.is_object() && accessing_klass != NULL) { Klass* sel_klass = java_lang_Class::as_Klass(mirror); mirror = NULL; // safety // Emulate ConstantPool::verify_constant_pool_resolve. if (sel_klass->is_objArray_klass()) sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass(); if (sel_klass->is_instance_klass()) { - KlassHandle sel_kh(THREAD, sel_klass); - LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); + LinkResolver::check_klass_accessability(accessing_klass, sel_klass, CHECK_(empty)); } } } @@ -2765,9 +2750,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, } // Ask Java code to find or construct a method handle constant. -Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, +Handle SystemDictionary::link_method_handle_constant(Klass* caller, int ref_kind, //e.g., JVM_REF_invokeVirtual - KlassHandle callee, + Klass* callee, Symbol* name_sym, Symbol* signature, TRAPS) { @@ -2776,7 +2761,7 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, Handle type; if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') { type = find_method_handle_type(signature, caller, CHECK_(empty)); - } else if (caller.is_null()) { + } else if (caller == NULL) { // This should not happen. JDK code should take care of that. THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad MH constant", empty); } else { @@ -2813,7 +2798,7 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, // Ask Java code to find or construct a java.lang.invoke.CallSite for the given // name and signature, as interpreted relative to the given class loader. -methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller, +methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller, Handle bootstrap_specifier, Symbol* name, Symbol* type, @@ -2844,7 +2829,7 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller Handle method_type = find_method_handle_type(type, caller, CHECK_(empty)); // This should not happen. JDK code should take care of that. - if (caller.is_null() || method_type.is_null()) { + if (caller == NULL || method_type.is_null()) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty); } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 612a83aac7e..cceca6101e7 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -259,7 +259,7 @@ class SystemDictionary : AllStatic { static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS); protected: // handle error translation for resolve_or_null results - static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, KlassHandle klass_h, TRAPS); + static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, Klass* klass, TRAPS); public: @@ -282,11 +282,11 @@ public: // Parse new stream. This won't update the system dictionary or // class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses. // Also used by Unsafe_DefineAnonymousClass - static Klass* parse_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - TRAPS) { + static InstanceKlass* parse_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, + TRAPS) { return parse_stream(class_name, class_loader, protection_domain, @@ -295,20 +295,20 @@ public: NULL, // cp_patches THREAD); } - static Klass* parse_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - const InstanceKlass* host_klass, - GrowableArray* cp_patches, - TRAPS); + static InstanceKlass* parse_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, + const InstanceKlass* host_klass, + GrowableArray* cp_patches, + TRAPS); // Resolve from stream (called by jni_DefineClass and JVM_DefineClass) - static Klass* resolve_from_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - TRAPS); + static InstanceKlass* resolve_from_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, + TRAPS); // Lookup an already loaded class. If not found NULL is returned. static Klass* find(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); @@ -516,10 +516,10 @@ public: // JSR 292 // find a java.lang.invoke.MethodHandle.invoke* method for a given signature // (asks Java to compute it if necessary, except in a compiler thread) - static methodHandle find_method_handle_invoker(KlassHandle klass, + static methodHandle find_method_handle_invoker(Klass* klass, Symbol* name, Symbol* signature, - KlassHandle accessing_klass, + Klass* accessing_klass, Handle *appendix_result, Handle *method_type_result, TRAPS); @@ -531,19 +531,19 @@ public: // find a java.lang.invoke.MethodType object for a given signature // (asks Java to compute it if necessary, except in a compiler thread) static Handle find_method_handle_type(Symbol* signature, - KlassHandle accessing_klass, + Klass* accessing_klass, TRAPS); // ask Java to compute a java.lang.invoke.MethodHandle object for a given CP entry - static Handle link_method_handle_constant(KlassHandle caller, + static Handle link_method_handle_constant(Klass* caller, int ref_kind, //e.g., JVM_REF_invokeVirtual - KlassHandle callee, + Klass* callee, Symbol* name, Symbol* signature, TRAPS); // ask Java to create a dynamic call site, while linking an invokedynamic op - static methodHandle find_dynamic_call_site_invoker(KlassHandle caller, + static methodHandle find_dynamic_call_site_invoker(Klass* caller, Handle bootstrap_method, Symbol* name, Symbol* type, @@ -615,7 +615,7 @@ public: static Klass* try_get_next_class(); protected: - static void validate_protection_domain(instanceKlassHandle klass, + static void validate_protection_domain(InstanceKlass* klass, Handle class_loader, Handle protection_domain, TRAPS); @@ -631,48 +631,48 @@ protected: // Basic loading operations static Klass* resolve_instance_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); static Klass* resolve_array_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); - static instanceKlassHandle handle_parallel_super_load(Symbol* class_name, Symbol* supername, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS); + static InstanceKlass* handle_parallel_super_load(Symbol* class_name, Symbol* supername, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS); // Wait on SystemDictionary_lock; unlocks lockObject before // waiting; relocks lockObject with correct recursion count // after waiting, but before reentering SystemDictionary_lock // to preserve lock order semantics. static void double_lock_wait(Handle lockObject, TRAPS); - static void define_instance_class(instanceKlassHandle k, TRAPS); - static instanceKlassHandle find_or_define_instance_class(Symbol* class_name, + static void define_instance_class(InstanceKlass* k, TRAPS); + static InstanceKlass* find_or_define_instance_class(Symbol* class_name, Handle class_loader, - instanceKlassHandle k, TRAPS); - static bool is_shared_class_visible(Symbol* class_name, instanceKlassHandle ik, + InstanceKlass* k, TRAPS); + static bool is_shared_class_visible(Symbol* class_name, InstanceKlass* ik, Handle class_loader, TRAPS); - static instanceKlassHandle load_shared_class(instanceKlassHandle ik, - Handle class_loader, - Handle protection_domain, - TRAPS); - static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); + static InstanceKlass* load_shared_class(InstanceKlass* ik, + Handle class_loader, + Handle protection_domain, + TRAPS); + static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); static bool is_parallelCapable(Handle class_loader); static bool is_parallelDefine(Handle class_loader); public: - static instanceKlassHandle load_shared_class(Symbol* class_name, - Handle class_loader, - TRAPS); + static InstanceKlass* load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS); static bool is_system_class_loader(oop class_loader); static bool is_platform_class_loader(oop class_loader); protected: - static Klass* find_shared_class(Symbol* class_name); + static InstanceKlass* find_shared_class(Symbol* class_name); // Setup link to hierarchy - static void add_to_hierarchy(instanceKlassHandle k, TRAPS); + static void add_to_hierarchy(InstanceKlass* k, TRAPS); // We pass in the hashtable index so we can calculate it outside of // the SystemDictionary_lock. // Basic find on loaded classes - static Klass* find_class(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data); - static Klass* find_class(Symbol* class_name, ClassLoaderData* loader_data); + static InstanceKlass* find_class(int index, unsigned int hash, + Symbol* name, ClassLoaderData* loader_data); + static InstanceKlass* find_class(Symbol* class_name, ClassLoaderData* loader_data); // Basic find on classes in the midst of being loaded static Symbol* find_placeholder(Symbol* name, ClassLoaderData* loader_data); @@ -697,11 +697,11 @@ protected: // Class loader constraints static void check_constraints(int index, unsigned int hash, - instanceKlassHandle k, Handle loader, + InstanceKlass* k, Handle loader, bool defining, TRAPS); static void update_dictionary(int d_index, unsigned int d_hash, int p_index, unsigned int p_hash, - instanceKlassHandle k, Handle loader, + InstanceKlass* k, Handle loader, TRAPS); // Variables holding commonly used klasses (preloaded) diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp index 764e1eaa348..d4803b740a2 100644 --- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,10 @@ class ClassFileStream; class SystemDictionaryShared: public SystemDictionary { public: static void initialize(TRAPS) {} - static instanceKlassHandle find_or_load_shared_class(Symbol* class_name, - Handle class_loader, - TRAPS) { - return instanceKlassHandle(); + static InstanceKlass* find_or_load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS) { + return NULL; } static void roots_oops_do(OopClosure* blk) {} static void oops_do(OopClosure* f) {} @@ -45,7 +45,7 @@ public: return (class_loader == NULL); } static bool is_shared_class_visible_for_classloader( - instanceKlassHandle ik, + InstanceKlass* ik, Handle class_loader, const char* pkg_string, Symbol* pkg_name, @@ -86,7 +86,7 @@ public: Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) {return false;} static void finalize_verification_constraints() {} - static void check_verification_constraints(instanceKlassHandle klass, + static void check_verification_constraints(InstanceKlass* klass, TRAPS) {} }; diff --git a/hotspot/src/share/vm/classfile/verificationType.cpp b/hotspot/src/share/vm/classfile/verificationType.cpp index fec279f7411..0817f1453e4 100644 --- a/hotspot/src/share/vm/classfile/verificationType.cpp +++ b/hotspot/src/share/vm/classfile/verificationType.cpp @@ -42,18 +42,16 @@ VerificationType VerificationType::from_tag(u1 tag) { } } -bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name, +bool VerificationType::resolve_and_check_assignability(InstanceKlass* klass, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) { HandleMark hm(THREAD); - Klass* obj = SystemDictionary::resolve_or_fail( + Klass* this_class = SystemDictionary::resolve_or_fail( name, Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { - Verifier::trace_class_resolution(obj, klass()); + Verifier::trace_class_resolution(this_class, klass); } - KlassHandle this_class(THREAD, obj); - if (this_class->is_interface() && (!from_field_is_protected || from_name != vmSymbols::java_lang_Object())) { // If we are not trying to access a protected field or method in @@ -68,9 +66,9 @@ bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass from_name, Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { - Verifier::trace_class_resolution(from_class, klass()); + Verifier::trace_class_resolution(from_class, klass); } - return InstanceKlass::cast(from_class)->is_subclass_of(this_class()); + return InstanceKlass::cast(from_class)->is_subclass_of(this_class); } return false; @@ -79,7 +77,7 @@ bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass bool VerificationType::is_reference_assignable_from( const VerificationType& from, ClassVerifier* context, bool from_field_is_protected, TRAPS) const { - instanceKlassHandle klass = context->current_class(); + InstanceKlass* klass = context->current_class(); if (from.is_null()) { // null is assignable to any reference return true; @@ -94,7 +92,7 @@ bool VerificationType::is_reference_assignable_from( return true; } - if (DumpSharedSpaces && SystemDictionaryShared::add_verification_constraint(klass(), + if (DumpSharedSpaces && SystemDictionaryShared::add_verification_constraint(klass, name(), from.name(), from_field_is_protected, from.is_array(), from.is_object())) { // If add_verification_constraint() returns true, the resolution/check should be @@ -102,7 +100,7 @@ bool VerificationType::is_reference_assignable_from( return true; } - return resolve_and_check_assignability(klass(), name(), from.name(), + return resolve_and_check_assignability(klass, name(), from.name(), from_field_is_protected, from.is_array(), from.is_object(), THREAD); } else if (is_array() && from.is_array()) { VerificationType comp_this = get_component(context, CHECK_false); diff --git a/hotspot/src/share/vm/classfile/verificationType.hpp b/hotspot/src/share/vm/classfile/verificationType.hpp index 92e2043334c..8d59b33a38e 100644 --- a/hotspot/src/share/vm/classfile/verificationType.hpp +++ b/hotspot/src/share/vm/classfile/verificationType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -336,7 +336,7 @@ class VerificationType VALUE_OBJ_CLASS_SPEC { TRAPS) const; public: - static bool resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name, + static bool resolve_and_check_assignability(InstanceKlass* klass, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS); diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 12e99051457..de274357b83 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -125,7 +125,7 @@ void Verifier::log_end_verification(outputStream* st, const char* klassName, Sym st->print_cr("End class verification for: %s", klassName); } -bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) { +bool Verifier::verify(InstanceKlass* klass, Verifier::Mode mode, bool should_verify_class, TRAPS) { HandleMark hm(THREAD); ResourceMark rm(THREAD); @@ -203,13 +203,13 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul return true; // verifcation succeeded } else { // VerifyError or ClassFormatError to be created and thrown ResourceMark rm(THREAD); - instanceKlassHandle kls = + Klass* kls = SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { - Verifier::trace_class_resolution(kls(), klass()); + Verifier::trace_class_resolution(kls, klass); } - while (!kls.is_null()) { + while (kls != NULL) { if (kls == klass) { // If the class being verified is the exception we're creating // or one of it's superclasses, we're in trouble and are going @@ -224,7 +224,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul } } -bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { +bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_verify_class) { Symbol* name = klass->name(); Klass* refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); @@ -243,7 +243,7 @@ bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool shou // already been rewritten to contain constant pool cache indices, // which the verifier can't understand. // Shared classes shouldn't have stackmaps either. - !klass()->is_shared() && + !klass->is_shared() && // As of the fix for 4486457 we disable verification for all of the // dynamically-generated bytecodes associated with the 1.4 @@ -256,7 +256,7 @@ bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool shou } Symbol* Verifier::inference_verify( - instanceKlassHandle klass, char* message, size_t message_len, TRAPS) { + InstanceKlass* klass, char* message, size_t message_len, TRAPS) { JavaThread* thread = (JavaThread*)THREAD; JNIEnv *env = thread->jni_environment(); @@ -559,7 +559,7 @@ void ErrorContext::stackmap_details(outputStream* ss, const Method* method) cons // Methods in ClassVerifier ClassVerifier::ClassVerifier( - instanceKlassHandle klass, TRAPS) + InstanceKlass* klass, TRAPS) : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) { _this_type = VerificationType::reference_type(klass->name()); // Create list to hold symbols in reference area. @@ -2001,13 +2001,13 @@ Klass* ClassVerifier::load_class(Symbol* name, TRAPS) { true, THREAD); if (log_is_enabled(Debug, class, resolve)) { - instanceKlassHandle cur_class = current_class(); - Verifier::trace_class_resolution(kls, cur_class()); + InstanceKlass* cur_class = InstanceKlass::cast(current_class()); + Verifier::trace_class_resolution(kls, cur_class); } return kls; } -bool ClassVerifier::is_protected_access(instanceKlassHandle this_class, +bool ClassVerifier::is_protected_access(InstanceKlass* this_class, Klass* target_class, Symbol* field_name, Symbol* field_sig, @@ -2170,7 +2170,7 @@ void ClassVerifier::verify_switch( } bool ClassVerifier::name_in_supers( - Symbol* ref_name, instanceKlassHandle current) { + Symbol* ref_name, InstanceKlass* current) { Klass* super = current->super(); while (super != NULL) { if (super->name() == ref_name) { @@ -2600,8 +2600,8 @@ void ClassVerifier::verify_invoke_init( Klass::find_overpass); // Do nothing if method is not found. Let resolution detect the error. if (m != NULL) { - instanceKlassHandle mh(THREAD, m->method_holder()); - if (m->is_protected() && !mh->is_same_class_package(_klass())) { + InstanceKlass* mh = m->method_holder(); + if (m->is_protected() && !mh->is_same_class_package(_klass)) { bool assignable = current_type().is_assignable_from( objectref_type, this, true, CHECK_VERIFY(this)); if (!assignable) { @@ -2631,7 +2631,7 @@ void ClassVerifier::verify_invoke_init( } bool ClassVerifier::is_same_or_direct_interface( - instanceKlassHandle klass, + InstanceKlass* klass, VerificationType klass_type, VerificationType ref_class_type) { if (ref_class_type.equals(klass_type)) return true; diff --git a/hotspot/src/share/vm/classfile/verifier.hpp b/hotspot/src/share/vm/classfile/verifier.hpp index f4c00eb9b1d..c79590d1bac 100644 --- a/hotspot/src/share/vm/classfile/verifier.hpp +++ b/hotspot/src/share/vm/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -51,7 +51,7 @@ class Verifier : AllStatic { * error. */ static void log_end_verification(outputStream* st, const char* klassName, Symbol* exception_name, TRAPS); - static bool verify(instanceKlassHandle klass, Mode mode, bool should_verify_class, TRAPS); + static bool verify(InstanceKlass* klass, Mode mode, bool should_verify_class, TRAPS); // Return false if the class is loaded by the bootstrap loader, // or if defineClass was called requesting skipping verification @@ -65,9 +65,9 @@ class Verifier : AllStatic { static void trace_class_resolution(Klass* resolve_class, InstanceKlass* verify_class); private: - static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class); + static bool is_eligible_for_verification(InstanceKlass* klass, bool should_verify_class); static Symbol* inference_verify( - instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS); + InstanceKlass* klass, char* msg, size_t msg_len, TRAPS); }; class RawBytecodeStream; @@ -275,7 +275,7 @@ class ClassVerifier : public StackObj { } bool is_protected_access( - instanceKlassHandle this_class, Klass* target_class, + InstanceKlass* this_class, Klass* target_class, Symbol* field_name, Symbol* field_sig, bool is_method); void verify_cp_index(u2 bci, const constantPoolHandle& cp, int index, TRAPS); @@ -344,11 +344,11 @@ class ClassVerifier : public StackObj { void verify_astore(u2 index, StackMapFrame* current_frame, TRAPS); void verify_iinc (u2 index, StackMapFrame* current_frame, TRAPS); - bool name_in_supers(Symbol* ref_name, instanceKlassHandle current); + bool name_in_supers(Symbol* ref_name, InstanceKlass* current); VerificationType object_type() const; - instanceKlassHandle _klass; // the class being verified + InstanceKlass* _klass; // the class being verified methodHandle _method; // current method being verified VerificationType _this_type; // the verification type of the current class @@ -362,7 +362,7 @@ class ClassVerifier : public StackObj { // that a class has been verified and prepared for execution. bool was_recursively_verified() { return _klass->is_rewritten(); } - bool is_same_or_direct_interface(instanceKlassHandle klass, + bool is_same_or_direct_interface(InstanceKlass* klass, VerificationType klass_type, VerificationType ref_class_type); public: @@ -372,14 +372,14 @@ class ClassVerifier : public StackObj { }; // constructor - ClassVerifier(instanceKlassHandle klass, TRAPS); + ClassVerifier(InstanceKlass* klass, TRAPS); // destructor ~ClassVerifier(); Thread* thread() { return _thread; } const methodHandle& method() { return _method; } - instanceKlassHandle current_class() const { return _klass; } + InstanceKlass* current_class() const { return _klass; } VerificationType current_type() const { return _this_type; } // Verifies the class. If a verify or class file format error occurs, diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 7378fd00aec..9848e188a2e 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1141,7 +1141,7 @@ bool CodeCache::is_far_target(address target) { } #ifdef HOTSWAP -int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) { +int CodeCache::mark_for_evol_deoptimization(InstanceKlass* dependee) { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); int number_of_marked_CodeBlobs = 0; @@ -1162,7 +1162,7 @@ int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) { CompiledMethod* nm = iter.method(); if (nm->is_marked_for_deoptimization()) { // ...Already marked in the previous pass; don't count it again. - } else if (nm->is_evol_dependent_on(dependee())) { + } else if (nm->is_evol_dependent_on(dependee)) { ResourceMark rm; nm->mark_for_deoptimization(); number_of_marked_CodeBlobs++; @@ -1218,7 +1218,7 @@ void CodeCache::make_marked_nmethods_not_entrant() { } // Flushes compiled methods dependent on dependee. -void CodeCache::flush_dependents_on(instanceKlassHandle dependee) { +void CodeCache::flush_dependents_on(InstanceKlass* dependee) { assert_lock_strong(Compile_lock); if (number_of_nmethods_with_dependencies() == 0) return; @@ -1239,7 +1239,7 @@ void CodeCache::flush_dependents_on(instanceKlassHandle dependee) { #ifdef HOTSWAP // Flushes compiled methods dependent on dependee in the evolutionary sense -void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) { +void CodeCache::flush_evol_dependents_on(InstanceKlass* ev_k) { // --- Compile_lock is not held. However we are at a safepoint. assert_locked_or_safepoint(Compile_lock); if (number_of_nmethods_with_dependencies() == 0 && !UseAOT) return; @@ -1249,7 +1249,7 @@ void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) { // holding the CodeCache_lock. // Compute the dependent nmethods - if (mark_for_evol_deoptimization(ev_k_h) > 0) { + if (mark_for_evol_deoptimization(ev_k) > 0) { // At least one nmethod has been marked for deoptimization // All this already happens inside a VM_Operation, so we'll do all the work here. diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 469ac0af329..f48b9a4fe6c 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -260,7 +260,7 @@ class CodeCache : AllStatic { private: static int mark_for_deoptimization(KlassDepChange& changes); #ifdef HOTSWAP - static int mark_for_evol_deoptimization(instanceKlassHandle dependee); + static int mark_for_evol_deoptimization(InstanceKlass* dependee); #endif // HOTSWAP public: @@ -269,10 +269,10 @@ class CodeCache : AllStatic { static void make_marked_nmethods_not_entrant(); // Flushing and deoptimization - static void flush_dependents_on(instanceKlassHandle dependee); + static void flush_dependents_on(InstanceKlass* dependee); #ifdef HOTSWAP // Flushing and deoptimization in case of evolution - static void flush_evol_dependents_on(instanceKlassHandle dependee); + static void flush_evol_dependents_on(InstanceKlass* dependee); #endif // HOTSWAP // Support for fullspeed debugging static void flush_dependents_on_method(methodHandle dependee); diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp index 97db8a54b66..91e508f04b3 100644 --- a/hotspot/src/share/vm/code/compiledIC.cpp +++ b/hotspot/src/share/vm/code/compiledIC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -457,7 +457,7 @@ void CompiledIC::set_to_monomorphic(CompiledICInfo& info) { // null check, while a static_bound won't. A static_bound (but not optimized) must // therefore use the unverified entry point. void CompiledIC::compute_monomorphic_entry(const methodHandle& method, - KlassHandle receiver_klass, + Klass* receiver_klass, bool is_optimized, bool static_bound, bool caller_is_nmethod, @@ -494,7 +494,7 @@ void CompiledIC::compute_monomorphic_entry(const methodHandle& method, bool far_c2a = entry != NULL && caller_is_nmethod && method_code->is_far_code(); if (entry != NULL && !far_c2a) { // Call to near compiled code (nmethod or aot). - info.set_compiled_entry(entry, (static_bound || is_optimized) ? NULL : receiver_klass(), is_optimized); + info.set_compiled_entry(entry, (static_bound || is_optimized) ? NULL : receiver_klass, is_optimized); } else { if (is_optimized) { if (far_c2a) { @@ -507,7 +507,7 @@ void CompiledIC::compute_monomorphic_entry(const methodHandle& method, } else { // Use icholder entry assert(method_code == NULL || method_code->is_compiled(), "must be compiled"); - CompiledICHolder* holder = new CompiledICHolder(method(), receiver_klass()); + CompiledICHolder* holder = new CompiledICHolder(method(), receiver_klass); info.set_icholder_entry(method()->get_c2i_unverified_entry(), holder); } } diff --git a/hotspot/src/share/vm/code/compiledIC.hpp b/hotspot/src/share/vm/code/compiledIC.hpp index 15af2b44b87..ff3614c7bea 100644 --- a/hotspot/src/share/vm/code/compiledIC.hpp +++ b/hotspot/src/share/vm/code/compiledIC.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -266,7 +266,7 @@ class CompiledIC: public ResourceObj { // allocation in the code cache fails. bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); - static void compute_monomorphic_entry(const methodHandle& method, KlassHandle receiver_klass, + static void compute_monomorphic_entry(const methodHandle& method, Klass* receiver_klass, bool is_optimized, bool static_bound, bool caller_is_nmethod, CompiledICInfo& info, TRAPS); diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp index eeedcb10e8b..0c0f7f611bc 100644 --- a/hotspot/src/share/vm/code/dependencies.hpp +++ b/hotspot/src/share/vm/code/dependencies.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -737,13 +737,13 @@ class DepChange : public StackObj { class KlassDepChange : public DepChange { private: // each change set is rooted in exactly one new type (at present): - KlassHandle _new_type; + Klass* _new_type; void initialize(); public: // notes the new type, marks it and all its super-types - KlassDepChange(KlassHandle new_type) + KlassDepChange(Klass* new_type) : _new_type(new_type) { initialize(); @@ -759,7 +759,7 @@ class KlassDepChange : public DepChange { nm->mark_for_deoptimization(/*inc_recompile_counts=*/true); } - Klass* new_type() { return _new_type(); } + Klass* new_type() { return _new_type; } // involves_context(k) is true if k is new_type or any of the super types bool involves_context(Klass* k); diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 6ebb3362726..c3fd4fc27dd 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -683,7 +683,7 @@ JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, Co AbstractCompiler* comp, bool compiler_thread, TRAPS) { JavaThread* thread = NULL; Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_0); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* klass = InstanceKlass::cast(k); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_0); Handle string = java_lang_String::create_from_str(name, CHECK_0); diff --git a/hotspot/src/share/vm/gc/shared/allocTracer.cpp b/hotspot/src/share/vm/gc/shared/allocTracer.cpp index 5f79a3310b3..b7050110278 100644 --- a/hotspot/src/share/vm/gc/shared/allocTracer.cpp +++ b/hotspot/src/share/vm/gc/shared/allocTracer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,19 +28,19 @@ #include "trace/tracing.hpp" #include "utilities/globalDefinitions.hpp" -void AllocTracer::send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size) { +void AllocTracer::send_allocation_outside_tlab_event(Klass* klass, size_t alloc_size) { EventObjectAllocationOutsideTLAB event; if (event.should_commit()) { - event.set_objectClass(klass()); + event.set_objectClass(klass); event.set_allocationSize(alloc_size); event.commit(); } } -void AllocTracer::send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size) { +void AllocTracer::send_allocation_in_new_tlab_event(Klass* klass, size_t tlab_size, size_t alloc_size) { EventObjectAllocationInNewTLAB event; if (event.should_commit()) { - event.set_objectClass(klass()); + event.set_objectClass(klass); event.set_allocationSize(alloc_size); event.set_tlabSize(tlab_size); event.commit(); diff --git a/hotspot/src/share/vm/gc/shared/allocTracer.hpp b/hotspot/src/share/vm/gc/shared/allocTracer.hpp index bd34c9bfd64..82a42325c29 100644 --- a/hotspot/src/share/vm/gc/shared/allocTracer.hpp +++ b/hotspot/src/share/vm/gc/shared/allocTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,8 @@ class AllocTracer : AllStatic { public: - static void send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size); - static void send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size); + static void send_allocation_outside_tlab_event(Klass* klass, size_t alloc_size); + static void send_allocation_in_new_tlab_event(Klass* klass, size_t tlab_size, size_t alloc_size); static void send_allocation_requiring_gc_event(size_t size, uint gcId); }; diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp index 737c57c117d..20c92bfcfd8 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -279,7 +279,7 @@ void CollectedHeap::check_for_valid_allocation_state() { } #endif -HeapWord* CollectedHeap::allocate_from_tlab_slow(KlassHandle klass, Thread* thread, size_t size) { +HeapWord* CollectedHeap::allocate_from_tlab_slow(Klass* klass, Thread* thread, size_t size) { // Retain tlab and allocate object in shared space if // the amount free in the tlab is too large to discard. diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp index 774f329a5c6..363a59abf3e 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -138,28 +138,28 @@ class CollectedHeap : public CHeapObj { virtual void resize_all_tlabs(); // Allocate from the current thread's TLAB, with broken-out slow path. - inline static HeapWord* allocate_from_tlab(KlassHandle klass, Thread* thread, size_t size); - static HeapWord* allocate_from_tlab_slow(KlassHandle klass, Thread* thread, size_t size); + inline static HeapWord* allocate_from_tlab(Klass* klass, Thread* thread, size_t size); + static HeapWord* allocate_from_tlab_slow(Klass* klass, Thread* thread, size_t size); // Allocate an uninitialized block of the given size, or returns NULL if // this is impossible. - inline static HeapWord* common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS); + inline static HeapWord* common_mem_allocate_noinit(Klass* klass, size_t size, TRAPS); // Like allocate_init, but the block returned by a successful allocation // is guaranteed initialized to zeros. - inline static HeapWord* common_mem_allocate_init(KlassHandle klass, size_t size, TRAPS); + inline static HeapWord* common_mem_allocate_init(Klass* klass, size_t size, TRAPS); // Helper functions for (VM) allocation. - inline static void post_allocation_setup_common(KlassHandle klass, HeapWord* obj); - inline static void post_allocation_setup_no_klass_install(KlassHandle klass, + inline static void post_allocation_setup_common(Klass* klass, HeapWord* obj); + inline static void post_allocation_setup_no_klass_install(Klass* klass, HeapWord* objPtr); - inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj, int size); + inline static void post_allocation_setup_obj(Klass* klass, HeapWord* obj, int size); - inline static void post_allocation_setup_array(KlassHandle klass, + inline static void post_allocation_setup_array(Klass* klass, HeapWord* obj, int length); - inline static void post_allocation_setup_class(KlassHandle klass, HeapWord* obj, int size); + inline static void post_allocation_setup_class(Klass* klass, HeapWord* obj, int size); // Clears an allocated object. inline static void init_obj(HeapWord* obj, size_t size); @@ -299,10 +299,10 @@ class CollectedHeap : public CHeapObj { GCCause::Cause gc_cause() { return _gc_cause; } // General obj/array allocation facilities. - inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); - inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); - inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS); - inline static oop class_allocate(KlassHandle klass, int size, TRAPS); + inline static oop obj_allocate(Klass* klass, int size, TRAPS); + inline static oop array_allocate(Klass* klass, int size, int length, TRAPS); + inline static oop array_allocate_nozero(Klass* klass, int size, int length, TRAPS); + inline static oop class_allocate(Klass* klass, int size, TRAPS); // Raw memory allocation facilities // The obj and array allocate methods are covers for these methods. diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp index cd54e1fdc5b..f4c89f7a7fc 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -40,26 +40,26 @@ // Inline allocation implementations. -void CollectedHeap::post_allocation_setup_common(KlassHandle klass, +void CollectedHeap::post_allocation_setup_common(Klass* klass, HeapWord* obj_ptr) { post_allocation_setup_no_klass_install(klass, obj_ptr); oop obj = (oop)obj_ptr; #if ! INCLUDE_ALL_GCS - obj->set_klass(klass()); + obj->set_klass(klass); #else // Need a release store to ensure array/class length, mark word, and // object zeroing are visible before setting the klass non-NULL, for // concurrent collectors. - obj->release_set_klass(klass()); + obj->release_set_klass(klass); #endif } -void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass, +void CollectedHeap::post_allocation_setup_no_klass_install(Klass* klass, HeapWord* obj_ptr) { oop obj = (oop)obj_ptr; assert(obj != NULL, "NULL object pointer"); - if (UseBiasedLocking && (klass() != NULL)) { + if (UseBiasedLocking && (klass != NULL)) { obj->set_mark(klass->prototype_header()); } else { // May be bootstrapping @@ -68,7 +68,7 @@ void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass, } // Support for jvmti and dtrace -inline void post_allocation_notify(KlassHandle klass, oop obj, int size) { +inline void post_allocation_notify(Klass* klass, oop obj, int size) { // support low memory notifications (no-op if not enabled) LowMemoryDetector::detect_low_memory_for_collected_pools(); @@ -77,13 +77,13 @@ inline void post_allocation_notify(KlassHandle klass, oop obj, int size) { if (DTraceAllocProbes) { // support for Dtrace object alloc event (no-op most of the time) - if (klass() != NULL && klass()->name() != NULL) { + if (klass != NULL && klass->name() != NULL) { SharedRuntime::dtrace_object_alloc(obj, size); } } } -void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, +void CollectedHeap::post_allocation_setup_obj(Klass* klass, HeapWord* obj_ptr, int size) { post_allocation_setup_common(klass, obj_ptr); @@ -94,7 +94,7 @@ void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, post_allocation_notify(klass, obj, size); } -void CollectedHeap::post_allocation_setup_class(KlassHandle klass, +void CollectedHeap::post_allocation_setup_class(Klass* klass, HeapWord* obj_ptr, int size) { // Set oop_size field before setting the _klass field because a @@ -110,7 +110,7 @@ void CollectedHeap::post_allocation_setup_class(KlassHandle klass, post_allocation_notify(klass, new_cls, size); } -void CollectedHeap::post_allocation_setup_array(KlassHandle klass, +void CollectedHeap::post_allocation_setup_array(Klass* klass, HeapWord* obj_ptr, int length) { // Set array length before setting the _klass field because a @@ -125,7 +125,7 @@ void CollectedHeap::post_allocation_setup_array(KlassHandle klass, post_allocation_notify(klass, new_obj, new_obj->size()); } -HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) { +HeapWord* CollectedHeap::common_mem_allocate_noinit(Klass* klass, size_t size, TRAPS) { // Clear unhandled oops for memory allocation. Memory allocation might // not take out a lock if from tlab, so clear here. @@ -186,13 +186,13 @@ HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t si } } -HeapWord* CollectedHeap::common_mem_allocate_init(KlassHandle klass, size_t size, TRAPS) { +HeapWord* CollectedHeap::common_mem_allocate_init(Klass* klass, size_t size, TRAPS) { HeapWord* obj = common_mem_allocate_noinit(klass, size, CHECK_NULL); init_obj(obj, size); return obj; } -HeapWord* CollectedHeap::allocate_from_tlab(KlassHandle klass, Thread* thread, size_t size) { +HeapWord* CollectedHeap::allocate_from_tlab(Klass* klass, Thread* thread, size_t size) { assert(UseTLAB, "should use UseTLAB"); HeapWord* obj = thread->tlab().allocate(size); @@ -211,7 +211,7 @@ void CollectedHeap::init_obj(HeapWord* obj, size_t size) { Copy::fill_to_aligned_words(obj + hs, size - hs); } -oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) { +oop CollectedHeap::obj_allocate(Klass* klass, int size, TRAPS) { debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); @@ -221,7 +221,7 @@ oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) { return (oop)obj; } -oop CollectedHeap::class_allocate(KlassHandle klass, int size, TRAPS) { +oop CollectedHeap::class_allocate(Klass* klass, int size, TRAPS) { debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); @@ -231,7 +231,7 @@ oop CollectedHeap::class_allocate(KlassHandle klass, int size, TRAPS) { return (oop)obj; } -oop CollectedHeap::array_allocate(KlassHandle klass, +oop CollectedHeap::array_allocate(Klass* klass, int size, int length, TRAPS) { @@ -244,7 +244,7 @@ oop CollectedHeap::array_allocate(KlassHandle klass, return (oop)obj; } -oop CollectedHeap::array_allocate_nozero(KlassHandle klass, +oop CollectedHeap::array_allocate_nozero(Klass* klass, int size, int length, TRAPS) { diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 573529f8cec..3bf0808ed45 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -138,8 +138,8 @@ IRT_END // Allocation IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index)) - Klass* k_oop = pool->klass_at(index, CHECK); - instanceKlassHandle klass (THREAD, k_oop); + Klass* k = pool->klass_at(index, CHECK); + InstanceKlass* klass = InstanceKlass::cast(k); // Make sure we are not instantiating an abstract klass klass->check_valid_for_instantiation(true, CHECK); @@ -461,8 +461,8 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea Exceptions::debug_check_abort(h_exception); // exception handler lookup - KlassHandle h_klass(THREAD, h_exception->klass()); - handler_bci = Method::fast_exception_handler_bci_for(h_method, h_klass, current_bci, THREAD); + Klass* klass = h_exception->klass(); + handler_bci = Method::fast_exception_handler_bci_for(h_method, klass, current_bci, THREAD); if (HAS_PENDING_EXCEPTION) { // We threw an exception while trying to find the exception handler. // Transfer the new exception to the exception handle which will @@ -1070,15 +1070,15 @@ ConstantPoolCacheEntry *cp_entry)) // non-static field accessors have an object, but we need a handle h_obj = Handle(thread, obj); } - instanceKlassHandle h_cp_entry_f1(thread, (Klass*)cp_entry->f1_as_klass()); - jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_cp_entry_f1, cp_entry->f2_as_index(), is_static); - JvmtiExport::post_field_access(thread, method(thread), bcp(thread), h_cp_entry_f1, h_obj, fid); + InstanceKlass* cp_entry_f1 = InstanceKlass::cast(cp_entry->f1_as_klass()); + jfieldID fid = jfieldIDWorkaround::to_jfieldID(cp_entry_f1, cp_entry->f2_as_index(), is_static); + JvmtiExport::post_field_access(thread, method(thread), bcp(thread), cp_entry_f1, h_obj, fid); IRT_END IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, oopDesc* obj, ConstantPoolCacheEntry *cp_entry, jvalue *value)) - Klass* k = (Klass*)cp_entry->f1_as_klass(); + Klass* k = cp_entry->f1_as_klass(); // check the access_flags for the field in the klass InstanceKlass* ik = InstanceKlass::cast(k); @@ -1103,8 +1103,7 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, bool is_static = (obj == NULL); HandleMark hm(thread); - instanceKlassHandle h_klass(thread, k); - jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_klass, cp_entry->f2_as_index(), is_static); + jfieldID fid = jfieldIDWorkaround::to_jfieldID(ik, cp_entry->f2_as_index(), is_static); jvalue fvalue; #ifdef _LP64 fvalue = *value; @@ -1128,7 +1127,7 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, h_obj = Handle(thread, obj); } - JvmtiExport::post_raw_field_modification(thread, method(thread), bcp(thread), h_klass, h_obj, + JvmtiExport::post_raw_field_modification(thread, method(thread), bcp(thread), ik, h_obj, fid, sig_type, &fvalue); IRT_END diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index ce452bfe1f4..c779460d4d4 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -55,14 +55,14 @@ // Implementation of CallInfo -void CallInfo::set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS) { +void CallInfo::set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS) { int vtable_index = Method::nonvirtual_vtable_index; set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); } -void CallInfo::set_interface(KlassHandle resolved_klass, - KlassHandle selected_klass, +void CallInfo::set_interface(Klass* resolved_klass, + Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, int itable_index, TRAPS) { @@ -75,8 +75,8 @@ void CallInfo::set_interface(KlassHandle resolved_klass, set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK); } -void CallInfo::set_virtual(KlassHandle resolved_klass, - KlassHandle selected_klass, +void CallInfo::set_virtual(Klass* resolved_klass, + Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, int vtable_index, TRAPS) { @@ -93,7 +93,7 @@ void CallInfo::set_handle(const methodHandle& resolved_method, set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK); } -void CallInfo::set_handle(KlassHandle resolved_klass, +void CallInfo::set_handle(Klass* resolved_klass, const methodHandle& resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) { @@ -110,8 +110,8 @@ void CallInfo::set_handle(KlassHandle resolved_klass, _resolved_method_type = resolved_method_type; } -void CallInfo::set_common(KlassHandle resolved_klass, - KlassHandle selected_klass, +void CallInfo::set_common(Klass* resolved_klass, + Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, CallKind kind, @@ -162,8 +162,8 @@ CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) { #ifdef ASSERT // Ensure that this is really the case. - KlassHandle object_klass = SystemDictionary::Object_klass(); - Method * object_resolved_method = object_klass()->vtable()->method_at(index); + Klass* object_klass = SystemDictionary::Object_klass(); + Method * object_resolved_method = object_klass->vtable()->method_at(index); assert(object_resolved_method->name() == resolved_method->name(), "Object and interface method names should match at vtable index %d, %s != %s", index, object_resolved_method->name()->as_C_string(), resolved_method->name()->as_C_string()); @@ -225,14 +225,13 @@ void CallInfo::print() { LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS) { // resolve klass - Klass* result = pool->klass_ref_at(index, CHECK); - _resolved_klass = KlassHandle(THREAD, result); + _resolved_klass = pool->klass_ref_at(index, CHECK); // Get name, signature, and static klass _name = pool->name_ref_at(index); _signature = pool->signature_ref_at(index); _tag = pool->tag_ref_at(index); - _current_klass = KlassHandle(THREAD, pool->pool_holder()); + _current_klass = pool->pool_holder(); _current_method = current_method; // Coming from the constant pool always checks access @@ -241,14 +240,13 @@ LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle curre LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { // resolve klass - Klass* result = pool->klass_ref_at(index, CHECK); - _resolved_klass = KlassHandle(THREAD, result); + _resolved_klass = pool->klass_ref_at(index, CHECK); // Get name, signature, and static klass _name = pool->name_ref_at(index); _signature = pool->signature_ref_at(index); _tag = pool->tag_ref_at(index); - _current_klass = KlassHandle(THREAD, pool->pool_holder()); + _current_klass = pool->pool_holder(); _current_method = methodHandle(); // Coming from the constant pool always checks access @@ -256,7 +254,7 @@ LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { } char* LinkInfo::method_string() const { - return Method::name_and_sig_as_C_string(_resolved_klass(), _name, _signature); + return Method::name_and_sig_as_C_string(_resolved_klass, _name, _signature); } #ifndef PRODUCT @@ -266,20 +264,20 @@ void LinkInfo::print() { _resolved_klass->name()->as_C_string(), _name->as_C_string(), _signature->as_C_string(), - _current_klass.is_null() ? "(none)" : _current_klass->name()->as_C_string(), + _current_klass == NULL ? "(none)" : _current_klass->name()->as_C_string(), _check_access ? "true" : "false"); } #endif // PRODUCT //------------------------------------------------------------------------------------------------------------------------ // Klass resolution -void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) { +void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS) { Reflection::VerifyClassAccessResults vca_result = - Reflection::verify_class_access(ref_klass(), InstanceKlass::cast(sel_klass()), true); + Reflection::verify_class_access(ref_klass, InstanceKlass::cast(sel_klass), true); if (vca_result != Reflection::ACCESS_OK) { ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(ref_klass(), - InstanceKlass::cast(sel_klass()), + char* msg = Reflection::verify_class_access_msg(ref_klass, + InstanceKlass::cast(sel_klass), vca_result); if (msg == NULL) { Exceptions::fthrow( @@ -308,7 +306,7 @@ void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { - KlassHandle klass = link_info.resolved_klass(); + Klass* klass = link_info.resolved_klass(); Symbol* name = link_info.name(); Symbol* signature = link_info.signature(); @@ -320,7 +318,7 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, return methodHandle(THREAD, result); } - InstanceKlass* ik = InstanceKlass::cast(klass()); + InstanceKlass* ik = InstanceKlass::cast(klass); // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, @@ -358,7 +356,7 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, // returns first instance method // Looks up method in classes, then looks up local default methods -methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass, +methodHandle LinkResolver::lookup_instance_method_in_klasses(Klass* klass, Symbol* name, Symbol* signature, TRAPS) { Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass); @@ -374,7 +372,7 @@ methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass, } if (result == NULL) { - Array* default_methods = InstanceKlass::cast(klass())->default_methods(); + Array* default_methods = InstanceKlass::cast(klass)->default_methods(); if (default_methods != NULL) { result = InstanceKlass::find_method(default_methods, name, signature); assert(result == NULL || !result->is_static(), "static defaults not allowed"); @@ -383,13 +381,13 @@ methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass, return methodHandle(THREAD, result); } -int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, +int LinkResolver::vtable_index_of_interface_method(Klass* klass, const methodHandle& resolved_method) { int vtable_index = Method::invalid_vtable_index; Symbol* name = resolved_method->name(); Symbol* signature = resolved_method->signature(); - InstanceKlass* ik = InstanceKlass::cast(klass()); + InstanceKlass* ik = InstanceKlass::cast(klass); // First check in default method array if (!resolved_method->is_abstract() && ik->default_methods() != NULL) { @@ -410,7 +408,7 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, } methodHandle LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info, TRAPS) { - InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass()()); + InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass()); // Specify 'true' in order to skip default methods when searching the // interfaces. Function lookup_method_in_klasses() already looked for @@ -425,7 +423,7 @@ methodHandle LinkResolver::lookup_polymorphic_method( Handle *appendix_result_or_null, Handle *method_type_result, TRAPS) { - KlassHandle klass = link_info.resolved_klass(); + Klass* klass = link_info.resolved_klass(); Symbol* name = link_info.name(); Symbol* full_signature = link_info.signature(); @@ -436,8 +434,8 @@ methodHandle LinkResolver::lookup_polymorphic_method( vmIntrinsics::name_at(iid), klass->external_name(), name->as_C_string(), full_signature->as_C_string()); } - if ((klass() == SystemDictionary::MethodHandle_klass() || - klass() == SystemDictionary::VarHandle_klass()) && + if ((klass == SystemDictionary::MethodHandle_klass() || + klass == SystemDictionary::VarHandle_klass()) && iid != vmIntrinsics::_none) { if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) { // Most of these do not need an up-call to Java to resolve, so can be done anywhere. @@ -531,9 +529,9 @@ methodHandle LinkResolver::lookup_polymorphic_method( return NULL; } -void LinkResolver::check_method_accessability(KlassHandle ref_klass, - KlassHandle resolved_klass, - KlassHandle sel_klass, +void LinkResolver::check_method_accessability(Klass* ref_klass, + Klass* resolved_klass, + Klass* sel_klass, const methodHandle& sel_method, TRAPS) { @@ -547,7 +545,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, // We'll check for the method name first, as that's most likely // to be false (so we'll short-circuit out of these tests). if (sel_method->name() == vmSymbols::clone_name() && - sel_klass() == SystemDictionary::Object_klass() && + sel_klass == SystemDictionary::Object_klass() && resolved_klass->is_array_klass()) { // We need to change "protected" to "public". assert(flags.is_protected(), "clone not protected?"); @@ -558,9 +556,9 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, } // assert(extra_arg_result_or_null != NULL, "must be able to return extra argument"); - if (!Reflection::verify_field_access(ref_klass(), - resolved_klass(), - sel_klass(), + if (!Reflection::verify_field_access(ref_klass, + resolved_klass, + sel_klass, flags, true)) { ResourceMark rm(THREAD); @@ -586,22 +584,21 @@ methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code, // It appears to fail when applied to an invokeinterface call site. // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points. // resolve klass - KlassHandle resolved_klass; if (code == Bytecodes::_invokedynamic) { - resolved_klass = SystemDictionary::MethodHandle_klass(); + Klass* resolved_klass = SystemDictionary::MethodHandle_klass(); Symbol* method_name = vmSymbols::invoke_name(); Symbol* method_signature = pool->signature_ref_at(index); - KlassHandle current_klass(THREAD, pool->pool_holder()); + Klass* current_klass = pool->pool_holder(); LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); return resolve_method(link_info, code, THREAD); } LinkInfo link_info(pool, index, methodHandle(), CHECK_NULL); - resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); if (pool->has_preresolution() - || (resolved_klass() == SystemDictionary::MethodHandle_klass() && - MethodHandles::is_signature_polymorphic_name(resolved_klass(), link_info.name()))) { + || (resolved_klass == SystemDictionary::MethodHandle_klass() && + MethodHandles::is_signature_polymorphic_name(resolved_klass, link_info.name()))) { Method* result = ConstantPool::method_at_if_loaded(pool, index); if (result != NULL) { return methodHandle(THREAD, result); @@ -652,8 +649,8 @@ void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info, } void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig, - KlassHandle current_klass, - KlassHandle sel_klass, TRAPS) { + Klass* current_klass, + Klass* sel_klass, TRAPS) { Handle ref_loader(THREAD, current_klass->class_loader()); Handle sel_loader(THREAD, sel_klass->class_loader()); @@ -686,14 +683,14 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS) { Handle nested_exception; - KlassHandle resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); // 1. For invokevirtual, cannot call an interface method if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", - resolved_klass()->external_name()); + resolved_klass->external_name()); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -727,21 +724,21 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, if (resolved_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, link_info.name(), link_info.signature()), nested_exception, NULL); } - // 6. access checks, access checking may be turned off when calling from within the VM. - KlassHandle current_klass = link_info.current_klass(); + // 5. access checks, access checking may be turned off when calling from within the VM. + Klass* current_klass = link_info.current_klass(); if (link_info.check_access()) { - assert(current_klass.not_null() , "current_klass should not be null"); + assert(current_klass != NULL , "current_klass should not be null"); // check if method can be accessed by the referring class check_method_accessability(current_klass, resolved_klass, - KlassHandle(THREAD, resolved_method->method_holder()), + resolved_method->method_holder(), resolved_method, CHECK_NULL); @@ -753,8 +750,8 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, } static void trace_method_resolution(const char* prefix, - KlassHandle klass, - KlassHandle resolved_klass, + Klass* klass, + Klass* resolved_klass, const methodHandle& method, bool logitables, int index = -1) { @@ -768,9 +765,9 @@ static void trace_method_resolution(const char* prefix, } st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", prefix, - (klass.is_null() ? "" : klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), + (klass == NULL ? "" : klass->internal_name()), + (resolved_klass == NULL ? "" : resolved_klass->internal_name()), + Method::name_and_sig_as_C_string(resolved_klass, method->name(), method->signature()), method->method_holder()->internal_name()); @@ -785,13 +782,13 @@ static void trace_method_resolution(const char* prefix, // Do linktime resolution of a method in the interface within the context of the specied bytecode. methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS) { - KlassHandle resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); // check if klass is interface if (!resolved_klass->is_interface()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); + jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass->external_name()); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -816,21 +813,21 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B // no method found ResourceMark rm(THREAD); THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, link_info.name(), link_info.signature())); } if (link_info.check_access()) { // JDK8 adds non-public interface methods, and accessability check requirement - KlassHandle current_klass = link_info.current_klass(); + Klass* current_klass = link_info.current_klass(); - assert(current_klass.not_null() , "current_klass should not be null"); + assert(current_klass != NULL , "current_klass should not be null"); // check if method can be accessed by the referring class check_method_accessability(current_klass, resolved_klass, - KlassHandle(THREAD, resolved_method->method_holder()), + resolved_method->method_holder(), resolved_method, CHECK_NULL); @@ -841,7 +838,7 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, resolved_method->name(), resolved_method->signature())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -850,12 +847,12 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B ResourceMark rm(THREAD); char buf[200]; - KlassHandle current_klass = link_info.current_klass(); + Klass* current_klass = link_info.current_klass(); jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s, caller-class:%s", - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, resolved_method->name(), resolved_method->signature()), - (current_klass.is_null() ? "" : current_klass->internal_name())); + (current_klass == NULL ? "" : current_klass->internal_name())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -873,14 +870,14 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B //------------------------------------------------------------------------------------------------------------------------ // Field resolution -void LinkResolver::check_field_accessability(KlassHandle ref_klass, - KlassHandle resolved_klass, - KlassHandle sel_klass, +void LinkResolver::check_field_accessability(Klass* ref_klass, + Klass* resolved_klass, + Klass* sel_klass, const fieldDescriptor& fd, TRAPS) { - if (!Reflection::verify_field_access(ref_klass(), - resolved_klass(), - sel_klass(), + if (!Reflection::verify_field_access(ref_klass, + resolved_klass, + sel_klass, fd.access_flags(), true)) { ResourceMark rm(THREAD); @@ -913,19 +910,19 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield); // Check if there's a resolved klass containing the field - KlassHandle resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); Symbol* field = link_info.name(); Symbol* sig = link_info.signature(); - if (resolved_klass.is_null()) { + if (resolved_klass == NULL) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); } // Resolve instance field - KlassHandle sel_klass(THREAD, resolved_klass->find_field(field, sig, &fd)); + Klass* sel_klass = resolved_klass->find_field(field, sig, &fd); // check if field exists; i.e., if a klass containing the field def has been selected - if (sel_klass.is_null()) { + if (sel_klass == NULL) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); } @@ -935,14 +932,14 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, return; // check access - KlassHandle current_klass = link_info.current_klass(); + Klass* current_klass = link_info.current_klass(); check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK); // check for errors if (is_static != fd.is_static()) { ResourceMark rm(THREAD); char msg[200]; - jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string()); + jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string()); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); } @@ -954,10 +951,10 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, ResourceMark rm(THREAD); stringStream ss; - if (sel_klass() != current_klass()) { + if (sel_klass != current_klass) { ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", - is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string(), - current_klass()->external_name()); + is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), + current_klass->external_name()); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); } @@ -973,7 +970,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, if (is_initialized_static_final_update || is_initialized_instance_final_update) { ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ", - is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string(), + is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), m()->name()->as_C_string(), is_static ? "" : ""); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); @@ -991,7 +988,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, sel_klass->initialize(CHECK); } - if (sel_klass() != current_klass()) { + if (sel_klass != current_klass) { check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK); } @@ -1017,7 +1014,7 @@ void LinkResolver::resolve_static_call(CallInfo& result, methodHandle resolved_method = linktime_resolve_static_method(link_info, CHECK); // The resolved class can change as a result of this resolution. - KlassHandle resolved_klass(THREAD, resolved_method->method_holder()); + Klass* resolved_klass = resolved_method->method_holder(); // Initialize klass (this should only happen if everything is ok) if (initialize_class && resolved_klass->should_be_initialized()) { @@ -1036,7 +1033,7 @@ void LinkResolver::resolve_static_call(CallInfo& result, // throws linktime exceptions methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_info, TRAPS) { - KlassHandle resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); methodHandle resolved_method; if (!resolved_klass->is_interface()) { resolved_method = resolve_method(link_info, Bytecodes::_invokestatic, CHECK_NULL); @@ -1049,7 +1046,7 @@ methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_i if (!resolved_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(), + jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass, resolved_method->name(), resolved_method->signature())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -1078,7 +1075,7 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ // superclass.method, which can also resolve to a default method // and the selected method is recalculated relative to the direct superclass // superinterface.method, which explicitly does not check shadowing - KlassHandle resolved_klass = link_info.resolved_klass(); + Klass* resolved_klass = link_info.resolved_klass(); methodHandle resolved_method; if (!resolved_klass->is_interface()) { @@ -1089,7 +1086,7 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ // check if method name is , that it is found in same klass as static type if (resolved_method->name() == vmSymbols::object_initializer_name() && - resolved_method->method_holder() != resolved_klass()) { + resolved_method->method_holder() != resolved_klass) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, @@ -1103,24 +1100,25 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ } // check if invokespecial's interface method reference is in an indirect superinterface - KlassHandle current_klass = link_info.current_klass(); - if (!current_klass.is_null() && resolved_klass->is_interface()) { - Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ? - current_klass() : - InstanceKlass::cast(current_klass())->host_klass(); + Klass* current_klass = link_info.current_klass(); + if (current_klass != NULL && resolved_klass->is_interface()) { + InstanceKlass* ck = InstanceKlass::cast(current_klass); + InstanceKlass *klass_to_check = !ck->is_anonymous() ? + ck : + InstanceKlass::cast(ck->host_klass()); // Disable verification for the dynamically-generated reflection bytecodes. bool is_reflect = klass_to_check->is_subclass_of( SystemDictionary::reflect_MagicAccessorImpl_klass()); if (!is_reflect && - !InstanceKlass::cast(klass_to_check)->is_same_or_direct_interface(resolved_klass())) { + !klass_to_check->is_same_or_direct_interface(resolved_klass)) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Interface method reference: %s, is in an indirect superinterface of %s", - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), + Method::name_and_sig_as_C_string(resolved_klass, + resolved_method->name(), + resolved_method->signature()), current_klass->external_name()); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -1132,7 +1130,7 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ char buf[200]; jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, resolved_method->name(), resolved_method->signature())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -1149,8 +1147,8 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ // throws runtime exceptions void LinkResolver::runtime_resolve_special_method(CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, - KlassHandle current_klass, + Klass* resolved_klass, + Klass* current_klass, bool check_access, TRAPS) { // resolved method is selected method unless we have an old-style lookup @@ -1160,33 +1158,29 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle sel_method(THREAD, resolved_method()); // check if this is an old-style super call and do a new lookup if so - { KlassHandle method_klass = KlassHandle(THREAD, - resolved_method->method_holder()); - - if (check_access && - // a) check if ACC_SUPER flag is set for the current class - (current_klass->is_super() || !AllowNonVirtualCalls) && - // b) check if the class of the resolved_klass is a superclass - // (not supertype in order to exclude interface classes) of the current class. - // This check is not performed for super.invoke for interface methods - // in super interfaces. - current_klass->is_subclass_of(resolved_klass()) && - current_klass() != resolved_klass() && - // c) check if the method is not - resolved_method->name() != vmSymbols::object_initializer_name()) { - // Lookup super method - KlassHandle super_klass(THREAD, current_klass->super()); - sel_method = lookup_instance_method_in_klasses(super_klass, - resolved_method->name(), - resolved_method->signature(), CHECK); - // check if found - if (sel_method.is_null()) { - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature())); - } + if (check_access && + // a) check if ACC_SUPER flag is set for the current class + (current_klass->is_super() || !AllowNonVirtualCalls) && + // b) check if the class of the resolved_klass is a superclass + // (not supertype in order to exclude interface classes) of the current class. + // This check is not performed for super.invoke for interface methods + // in super interfaces. + current_klass->is_subclass_of(resolved_klass) && + current_klass != resolved_klass && + // c) check if the method is not + resolved_method->name() != vmSymbols::object_initializer_name()) { + // Lookup super method + Klass* super_klass = current_klass->super(); + sel_method = lookup_instance_method_in_klasses(super_klass, + resolved_method->name(), + resolved_method->signature(), CHECK); + // check if found + if (sel_method.is_null()) { + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), + Method::name_and_sig_as_C_string(resolved_klass, + resolved_method->name(), + resolved_method->signature())); } } @@ -1194,9 +1188,9 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, if (sel_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature())); + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, + resolved_method->name(), + resolved_method->signature())); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -1204,7 +1198,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, if (sel_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, sel_method->name(), sel_method->signature())); } @@ -1218,7 +1212,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, result.set_static(resolved_klass, sel_method, CHECK); } -void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, +void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, Klass* receiver_klass, const LinkInfo& link_info, bool check_null_and_abstract, TRAPS) { methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK); @@ -1238,18 +1232,18 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_ assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); // check if private interface method - KlassHandle resolved_klass = link_info.resolved_klass(); - KlassHandle current_klass = link_info.current_klass(); + Klass* resolved_klass = link_info.resolved_klass(); + Klass* current_klass = link_info.current_klass(); // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method if (resolved_klass->is_interface() && resolved_method->is_private()) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s", - Method::name_and_sig_as_C_string(resolved_klass(), + Method::name_and_sig_as_C_string(resolved_klass, resolved_method->name(), resolved_method->signature()), - (current_klass.is_null() ? "" : current_klass->internal_name())); + (current_klass == NULL ? "" : current_klass->internal_name())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -1257,9 +1251,9 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_ if (resolved_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature())); + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, + resolved_method->name(), + resolved_method->signature())); THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -1274,9 +1268,9 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_ // throws runtime exceptions void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, + Klass* resolved_klass, Handle recv, - KlassHandle recv_klass, + Klass* recv_klass, bool check_null_and_abstract, TRAPS) { @@ -1325,18 +1319,18 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, if (selected_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature())); + Method::name_and_sig_as_C_string(resolved_klass, + resolved_method->name(), + resolved_method->signature())); } // check if abstract if (check_null_and_abstract && selected_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - selected_method->name(), - selected_method->signature())); + Method::name_and_sig_as_C_string(resolved_klass, + selected_method->name(), + selected_method->signature())); } if (log_develop_is_enabled(Trace, vtables)) { @@ -1348,7 +1342,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); } -void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, +void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass, const LinkInfo& link_info, bool check_null_and_abstract, TRAPS) { // throws linktime exceptions @@ -1370,9 +1364,9 @@ methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& lin // throws runtime exceptions void LinkResolver::runtime_resolve_interface_method(CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, + Klass* resolved_klass, Handle recv, - KlassHandle recv_klass, + Klass* recv_klass, bool check_null_and_abstract, TRAPS) { // check if receiver exists if (check_null_and_abstract && recv.is_null()) { @@ -1380,12 +1374,12 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, } // check if receiver klass implements the resolved interface - if (!recv_klass->is_subtype_of(resolved_klass())) { + if (!recv_klass->is_subtype_of(resolved_klass)) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", - recv_klass()->external_name(), - resolved_klass()->external_name()); + recv_klass->external_name(), + resolved_klass->external_name()); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -1405,7 +1399,7 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, if (sel_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(recv_klass(), + Method::name_and_sig_as_C_string(recv_klass, resolved_method->name(), resolved_method->signature())); } @@ -1414,7 +1408,7 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, if (!sel_method->is_public()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), - Method::name_and_sig_as_C_string(recv_klass(), + Method::name_and_sig_as_C_string(recv_klass, sel_method->name(), sel_method->signature())); } @@ -1422,9 +1416,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, if (check_null_and_abstract && sel_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(recv_klass(), - sel_method->name(), - sel_method->signature())); + Method::name_and_sig_as_C_string(recv_klass, + sel_method->name(), + sel_method->signature())); } if (log_develop_is_enabled(Trace, itables)) { @@ -1468,7 +1462,7 @@ methodHandle LinkResolver::linktime_resolve_virtual_method_or_null( } methodHandle LinkResolver::resolve_virtual_call_or_null( - KlassHandle receiver_klass, + Klass* receiver_klass, const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; @@ -1481,7 +1475,7 @@ methodHandle LinkResolver::resolve_virtual_call_or_null( } methodHandle LinkResolver::resolve_interface_call_or_null( - KlassHandle receiver_klass, + Klass* receiver_klass, const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; @@ -1493,7 +1487,7 @@ methodHandle LinkResolver::resolve_interface_call_or_null( return info.selected_method(); } -int LinkResolver::resolve_virtual_vtable_index(KlassHandle receiver_klass, +int LinkResolver::resolve_virtual_vtable_index(Klass* receiver_klass, const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; @@ -1548,7 +1542,7 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantP void LinkResolver::resolve_invoke(CallInfo& result, Handle& recv, const methodHandle& attached_method, Bytecodes::Code byte, TRAPS) { - KlassHandle defc = attached_method->method_holder(); + Klass* defc = attached_method->method_holder(); Symbol* name = attached_method->name(); Symbol* type = attached_method->signature(); LinkInfo link_info(defc, name, type); @@ -1589,14 +1583,14 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, TRAPS) { LinkInfo link_info(pool, index, CHECK); - KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); + Klass* recvrKlass = recv.is_null() ? (Klass*)NULL : recv->klass(); resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); } void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, CHECK); - KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); + Klass* recvrKlass = recv.is_null() ? (Klass*)NULL : recv->klass(); resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); } @@ -1616,9 +1610,9 @@ void LinkResolver::resolve_handle_call(CallInfo& result, const LinkInfo& link_info, TRAPS) { // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar - KlassHandle resolved_klass = link_info.resolved_klass(); - assert(resolved_klass() == SystemDictionary::MethodHandle_klass() || - resolved_klass() == SystemDictionary::VarHandle_klass(), ""); + Klass* resolved_klass = link_info.resolved_klass(); + assert(resolved_klass == SystemDictionary::MethodHandle_klass() || + resolved_klass == SystemDictionary::VarHandle_klass(), ""); assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); Handle resolved_appendix; Handle resolved_method_type; @@ -1655,7 +1649,7 @@ static void wrap_invokedynamic_exception(TRAPS) { void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { Symbol* method_name = pool->name_ref_at(index); Symbol* method_signature = pool->signature_ref_at(index); - KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder()); + Klass* current_klass = pool->pool_holder(); // Resolve the bootstrap specifier (BSM + optional arguments). Handle bootstrap_specifier; @@ -1693,7 +1687,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHan void LinkResolver::resolve_dynamic_call(CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, + Klass* current_klass, TRAPS) { // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) // The appendix argument is likely to be a freshly-created CallSite. diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index 1c02898b42d..05cd706fd98 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,8 +47,8 @@ class CallInfo : public StackObj { unknown_kind = -1 }; private: - KlassHandle _resolved_klass; // static receiver klass, resolved from a symbolic reference - KlassHandle _selected_klass; // dynamic receiver class (same as static, or subklass) + Klass* _resolved_klass; // static receiver klass, resolved from a symbolic reference + Klass* _selected_klass; // dynamic receiver class (same as static, or subklass) methodHandle _resolved_method; // static target method methodHandle _selected_method; // dynamic (actual) target method CallKind _call_kind; // kind of call (static(=bytecode static/special + @@ -57,21 +57,21 @@ class CallInfo : public StackObj { Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) - void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS); - void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, + void set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS); + void set_interface(Klass* resolved_klass, Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, int itable_index, TRAPS); - void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, + void set_virtual(Klass* resolved_klass, Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, int vtable_index, TRAPS); void set_handle(const methodHandle& resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); - void set_handle(KlassHandle resolved_klass, + void set_handle(Klass* resolved_klass, const methodHandle& resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); - void set_common(KlassHandle resolved_klass, KlassHandle selected_klass, + void set_common(Klass* resolved_klass, Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, CallKind kind, @@ -91,8 +91,8 @@ class CallInfo : public StackObj { // does not queue the method for compilation CallInfo(Method* resolved_method, Klass* resolved_klass = NULL); - KlassHandle resolved_klass() const { return _resolved_klass; } - KlassHandle selected_klass() const { return _selected_klass; } + Klass* resolved_klass() const { return _resolved_klass; } + Klass* selected_klass() const { return _selected_klass; } methodHandle resolved_method() const { return _resolved_method; } methodHandle selected_method() const { return _selected_method; } Handle resolved_appendix() const { return _resolved_appendix; } @@ -135,8 +135,8 @@ class CallInfo : public StackObj { class LinkInfo : public StackObj { Symbol* _name; // extracted from JVM_CONSTANT_NameAndType Symbol* _signature; - KlassHandle _resolved_klass; // class that the constant pool entry points to - KlassHandle _current_klass; // class that owns the constant pool + Klass* _resolved_klass; // class that the constant pool entry points to + Klass* _current_klass; // class that owns the constant pool methodHandle _current_method; // sending method bool _check_access; constantTag _tag; @@ -151,14 +151,14 @@ class LinkInfo : public StackObj { LinkInfo(const constantPoolHandle& pool, int index, TRAPS); // Condensed information from other call sites within the vm. - LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, KlassHandle current_klass, + LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, Klass* current_klass, AccessCheck check_access = needs_access_check, constantTag tag = JVM_CONSTANT_Invalid) : _resolved_klass(resolved_klass), - _name(name), _signature(signature), _current_klass(current_klass), _current_method(NULL), + _name(name), _signature(signature), _current_klass(current_klass), _current_method(methodHandle()), _check_access(check_access == needs_access_check), _tag(tag) {} - LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, methodHandle current_method, + LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, methodHandle current_method, AccessCheck check_access = needs_access_check, constantTag tag = JVM_CONSTANT_Invalid) : _resolved_klass(resolved_klass), @@ -166,16 +166,16 @@ class LinkInfo : public StackObj { _check_access(check_access == needs_access_check), _tag(tag) {} // Case where we just find the method and don't check access against the current class - LinkInfo(KlassHandle resolved_klass, Symbol*name, Symbol* signature) : + LinkInfo(Klass* resolved_klass, Symbol*name, Symbol* signature) : _resolved_klass(resolved_klass), - _name(name), _signature(signature), _current_klass(NULL), _current_method(NULL), + _name(name), _signature(signature), _current_klass(NULL), _current_method(methodHandle()), _check_access(false), _tag(JVM_CONSTANT_Invalid) {} // accessors Symbol* name() const { return _name; } Symbol* signature() const { return _signature; } - KlassHandle resolved_klass() const { return _resolved_klass; } - KlassHandle current_klass() const { return _current_klass; } + Klass* resolved_klass() const { return _resolved_klass; } + Klass* current_klass() const { return _current_klass; } methodHandle current_method() const { return _current_method; } constantTag tag() const { return _tag; } bool check_access() const { return _check_access; } @@ -206,7 +206,7 @@ class LinkResolver: AllStatic { JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod() // Not Linktime so doesn't take LinkInfo static methodHandle lookup_instance_method_in_klasses ( - KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); + Klass* klass, Symbol* name, Symbol* signature, TRAPS); JVMCI_ONLY(private:) // Similar loader constraint checking functions that throw @@ -215,8 +215,8 @@ class LinkResolver: AllStatic { const methodHandle& resolved_method, const char* method_type, TRAPS); static void check_field_loader_constraints(Symbol* field, Symbol* sig, - KlassHandle current_klass, - KlassHandle sel_klass, TRAPS); + Klass* current_klass, + Klass* sel_klass, TRAPS); static methodHandle resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS); static methodHandle resolve_method (const LinkInfo& link_info, Bytecodes::Code code, TRAPS); @@ -228,29 +228,29 @@ class LinkResolver: AllStatic { static void runtime_resolve_special_method (CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, - KlassHandle current_klass, + Klass* resolved_klass, + Klass* current_klass, bool check_access, TRAPS); static void runtime_resolve_virtual_method (CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, + Klass* resolved_klass, Handle recv, - KlassHandle recv_klass, + Klass* recv_klass, bool check_null_and_abstract, TRAPS); static void runtime_resolve_interface_method (CallInfo& result, const methodHandle& resolved_method, - KlassHandle resolved_klass, + Klass* resolved_klass, Handle recv, - KlassHandle recv_klass, + Klass* recv_klass, bool check_null_and_abstract, TRAPS); - static void check_field_accessability(KlassHandle ref_klass, - KlassHandle resolved_klass, - KlassHandle sel_klass, + static void check_field_accessability(Klass* ref_klass, + Klass* resolved_klass, + Klass* sel_klass, const fieldDescriptor& fd, TRAPS); - static void check_method_accessability(KlassHandle ref_klass, - KlassHandle resolved_klass, - KlassHandle sel_klass, + static void check_method_accessability(Klass* ref_klass, + Klass* resolved_klass, + Klass* sel_klass, const methodHandle& sel_method, TRAPS); // runtime resolving from constant pool @@ -268,7 +268,7 @@ class LinkResolver: AllStatic { const constantPoolHandle& pool, int index, TRAPS); public: // constant pool resolving - static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS); + static void check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS); // static resolving calls (will not run any Java code); // used only from Bytecode_invoke::static_target @@ -291,31 +291,31 @@ class LinkResolver: AllStatic { static void resolve_special_call (CallInfo& result, const LinkInfo& link_info, TRAPS); - static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, + static void resolve_virtual_call (CallInfo& result, Handle recv, Klass* recv_klass, const LinkInfo& link_info, bool check_null_and_abstract, TRAPS); - static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, + static void resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass, const LinkInfo& link_info, bool check_null_and_abstract, TRAPS); static void resolve_handle_call (CallInfo& result, const LinkInfo& link_info, TRAPS); static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, TRAPS); + Klass* current_klass, TRAPS); // same as above for compile-time resolution; but returns null handle instead of throwing // an exception on error also, does not initialize klass (i.e., no side effects) - static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, + static methodHandle resolve_virtual_call_or_null (Klass* receiver_klass, const LinkInfo& link_info); - static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, + static methodHandle resolve_interface_call_or_null(Klass* receiver_klass, const LinkInfo& link_info); static methodHandle resolve_static_call_or_null (const LinkInfo& link_info); static methodHandle resolve_special_call_or_null (const LinkInfo& link_info); - static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method); + static int vtable_index_of_interface_method(Klass* klass, const methodHandle& resolved_method); // same as above for compile-time resolution; returns vtable_index if current_klass if linked - static int resolve_virtual_vtable_index (KlassHandle receiver_klass, + static int resolve_virtual_vtable_index (Klass* receiver_klass, const LinkInfo& link_info); // static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful) diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index 8158776e2c9..397f48120ec 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -544,16 +544,16 @@ void Rewriter::rewrite_bytecodes(TRAPS) { patch_invokedynamic_bytecodes(); } -void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { +void Rewriter::rewrite(InstanceKlass* klass, TRAPS) { if (!DumpSharedSpaces) { - assert(!MetaspaceShared::is_in_shared_space(klass()), "archive methods must not be rewritten at run time"); + assert(!MetaspaceShared::is_in_shared_space(klass), "archive methods must not be rewritten at run time"); } ResourceMark rm(THREAD); Rewriter rw(klass, klass->constants(), klass->methods(), CHECK); // (That's all, folks.) } -Rewriter::Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array* methods, TRAPS) +Rewriter::Rewriter(InstanceKlass* klass, const constantPoolHandle& cpool, Array* methods, TRAPS) : _klass(klass), _pool(cpool), _methods(methods), diff --git a/hotspot/src/share/vm/interpreter/rewriter.hpp b/hotspot/src/share/vm/interpreter/rewriter.hpp index 68658537b4e..16635f41a0c 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.hpp +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ class Rewriter: public StackObj { private: - instanceKlassHandle _klass; + InstanceKlass* _klass; constantPoolHandle _pool; Array* _methods; GrowableArray _cp_map; @@ -188,7 +188,7 @@ class Rewriter: public StackObj { } // All the work goes in here: - Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array* methods, TRAPS); + Rewriter(InstanceKlass* klass, const constantPoolHandle& cpool, Array* methods, TRAPS); void compute_index_maps(); void make_constant_pool_cache(TRAPS); @@ -211,7 +211,7 @@ class Rewriter: public StackObj { static methodHandle rewrite_jsrs(methodHandle m, TRAPS); public: // Driver routine: - static void rewrite(instanceKlassHandle klass, TRAPS); + static void rewrite(InstanceKlass* klass, TRAPS); }; #endif // SHARE_VM_INTERPRETER_REWRITER_HPP diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index cee5e2cecd3..f382c5f3d09 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -77,8 +77,8 @@ oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) { return NULL; } -oop CompilerToVM::get_jvmci_type(KlassHandle klass, TRAPS) { - if (klass() != NULL) { +oop CompilerToVM::get_jvmci_type(Klass* klass, TRAPS) { + if (klass != NULL) { JavaValue result(T_OBJECT); JavaCallArguments args; args.push_oop(Handle(THREAD, klass->java_mirror())); @@ -678,7 +678,7 @@ C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle) } C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed)) - KlassHandle klass; + Klass* klass = NULL; oop base_object = JNIHandles::resolve(base); jlong base_address = 0; if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) { @@ -703,7 +703,7 @@ C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlon THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false")); } - assert (klass.is_null() || klass->is_klass(), "invalid read"); + assert (klass == NULL || klass->is_klass(), "invalid read"); oop result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL); return JNIHandles::make_local(THREAD, result); } @@ -711,7 +711,7 @@ C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlon C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method)) ResourceMark rm; methodHandle method = CompilerToVM::asMethod(jvmci_method); - KlassHandle holder = CompilerToVM::asKlass(jvmci_type); + Klass* holder = CompilerToVM::asKlass(jvmci_type); if (holder->is_interface()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name())); } @@ -719,7 +719,7 @@ C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci methodHandle ucm; { MutexLocker locker(Compile_lock); - ucm = Dependencies::find_unique_concrete_method(holder(), method()); + ucm = Dependencies::find_unique_concrete_method(holder, method()); } oop result = CompilerToVM::get_jvmci_method(ucm, CHECK_NULL); return JNIHandles::make_local(THREAD, result); @@ -848,15 +848,15 @@ C2V_END C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool); - KlassHandle loading_klass(cp->pool_holder()); + Klass* loading_klass = cp->pool_holder(); bool is_accessible = false; - KlassHandle klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass); + Klass* klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass); Symbol* symbol = NULL; - if (klass.is_null()) { + if (klass == NULL) { symbol = cp->klass_name_at(index); } oop result_oop; - if (!klass.is_null()) { + if (klass != NULL) { result_oop = CompilerToVM::get_jvmci_type(klass, CHECK_NULL); } else { Handle result = java_lang_String::create_from_symbol(symbol, CHECK_NULL); @@ -873,7 +873,7 @@ C2V_END C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool); - instanceKlassHandle pool_holder(cp->pool_holder()); + InstanceKlass* pool_holder = cp->pool_holder(); Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder); oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL); @@ -920,11 +920,11 @@ C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject C2V_END C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type)) - KlassHandle recv_klass = CompilerToVM::asKlass(receiver_jvmci_type); - KlassHandle caller_klass = CompilerToVM::asKlass(caller_jvmci_type); + Klass* recv_klass = CompilerToVM::asKlass(receiver_jvmci_type); + Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type); methodHandle method = CompilerToVM::asMethod(jvmci_method); - KlassHandle h_resolved (THREAD, method->method_holder()); + Klass* resolved = method->method_holder(); Symbol* h_name = method->name(); Symbol* h_signature = method->signature(); @@ -933,13 +933,13 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t return NULL; } - LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass); + LinkInfo link_info(resolved, h_name, h_signature, caller_klass); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. if (recv_klass->is_array_klass() || - InstanceKlass::cast(recv_klass())->is_linked() && !recv_klass->is_interface()) { - if (h_resolved->is_interface()) { + InstanceKlass::cast(recv_klass)->is_linked() && !recv_klass->is_interface()) { + if (resolved->is_interface()) { m = LinkResolver::resolve_interface_call_or_null(recv_klass, link_info); } else { m = LinkResolver::resolve_virtual_call_or_null(recv_klass, link_info); @@ -1482,12 +1482,12 @@ C2V_END C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool); - KlassHandle holder = cp->klass_ref_at(index, CHECK); + Klass* holder = cp->klass_ref_at(index, CHECK); Symbol* name = cp->name_ref_at(index); - if (MethodHandles::is_signature_polymorphic_name(holder(), name)) { + if (MethodHandles::is_signature_polymorphic_name(holder, name)) { CallInfo callInfo; LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokehandle, CHECK); - ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index)); + ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index)); cp_cache_entry->set_method_handle(cp, callInfo); } C2V_END diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index f5f325d193a..eb541f643ad 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -161,7 +161,7 @@ class CompilerToVM { static oop get_jvmci_method(const methodHandle& method, TRAPS); - static oop get_jvmci_type(KlassHandle klass, TRAPS); + static oop get_jvmci_type(Klass* klass, TRAPS); }; class JavaArgumentUnboxer : public SignatureIterator { diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp index 4c8afddf204..acc85159b24 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp @@ -65,9 +65,9 @@ JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter // ------------------------------------------------------------------ // Note: the logic of this method should mirror the logic of // constantPoolOopDesc::verify_constant_pool_resolve. -bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) { +bool JVMCIEnv::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) { if (accessing_klass->is_objArray_klass()) { - accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass(); + accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass(); } if (!accessing_klass->is_instance_klass()) { return true; @@ -75,21 +75,21 @@ bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandl if (resolved_klass->is_objArray_klass()) { // Find the element klass, if this is an array. - resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass(); + resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass(); } if (resolved_klass->is_instance_klass()) { Reflection::VerifyClassAccessResults result = - Reflection::verify_class_access(accessing_klass(), InstanceKlass::cast(resolved_klass()), true); + Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true); return result == Reflection::ACCESS_OK; } return true; } // ------------------------------------------------------------------ -KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass, - const constantPoolHandle& cpool, - Symbol* sym, - bool require_local) { +Klass* JVMCIEnv::get_klass_by_name_impl(Klass* accessing_klass, + const constantPoolHandle& cpool, + Symbol* sym, + bool require_local) { JVMCI_EXCEPTION_CONTEXT; // Now we need to check the SystemDictionary @@ -99,28 +99,26 @@ KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass, // Call recursive to keep scope of strippedsym. TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1, sym->utf8_length()-2, - CHECK_(KlassHandle())); + CHECK_NULL); return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local); } Handle loader(THREAD, (oop)NULL); Handle domain(THREAD, (oop)NULL); - if (!accessing_klass.is_null()) { + if (accessing_klass != NULL) { loader = Handle(THREAD, accessing_klass->class_loader()); domain = Handle(THREAD, accessing_klass->protection_domain()); } - KlassHandle found_klass; + Klass* found_klass = NULL; { ttyUnlocker ttyul; // release tty lock to avoid ordering problems MutexLocker ml(Compile_lock); - Klass* kls; if (!require_local) { - kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_(KlassHandle())); + found_klass = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_NULL); } else { - kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_(KlassHandle())); + found_klass = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_NULL); } - found_klass = KlassHandle(THREAD, kls); } // If we fail to find an array klass, look again for its element type. @@ -135,21 +133,21 @@ KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass, // Build it on the fly if the element class exists. TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1, sym->utf8_length()-1, - CHECK_(KlassHandle())); + CHECK_NULL); // Get element Klass recursively. - KlassHandle elem_klass = + Klass* elem_klass = get_klass_by_name_impl(accessing_klass, cpool, elem_sym, require_local); - if (!elem_klass.is_null()) { + if (elem_klass != NULL) { // Now make an array for it - return elem_klass->array_klass(CHECK_(KlassHandle())); + return elem_klass->array_klass(CHECK_NULL); } } - if (found_klass.is_null() && !cpool.is_null() && cpool->has_preresolution()) { + if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) { // Look inside the constant pool for pre-resolved class entries. for (int i = cpool->length() - 1; i >= 1; i--) { if (cpool->tag_at(i).is_klass()) { @@ -161,45 +159,45 @@ KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass, } } - return found_klass(); + return found_klass; } // ------------------------------------------------------------------ -KlassHandle JVMCIEnv::get_klass_by_name(KlassHandle accessing_klass, +Klass* JVMCIEnv::get_klass_by_name(Klass* accessing_klass, Symbol* klass_name, bool require_local) { ResourceMark rm; constantPoolHandle cpool; return get_klass_by_name_impl(accessing_klass, - cpool, - klass_name, - require_local); + cpool, + klass_name, + require_local); } // ------------------------------------------------------------------ // Implementation of get_klass_by_index. -KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, +Klass* JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, int index, bool& is_accessible, - KlassHandle accessor) { + Klass* accessor) { JVMCI_EXCEPTION_CONTEXT; - KlassHandle klass (THREAD, ConstantPool::klass_at_if_loaded(cpool, index)); + Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index); Symbol* klass_name = NULL; - if (klass.is_null()) { + if (klass == NULL) { klass_name = cpool->klass_name_at(index); } - if (klass.is_null()) { + if (klass == NULL) { // Not found in constant pool. Use the name to do the lookup. - KlassHandle k = get_klass_by_name_impl(accessor, - cpool, - klass_name, - false); + Klass* k = get_klass_by_name_impl(accessor, + cpool, + klass_name, + false); // Calculate accessibility the hard way. - if (k.is_null()) { + if (k == NULL) { is_accessible = false; } else if (k->class_loader() != accessor->class_loader() && - get_klass_by_name_impl(accessor, cpool, k->name(), true).is_null()) { + get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) { // Loaded only remotely. Not linked yet. is_accessible = false; } else { @@ -207,7 +205,7 @@ KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, is_accessible = check_klass_accessibility(accessor, k); } if (!is_accessible) { - return KlassHandle(); + return NULL; } return k; } @@ -219,13 +217,12 @@ KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, // ------------------------------------------------------------------ // Get a klass from the constant pool. -KlassHandle JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool, - int index, - bool& is_accessible, - KlassHandle accessor) { +Klass* JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool, + int index, + bool& is_accessible, + Klass* accessor) { ResourceMark rm; - KlassHandle result = get_klass_by_index_impl(cpool, index, is_accessible, accessor); - return result; + return get_klass_by_index_impl(cpool, index, is_accessible, accessor); } // ------------------------------------------------------------------ @@ -233,7 +230,7 @@ KlassHandle JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool, // // Implementation note: the results of field lookups are cached // in the accessor klass. -void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescriptor& field_desc, +void JVMCIEnv::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc, int index) { JVMCI_EXCEPTION_CONTEXT; @@ -251,9 +248,9 @@ void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescripto // Get the field's declared holder. int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; - KlassHandle declared_holder = get_klass_by_index(cpool, holder_index, - holder_is_accessible, - klass); + Klass* declared_holder = get_klass_by_index(cpool, holder_index, + holder_is_accessible, + klass); // The declared holder of this field may not have been loaded. // Bail out with partial field information. @@ -264,7 +261,7 @@ void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescripto // Perform the field lookup. Klass* canonical_holder = - InstanceKlass::cast(declared_holder())->find_field(name, signature, &field_desc); + InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc); if (canonical_holder == NULL) { return; } @@ -274,7 +271,7 @@ void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescripto // ------------------------------------------------------------------ // Get a field by index from a klass's constant pool. -void JVMCIEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor& fd, int index) { +void JVMCIEnv::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index) { ResourceMark rm; return get_field_by_index_impl(accessor, fd, index); } @@ -282,17 +279,17 @@ void JVMCIEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor& // ------------------------------------------------------------------ // Perform an appropriate method lookup based on accessor, holder, // name, signature, and bytecode. -methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor, - KlassHandle h_holder, - Symbol* name, - Symbol* sig, +methodHandle JVMCIEnv::lookup_method(InstanceKlass* accessor, + Klass* holder, + Symbol* name, + Symbol* sig, Bytecodes::Code bc, constantTag tag) { // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl(). - assert(check_klass_accessibility(h_accessor, h_holder), "holder not accessible"); + assert(check_klass_accessibility(accessor, holder), "holder not accessible"); methodHandle dest_method; - LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); + LinkInfo link_info(holder, name, sig, accessor, LinkInfo::needs_access_check, tag); switch (bc) { case Bytecodes::_invokestatic: dest_method = @@ -320,7 +317,7 @@ methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor, // ------------------------------------------------------------------ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, - instanceKlassHandle accessor) { + InstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index); bool is_resolved = !cpce->is_f1_null(); @@ -336,15 +333,15 @@ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; - KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); + Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); // Get the method's name and signature. Symbol* name_sym = cpool->name_ref_at(index); Symbol* sig_sym = cpool->signature_ref_at(index); if (cpool->has_preresolution() - || ((holder() == SystemDictionary::MethodHandle_klass() || holder() == SystemDictionary::VarHandle_klass()) && - MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) { + || ((holder == SystemDictionary::MethodHandle_klass() || holder == SystemDictionary::VarHandle_klass()) && + MethodHandles::is_signature_polymorphic_name(holder, name_sym))) { // Short-circuit lookups for JSR 292-related call sites. // That is, do not rely only on name-based lookups, because they may fail // if the names are not resolvable in the boot class loader (7056328). @@ -385,14 +382,14 @@ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, } // ------------------------------------------------------------------ -instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(KlassHandle method_holder) { +InstanceKlass* JVMCIEnv::get_instance_klass_for_declared_method_holder(Klass* method_holder) { // For the case of .clone(), the method holder can be an ArrayKlass* // instead of an InstanceKlass*. For that case simply pretend that the // declared holder is Object.clone since that's where the call will bottom out. if (method_holder->is_instance_klass()) { - return instanceKlassHandle(method_holder()); + return InstanceKlass::cast(method_holder); } else if (method_holder->is_array_klass()) { - return instanceKlassHandle(SystemDictionary::Object_klass()); + return SystemDictionary::Object_klass(); } else { ShouldNotReachHere(); } @@ -403,7 +400,7 @@ instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(Klas // ------------------------------------------------------------------ methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, - instanceKlassHandle accessor) { + InstanceKlass* accessor) { ResourceMark rm; return get_method_by_index_impl(cpool, index, bc, accessor); } diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp index 1154a95d567..b28eb79bf8e 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -79,20 +79,18 @@ public: // The CI treats a klass as loaded if it is consistently defined in // another loader, even if it hasn't yet been loaded in all loaders // that could potentially see it via delegation. - static KlassHandle get_klass_by_name(KlassHandle accessing_klass, - Symbol* klass_name, - bool require_local); + static Klass* get_klass_by_name(Klass* accessing_klass, Symbol* klass_name, bool require_local); // Constant pool access. - static KlassHandle get_klass_by_index(const constantPoolHandle& cpool, - int klass_index, - bool& is_accessible, - KlassHandle loading_klass); - static void get_field_by_index(instanceKlassHandle loading_klass, fieldDescriptor& fd, - int field_index); + static Klass* get_klass_by_index(const constantPoolHandle& cpool, + int klass_index, + bool& is_accessible, + Klass* loading_klass); + static void get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd, + int field_index); static methodHandle get_method_by_index(const constantPoolHandle& cpool, - int method_index, Bytecodes::Code bc, - instanceKlassHandle loading_klass); + int method_index, Bytecodes::Code bc, + InstanceKlass* loading_klass); JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter); @@ -110,26 +108,26 @@ private: bool _jvmti_can_post_on_exceptions; // Implementation methods for loading and constant pool access. - static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass, + static Klass* get_klass_by_name_impl(Klass* accessing_klass, const constantPoolHandle& cpool, Symbol* klass_name, bool require_local); - static KlassHandle get_klass_by_index_impl(const constantPoolHandle& cpool, + static Klass* get_klass_by_index_impl(const constantPoolHandle& cpool, int klass_index, bool& is_accessible, - KlassHandle loading_klass); - static void get_field_by_index_impl(instanceKlassHandle loading_klass, fieldDescriptor& fd, + Klass* loading_klass); + static void get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd, int field_index); static methodHandle get_method_by_index_impl(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, - instanceKlassHandle loading_klass); + InstanceKlass* loading_klass); // Helper methods - static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass); - static methodHandle lookup_method(instanceKlassHandle accessor, - KlassHandle holder, - Symbol* name, - Symbol* sig, + static bool check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass); + static methodHandle lookup_method(InstanceKlass* accessor, + Klass* holder, + Symbol* name, + Symbol* sig, Bytecodes::Code bc, constantTag tag); @@ -180,7 +178,7 @@ public: // InstanceKlass*. This is needed since the holder of a method in // the bytecodes could be an array type. Basically this converts // array types into java/lang/Object and other types stay as they are. - static instanceKlassHandle get_instance_klass_for_declared_method_holder(KlassHandle klass); + static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass); }; #endif // SHARE_VM_JVMCI_JVMCIENV_HPP diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index d7a81cd78e8..bf7ec1dce9b 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -107,12 +107,12 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klas JRT_BLOCK; assert(klass->is_klass(), "not a class"); Handle holder(THREAD, klass->klass_holder()); // keep the klass alive - instanceKlassHandle h(thread, klass); - h->check_valid_for_instantiation(true, CHECK); + InstanceKlass* ik = InstanceKlass::cast(klass); + ik->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized - h->initialize(CHECK); + ik->initialize(CHECK); // allocate instance and return via TLS - oop obj = h->allocate_instance(CHECK); + oop obj = ik->allocate_instance(CHECK); thread->set_vm_result(obj); JRT_BLOCK_END; @@ -187,7 +187,7 @@ JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array(JavaThread* thread, oopDesc* ele JRT_END JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror)) - instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(type_mirror)); + InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(type_mirror)); if (klass == NULL) { ResourceMark rm(THREAD); @@ -641,7 +641,7 @@ JVM_END Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, const char* signature, JavaCallArguments* args, TRAPS) { TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_(Handle())); - KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, CHECK_(Handle())); + Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_(Handle())); TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_(Handle())); TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_(Handle())); JavaValue result(T_OBJECT); @@ -657,7 +657,7 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime"); JVMCIRuntime::initialize_well_known_classes(CHECK); // This should only be called in the context of the JVMCI class being initialized - instanceKlassHandle klass = InstanceKlass::cast(SystemDictionary::JVMCI_klass()); + InstanceKlass* klass = SystemDictionary::JVMCI_klass(); guarantee(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD), "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization"); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index eade3bb0408..d860fe4e325 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -460,9 +460,8 @@ void Universe::fixup_mirrors(TRAPS) { Klass* k = list->at(i); assert(k->is_klass(), "List should only hold classes"); EXCEPTION_MARK; - KlassHandle kh(THREAD, k); - java_lang_Class::fixup_mirror(kh, CATCH); -} + java_lang_Class::fixup_mirror(k, CATCH); + } delete java_lang_Class::fixup_mirror_list(); java_lang_Class::set_fixup_mirror_list(NULL); } @@ -506,7 +505,7 @@ void Universe::run_finalizers_on_exit() { log_trace(ref)("Callback to run finalizers on exit"); { PRESERVE_EXCEPTION_MARK; - KlassHandle finalizer_klass(THREAD, SystemDictionary::Finalizer_klass()); + Klass* finalizer_klass = SystemDictionary::Finalizer_klass(); JavaValue result(T_VOID); JavaCalls::call_static( &result, @@ -525,16 +524,15 @@ void Universe::run_finalizers_on_exit() { // 1) we specified true to initialize_vtable and // 2) this ran after gc was enabled // In case those ever change we use handles for oops -void Universe::reinitialize_vtable_of(KlassHandle k_h, TRAPS) { +void Universe::reinitialize_vtable_of(Klass* ko, TRAPS) { // init vtable of k and all subclasses - Klass* ko = k_h(); klassVtable* vt = ko->vtable(); if (vt) vt->initialize_vtable(false, CHECK); if (ko->is_instance_klass()) { - for (KlassHandle s_h(THREAD, ko->subklass()); - s_h() != NULL; - s_h = KlassHandle(THREAD, s_h()->next_sibling())) { - reinitialize_vtable_of(s_h, CHECK); + for (Klass* sk = ko->subklass(); + sk != NULL; + sk = sk->next_sibling()) { + reinitialize_vtable_of(sk, CHECK); } } } @@ -964,28 +962,26 @@ bool universe_post_init() { Interpreter::initialize(); // needed for interpreter entry points if (!UseSharedSpaces) { HandleMark hm(THREAD); - KlassHandle ok_h(THREAD, SystemDictionary::Object_klass()); - Universe::reinitialize_vtable_of(ok_h, CHECK_false); + Klass* ok = SystemDictionary::Object_klass(); + Universe::reinitialize_vtable_of(ok, CHECK_false); Universe::reinitialize_itables(CHECK_false); } } HandleMark hm(THREAD); - Klass* k; - instanceKlassHandle k_h; // Setup preallocated empty java.lang.Class array Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false); // Setup preallocated OutOfMemoryError errors - k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false); - k_h = instanceKlassHandle(THREAD, k); - Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false); + InstanceKlass* ik = InstanceKlass::cast(k); + Universe::_out_of_memory_error_java_heap = ik->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_metaspace = ik->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_class_metaspace = ik->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_array_size = ik->allocate_instance(CHECK_false); Universe::_out_of_memory_error_gc_overhead_limit = - k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false); + ik->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_realloc_objects = ik->allocate_instance(CHECK_false); // Setup preallocated cause message for delayed StackOverflowError if (StackReservedPages > 0) { @@ -1006,8 +1002,8 @@ bool universe_post_init() { vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false); bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false); if (!linked) { - tty->print_cr("Unable to link/verify VirtualMachineError class"); - return false; // initialization failed + tty->print_cr("Unable to link/verify VirtualMachineError class"); + return false; // initialization failed } Universe::_virtual_machine_error_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); @@ -1040,12 +1036,12 @@ bool universe_post_init() { // Setup the array of errors that have preallocated backtrace k = Universe::_out_of_memory_error_java_heap->klass(); assert(k->name() == vmSymbols::java_lang_OutOfMemoryError(), "should be out of memory error"); - k_h = instanceKlassHandle(THREAD, k); + ik = InstanceKlass::cast(k); int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0; - Universe::_preallocated_out_of_memory_error_array = oopFactory::new_objArray(k_h(), len, CHECK_false); + Universe::_preallocated_out_of_memory_error_array = oopFactory::new_objArray(ik, len, CHECK_false); for (int i=0; iallocate_instance(CHECK_false); + oop err = ik->allocate_instance(CHECK_false); Handle err_h = Handle(THREAD, err); java_lang_Throwable::allocate_backtrace(err_h, CHECK_false); Universe::preallocated_out_of_memory_errors()->obj_at_put(i, err_h()); diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 03d87637a1e..ed2ce0bcc8b 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -230,7 +230,7 @@ class Universe: AllStatic { static void initialize_basic_type_mirrors(TRAPS); static void fixup_mirrors(TRAPS); - static void reinitialize_vtable_of(KlassHandle h_k, TRAPS); + static void reinitialize_vtable_of(Klass* k, TRAPS); static void reinitialize_itables(TRAPS); static void compute_base_vtable_size(); // compute vtable size of class Object diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 782e2376f40..478d9264560 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -96,9 +96,9 @@ ArrayKlass::ArrayKlass(Symbol* name) : // Initialization of vtables and mirror object is done separatly from base_create_array_klass, // since a GC can happen. At this point all instance variables of the ArrayKlass must be setup. -void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module_entry, TRAPS) { +void ArrayKlass::complete_create_array_klass(ArrayKlass* k, Klass* super_klass, ModuleEntry* module_entry, TRAPS) { ResourceMark rm(THREAD); - k->initialize_supers(super_klass(), CHECK); + k->initialize_supers(super_klass, CHECK); k->vtable()->initialize_vtable(false, CHECK); // During bootstrapping, before java.base is defined, the module_entry may not be present yet. diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index c7dcd1f8657..9ff03a94868 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -115,7 +115,7 @@ class ArrayKlass: public Klass { void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); // Return a handle. - static void complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module, TRAPS); + static void complete_create_array_klass(ArrayKlass* k, Klass* super_klass, ModuleEntry* module, TRAPS); // jvm support diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 10effc78dba..bf556b28ba7 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -193,7 +193,7 @@ void ConstantPool::string_at_put(int which, int obj_index, oop str) { resolved_references()->obj_at_put(obj_index, str); } -void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k) { +void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, Klass* k) { ResourceMark rm; int line_number = -1; const char * source_file = NULL; @@ -208,7 +208,7 @@ void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, Kla } } } - if (k() != this_cp->pool_holder()) { + if (k != this_cp->pool_holder()) { // only print something if the classes are different if (source_file != NULL) { log_debug(class, resolve)("%s %s %s:%d", @@ -254,11 +254,10 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, Symbol* name = entry.get_symbol(); Handle loader (THREAD, this_cp->pool_holder()->class_loader()); Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain()); - Klass* kk = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD); - KlassHandle k (THREAD, kk); + Klass* k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD); if (!HAS_PENDING_EXCEPTION) { // preserve the resolved klass from unloading - mirror_handle = Handle(THREAD, kk->java_mirror()); + mirror_handle = Handle(THREAD, k->java_mirror()); // Do access check for klasses verify_constant_pool_resolve(this_cp, k, THREAD); } @@ -282,13 +281,13 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, // Make this class loader depend upon the class loader owning the class reference ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data(); - this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM + this_key->record_dependency(k, CHECK_NULL); // Can throw OOM // logging for class+resolve. if (log_is_enabled(Debug, class, resolve)){ trace_class_resolution(this_cp, k); } - this_cp->klass_at_put(which, k()); + this_cp->klass_at_put(which, k); entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); return entry.get_klass(); @@ -317,14 +316,13 @@ Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int w if (k != NULL) { // Make sure that resolving is legal EXCEPTION_MARK; - KlassHandle klass(THREAD, k); // return NULL if verification fails - verify_constant_pool_resolve(this_cp, klass, THREAD); + verify_constant_pool_resolve(this_cp, k, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return NULL; } - return klass(); + return k; } else { return k; } @@ -456,16 +454,15 @@ int ConstantPool::remap_instruction_operand_from_cache(int operand) { } -void ConstantPool::verify_constant_pool_resolve(const constantPoolHandle& this_cp, KlassHandle k, TRAPS) { +void ConstantPool::verify_constant_pool_resolve(const constantPoolHandle& this_cp, Klass* k, TRAPS) { if (k->is_instance_klass() || k->is_objArray_klass()) { - instanceKlassHandle holder (THREAD, this_cp->pool_holder()); - Klass* elem = k->is_instance_klass() ? k() : ObjArrayKlass::cast(k())->bottom_klass(); - KlassHandle element (THREAD, elem); + InstanceKlass* holder = this_cp->pool_holder(); + Klass* elem = k->is_instance_klass() ? k : ObjArrayKlass::cast(k)->bottom_klass(); // The element type could be a typeArray - we only need the access check if it is // an reference to another class - if (element->is_instance_klass()) { - LinkResolver::check_klass_accessability(holder, element, CHECK); + if (elem->is_instance_klass()) { + LinkResolver::check_klass_accessability(holder, elem, CHECK); } } } @@ -693,8 +690,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in callee_index, name->as_C_string(), signature->as_C_string()); } - Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL); - KlassHandle callee(THREAD, k); + Klass* callee = klass_at_impl(this_cp, callee_index, true, CHECK_NULL); // Check constant pool method consistency if ((callee->is_interface() && m_tag.is_method()) || @@ -710,7 +706,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } - KlassHandle klass(THREAD, this_cp->pool_holder()); + Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, THREAD); @@ -729,7 +725,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in index, this_cp->method_type_index_at(index), signature->as_C_string()); } - KlassHandle klass(THREAD, this_cp->pool_holder()); + Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { @@ -845,8 +841,7 @@ oop ConstantPool::string_at_impl(const constantPoolHandle& this_cp, int which, i } -bool ConstantPool::klass_name_at_matches(instanceKlassHandle k, - int which) { +bool ConstantPool::klass_name_at_matches(const InstanceKlass* k, int which) { // Names are interned, so we can compare Symbol*s directly Symbol* cp_name = klass_name_at(which); return (cp_name == k->name()); diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 9c5976f5695..5f169006617 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -693,7 +693,7 @@ class ConstantPool : public Metadata { } // Klass name matches name at offset - bool klass_name_at_matches(instanceKlassHandle k, int which); + bool klass_name_at_matches(const InstanceKlass* k, int which); // Sizing int length() const { return _length; } @@ -784,7 +784,7 @@ class ConstantPool : public Metadata { } // Performs the LinkResolver checks - static void verify_constant_pool_resolve(const constantPoolHandle& this_cp, KlassHandle klass, TRAPS); + static void verify_constant_pool_resolve(const constantPoolHandle& this_cp, Klass* klass, TRAPS); // Implementation of methods that needs an exposed 'this' pointer, in order to // handle GC while executing the method @@ -792,7 +792,7 @@ class ConstantPool : public Metadata { bool save_resolution_error, TRAPS); static oop string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS); - static void trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k); + static void trace_class_resolution(const constantPoolHandle& this_cp, Klass* k); // Resolve string constants (to prevent allocation during compilation) static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS); diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 04ae2104ffe..00438a6d543 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -101,14 +101,14 @@ bool ConstantPoolCacheEntry::init_flags_atomic(intptr_t flags) { // are updated, lest other processors see a non-zero bytecode but zero f1/f2. void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code, Bytecodes::Code put_code, - KlassHandle field_holder, + Klass* field_holder, int field_index, int field_offset, TosState field_type, bool is_final, bool is_volatile, Klass* root_klass) { - set_f1(field_holder()); + set_f1(field_holder); set_f2(field_offset); assert((field_index & field_index_mask) == field_index, "field index does not fit in low flag bits"); diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index e58d7c16ceb..89bf742fea6 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -217,7 +217,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { void set_field( // sets entry to resolved field state Bytecodes::Code get_code, // the bytecode used for reading the field Bytecodes::Code put_code, // the bytecode used for writing the field - KlassHandle field_holder, // the object/klass holding the field + Klass* field_holder, // the object/klass holding the field int orig_field_index, // the original field index in the field holder int field_offset, // the field offset in words in the field holder TosState field_type, // the (machine) field type diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp index c7d2d2743cf..b9a44c93d77 100644 --- a/hotspot/src/share/vm/oops/fieldStreams.hpp +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -107,14 +107,6 @@ class FieldStreamBase : public StackObj { init_generic_signature_start_slot(); assert(klass == field_holder(), ""); } - FieldStreamBase(instanceKlassHandle klass) { - _fields = klass->fields(); - _constants = klass->constants(); - _index = 0; - _limit = klass->java_fields_count(); - init_generic_signature_start_slot(); - assert(klass == field_holder(), ""); - } // accessors int index() const { return _index; } @@ -196,7 +188,7 @@ class FieldStreamBase : public StackObj { // Iterate over only the internal fields class JavaFieldStream : public FieldStreamBase { public: - JavaFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} + JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} int name_index() const { assert(!field()->is_internal(), "regular only"); @@ -245,7 +237,6 @@ class JavaFieldStream : public FieldStreamBase { class InternalFieldStream : public FieldStreamBase { public: InternalFieldStream(InstanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {} - InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {} }; @@ -253,7 +244,6 @@ class AllFieldStream : public FieldStreamBase { public: AllFieldStream(Array* fields, const constantPoolHandle& constants): FieldStreamBase(fields, constants) {} AllFieldStream(InstanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {} - AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {} }; #endif // SHARE_VM_OOPS_FIELDSTREAMS_HPP diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 336b1ea048c..bf53df7e68f 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -374,7 +374,7 @@ bool InstanceKlass::should_be_initialized() const { } klassItable* InstanceKlass::itable() const { - return new klassItable(instanceKlassHandle(this)); + return new klassItable(const_cast(this)); } void InstanceKlass::eager_initialize(Thread *thread) { @@ -392,8 +392,7 @@ void InstanceKlass::eager_initialize(Thread *thread) { if (!InstanceKlass::cast(super)->is_initialized()) return; // call body to expose the this pointer - instanceKlassHandle this_k(thread, this); - eager_initialize_impl(this_k); + eager_initialize_impl(this); } } @@ -432,7 +431,7 @@ void InstanceKlass::fence_and_clear_init_lock() { assert(!is_not_initialized(), "class must be initialized now"); } -void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) { +void InstanceKlass::eager_initialize_impl(InstanceKlass* this_k) { EXCEPTION_MARK; HandleMark hm(THREAD); Handle init_lock(THREAD, this_k->init_lock()); @@ -470,8 +469,7 @@ void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) { // Note: implementation moved to static method to expose the this pointer. void InstanceKlass::initialize(TRAPS) { if (this->should_be_initialized()) { - instanceKlassHandle this_k(THREAD, this); - initialize_impl(this_k, CHECK); + initialize_impl(this, CHECK); // Note: at this point the class may be initialized // OR it may be in the state of being initialized // in case of recursive initialization! @@ -482,7 +480,7 @@ void InstanceKlass::initialize(TRAPS) { bool InstanceKlass::verify_code( - instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) { + InstanceKlass* this_k, bool throw_verifyerror, TRAPS) { // 1) Verify the bytecodes Verifier::Mode mode = throw_verifyerror ? Verifier::ThrowException : Verifier::NoException; @@ -501,8 +499,7 @@ void InstanceKlass::unlink_class() { void InstanceKlass::link_class(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - instanceKlassHandle this_k(THREAD, this); - link_class_impl(this_k, true, CHECK); + link_class_impl(this, true, CHECK); } } @@ -511,14 +508,13 @@ void InstanceKlass::link_class(TRAPS) { bool InstanceKlass::link_class_or_fail(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - instanceKlassHandle this_k(THREAD, this); - link_class_impl(this_k, false, CHECK_false); + link_class_impl(this, false, CHECK_false); } return is_linked(); } bool InstanceKlass::link_class_impl( - instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) { + InstanceKlass* this_k, bool throw_verifyerror, TRAPS) { if (DumpSharedSpaces && this_k->is_in_error_state()) { // This is for CDS dumping phase only -- we use the in_error_state to indicate that // the class has failed verification. Throwing the NoClassDefFoundError here is just @@ -542,8 +538,8 @@ bool InstanceKlass::link_class_impl( JavaThread* jt = (JavaThread*)THREAD; // link super class before linking this class - instanceKlassHandle super(THREAD, this_k->super()); - if (super.not_null()) { + Klass* super = this_k->super(); + if (super != NULL) { if (super->is_interface()) { // check if super class is an interface ResourceMark rm(THREAD); Exceptions::fthrow( @@ -556,15 +552,16 @@ bool InstanceKlass::link_class_impl( return false; } - link_class_impl(super, throw_verifyerror, CHECK_false); + InstanceKlass* ik_super = InstanceKlass::cast(super); + link_class_impl(ik_super, throw_verifyerror, CHECK_false); } // link all interfaces implemented by this class before linking this class Array* interfaces = this_k->local_interfaces(); int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) { - instanceKlassHandle ih(THREAD, interfaces->at(index)); - link_class_impl(ih, throw_verifyerror, CHECK_false); + InstanceKlass* interk = InstanceKlass::cast(interfaces->at(index)); + link_class_impl(interk, throw_verifyerror, CHECK_false); } // in case the class is linked in the process of linking its superclasses @@ -642,7 +639,7 @@ bool InstanceKlass::link_class_impl( if (JvmtiExport::should_post_class_prepare()) { Thread *thread = THREAD; assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_prepare((JavaThread *) thread, this_k()); + JvmtiExport::post_class_prepare((JavaThread *) thread, this_k); } } } @@ -655,13 +652,12 @@ bool InstanceKlass::link_class_impl( // verification but before the first method of the class is executed. void InstanceKlass::rewrite_class(TRAPS) { assert(is_loaded(), "must be loaded"); - instanceKlassHandle this_k(THREAD, this); - if (this_k->is_rewritten()) { - assert(this_k()->is_shared(), "rewriting an unshared class?"); + if (is_rewritten()) { + assert(is_shared(), "rewriting an unshared class?"); return; } - Rewriter::rewrite(this_k, CHECK); - this_k->set_rewritten(); + Rewriter::rewrite(this, CHECK); + set_rewritten(); } // Now relocate and link method entry points after class is rewritten. @@ -678,7 +674,7 @@ void InstanceKlass::link_methods(TRAPS) { } // Eagerly initialize superinterfaces that declare default methods (concrete instance: any access) -void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) { +void InstanceKlass::initialize_super_interfaces(InstanceKlass* this_k, TRAPS) { assert (this_k->has_nonstatic_concrete_methods(), "caller should have checked this"); for (int i = 0; i < this_k->local_interfaces()->length(); ++i) { Klass* iface = this_k->local_interfaces()->at(i); @@ -698,14 +694,14 @@ void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAP } } -void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { +void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { HandleMark hm(THREAD); // Make sure klass is linked (verified) before initialization // A class could already be verified, since it has been reflected upon. this_k->link_class(CHECK); - DTRACE_CLASSINIT_PROBE(required, this_k(), -1); + DTRACE_CLASSINIT_PROBE(required, this_k, -1); bool wait = false; @@ -728,19 +724,19 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // Step 3 if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) { - DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k, -1,wait); return; } // Step 4 if (this_k->is_initialized()) { - DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k, -1,wait); return; } // Step 5 if (this_k->is_in_error_state()) { - DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k, -1,wait); ResourceMark rm(THREAD); const char* desc = "Could not initialize class "; const char* className = this_k->external_name(); @@ -786,7 +782,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { this_k->set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; } - DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k, -1,wait); THROW_OOP(e()); } } @@ -799,7 +795,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { { assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); JavaThread* jt = (JavaThread*)THREAD; - DTRACE_CLASSINIT_PROBE_WAIT(clinit, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(clinit, this_k, -1,wait); // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer(). PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), @@ -833,7 +829,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError JvmtiExport::clear_detected_exception((JavaThread*)THREAD); } - DTRACE_CLASSINIT_PROBE_WAIT(error, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(error, this_k, -1,wait); if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { @@ -843,17 +839,16 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { &args); } } - DTRACE_CLASSINIT_PROBE_WAIT(end, this_k(), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(end, this_k, -1,wait); } // Note: implementation moved to static method to expose the this pointer. void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) { - instanceKlassHandle kh(THREAD, this); - set_initialization_state_and_notify_impl(kh, state, CHECK); + set_initialization_state_and_notify_impl(this, state, CHECK); } -void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) { +void InstanceKlass::set_initialization_state_and_notify_impl(InstanceKlass* this_k, ClassState state, TRAPS) { Handle init_lock(THREAD, this_k->init_lock()); if (init_lock() != NULL) { ObjectLocker ol(init_lock, THREAD); @@ -995,9 +990,8 @@ objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) { } int size = objArrayOopDesc::object_size(length); Klass* ak = array_klass(n, CHECK_NULL); - KlassHandle h_ak (THREAD, ak); objArrayOop o = - (objArrayOop)CollectedHeap::array_allocate(h_ak, size, length, CHECK_NULL); + (objArrayOop)CollectedHeap::array_allocate(ak, size, length, CHECK_NULL); return o; } @@ -1020,11 +1014,9 @@ instanceOop InstanceKlass::allocate_instance(TRAPS) { bool has_finalizer_flag = has_finalizer(); // Query before possible GC int size = size_helper(); // Query before forming handle. - KlassHandle h_k(THREAD, this); - instanceOop i; - i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); + i = (instanceOop)CollectedHeap::obj_allocate(this, size, CHECK_NULL); if (has_finalizer_flag && !RegisterFinalizersAtInit) { i = register_finalizer(i, CHECK_NULL); } @@ -1045,11 +1037,10 @@ void InstanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) { } Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) { - instanceKlassHandle this_k(THREAD, this); - return array_klass_impl(this_k, or_null, n, THREAD); + return array_klass_impl(this, or_null, n, THREAD); } -Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_k, bool or_null, int n, TRAPS) { +Klass* InstanceKlass::array_klass_impl(InstanceKlass* this_k, bool or_null, int n, TRAPS) { // Need load-acquire for lock-free read if (this_k->array_klasses_acquire() == NULL) { if (or_null) return NULL; @@ -1082,13 +1073,12 @@ Klass* InstanceKlass::array_klass_impl(bool or_null, TRAPS) { } void InstanceKlass::call_class_initializer(TRAPS) { - instanceKlassHandle ik (THREAD, this); - call_class_initializer_impl(ik, THREAD); + call_class_initializer_impl(this, THREAD); } static int call_class_initializer_impl_counter = 0; // for debugging -Method* InstanceKlass::class_initializer() { +Method* InstanceKlass::class_initializer() const { Method* clinit = find_method( vmSymbols::class_initializer_name(), vmSymbols::void_method_signature()); if (clinit != NULL && clinit->has_valid_initializer_flags()) { @@ -1097,7 +1087,7 @@ Method* InstanceKlass::class_initializer() { return NULL; } -void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAPS) { +void InstanceKlass::call_class_initializer_impl(InstanceKlass* this_k, TRAPS) { if (ReplayCompiles && (ReplaySuppressInitializers == 1 || ReplaySuppressInitializers >= 2 && this_k->class_loader() != NULL)) { @@ -1112,7 +1102,7 @@ void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAP outputStream* log = Log(class, init)::info_stream(); log->print("%d Initializing ", call_class_initializer_impl_counter++); this_k->name()->print_value_on(log); - log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this_k())); + log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this_k)); } if (h_method() != NULL) { JavaCallArguments args; // No arguments @@ -1263,14 +1253,13 @@ void InstanceKlass::do_local_static_fields(FieldClosure* cl) { void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) { - instanceKlassHandle h_this(THREAD, this); - do_local_static_fields_impl(h_this, f, mirror, CHECK); + do_local_static_fields_impl(this, f, mirror, CHECK); } -void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, +void InstanceKlass::do_local_static_fields_impl(InstanceKlass* this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle mirror, TRAPS) { - for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) { + for (JavaFieldStream fs(this_k); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { fieldDescriptor& fd = fs.field_descriptor(); f(&fd, mirror, CHECK); @@ -1629,13 +1618,13 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, } /* jni_id_for_impl for jfieldIds only */ -JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_k, int offset) { +JNIid* InstanceKlass::jni_id_for_impl(InstanceKlass* this_k, int offset) { MutexLocker ml(JfieldIdCreation_lock); // Retry lookup after we got the lock JNIid* probe = this_k->jni_ids() == NULL ? NULL : this_k->jni_ids()->find(offset); if (probe == NULL) { // Slow case, allocate new static field identifier - probe = new JNIid(this_k(), offset, this_k->jni_ids()); + probe = new JNIid(this_k, offset, this_k->jni_ids()); this_k->set_jni_ids(probe); } return probe; @@ -1684,9 +1673,9 @@ void InstanceKlass::set_enclosing_method_indices(u2 class_index, // locking has to be done very carefully to avoid deadlocks // and/or other cache consistency problems. // -jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHandle& method_h) { +jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& method_h) { size_t idnum = (size_t)method_h->method_idnum(); - jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire(); + jmethodID* jmeths = ik->methods_jmethod_ids_acquire(); size_t length = 0; jmethodID id = NULL; @@ -1710,7 +1699,7 @@ jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHa if (jmeths != NULL) { // the cache already exists - if (!ik_h->idnum_can_increment()) { + if (!ik->idnum_can_increment()) { // the cache can't grow so we can just get the current values get_jmethod_id_length_value(jmeths, idnum, &length, &id); } else { @@ -1744,7 +1733,7 @@ jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHa jmethodID* new_jmeths = NULL; if (length <= idnum) { // allocate a new cache that might be used - size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count()); + size_t size = MAX2(idnum+1, (size_t)ik->idnum_allocated_count()); new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass); memset(new_jmeths, 0, (size+1)*sizeof(jmethodID)); // cache size is stored in element[0], other elements offset by one @@ -1755,23 +1744,23 @@ jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHa jmethodID new_id = NULL; if (method_h->is_old() && !method_h->is_obsolete()) { // The method passed in is old (but not obsolete), we need to use the current version - Method* current_method = ik_h->method_with_idnum((int)idnum); + Method* current_method = ik->method_with_idnum((int)idnum); assert(current_method != NULL, "old and but not obsolete, so should exist"); - new_id = Method::make_jmethod_id(ik_h->class_loader_data(), current_method); + new_id = Method::make_jmethod_id(ik->class_loader_data(), current_method); } else { // It is the current version of the method or an obsolete method, // use the version passed in - new_id = Method::make_jmethod_id(ik_h->class_loader_data(), method_h()); + new_id = Method::make_jmethod_id(ik->class_loader_data(), method_h()); } if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) { // we're single threaded or at a safepoint - no locking needed - id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths, + id = get_jmethod_id_fetch_or_update(ik, idnum, new_id, new_jmeths, &to_dealloc_id, &to_dealloc_jmeths); } else { MutexLocker ml(JmethodIdCreation_lock); - id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths, + id = get_jmethod_id_fetch_or_update(ik, idnum, new_id, new_jmeths, &to_dealloc_id, &to_dealloc_jmeths); } @@ -1782,7 +1771,7 @@ jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHa } // free up the new ID since it wasn't needed if (to_dealloc_id != NULL) { - Method::destroy_jmethod_id(ik_h->class_loader_data(), to_dealloc_id); + Method::destroy_jmethod_id(ik->class_loader_data(), to_dealloc_id); } } return id; @@ -1814,7 +1803,7 @@ void InstanceKlass::ensure_space_for_methodids(int start_offset) { // the VMThread or have cache consistency issues. // jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( - instanceKlassHandle ik_h, size_t idnum, jmethodID new_id, + InstanceKlass* ik, size_t idnum, jmethodID new_id, jmethodID* new_jmeths, jmethodID* to_dealloc_id_p, jmethodID** to_dealloc_jmeths_p) { assert(new_id != NULL, "sanity check"); @@ -1825,7 +1814,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( JmethodIdCreation_lock->owned_by_self(), "sanity check"); // reacquire the cache - we are locked, single threaded or at a safepoint - jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire(); + jmethodID* jmeths = ik->methods_jmethod_ids_acquire(); jmethodID id = NULL; size_t length = 0; @@ -1838,7 +1827,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( } *to_dealloc_jmeths_p = jmeths; // save old cache for later delete } - ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths); + ik->release_set_methods_jmethod_ids(jmeths = new_jmeths); } else { // fetch jmethodID (if any) from the existing cache id = jmeths[idnum+1]; @@ -2058,11 +2047,10 @@ static void restore_unshareable_in_class(Klass* k, TRAPS) { } void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { - instanceKlassHandle ik(THREAD, this); - ik->set_package(loader_data, CHECK); + set_package(loader_data, CHECK); Klass::restore_unshareable_info(loader_data, protection_domain, CHECK); - Array* methods = ik->methods(); + Array* methods = this->methods(); int num_methods = methods->length(); for (int index2 = 0; index2 < num_methods; ++index2) { methodHandle m(THREAD, methods->at(index2)); @@ -2075,14 +2063,14 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl // vtables in the shared system dictionary, only the main one. // It also redefines the itable too so fix that too. ResourceMark rm(THREAD); - ik->vtable()->initialize_vtable(false, CHECK); - ik->itable()->initialize_itable(false, CHECK); + vtable()->initialize_vtable(false, CHECK); + itable()->initialize_itable(false, CHECK); } // restore constant pool resolved references - ik->constants()->restore_unshareable_info(CHECK); + constants()->restore_unshareable_info(CHECK); - ik->array_klasses_do(restore_unshareable_in_class, CHECK); + array_klasses_do(restore_unshareable_in_class, CHECK); } // returns true IFF is_in_error_state() has been changed as a result of this call. @@ -2448,7 +2436,7 @@ bool InstanceKlass::is_override(const methodHandle& super_method, Handle targetc } /* defined for now in jvm.cpp, for historical reasons *-- -Klass* InstanceKlass::compute_enclosing_class_impl(instanceKlassHandle self, +Klass* InstanceKlass::compute_enclosing_class_impl(InstanceKlass* self, Symbol*& simple_name_result, TRAPS) { ... } @@ -2522,7 +2510,7 @@ bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1, return false; } -bool InstanceKlass::find_inner_classes_attr(instanceKlassHandle k, int* ooff, int* noff, TRAPS) { +bool InstanceKlass::find_inner_classes_attr(const InstanceKlass* k, int* ooff, int* noff, TRAPS) { constantPoolHandle i_cp(THREAD, k->constants()); for (InnerClassesIterator iter(k); !iter.done(); iter.next()) { int ioff = iter.inner_class_info_index(); @@ -2531,7 +2519,7 @@ bool InstanceKlass::find_inner_classes_attr(instanceKlassHandle k, int* ooff, in // before attempting to find the class. if (i_cp->klass_name_at_matches(k, ioff)) { Klass* inner_klass = i_cp->klass_at(ioff, CHECK_false); - if (k() == inner_klass) { + if (k == inner_klass) { *ooff = iter.outer_class_info_index(); *noff = iter.inner_name_index(); return true; @@ -2580,8 +2568,7 @@ jint InstanceKlass::compute_modifier_flags(TRAPS) const { jint access = access_flags().as_int(); // But check if it happens to be member class. - instanceKlassHandle ik(THREAD, this); - InnerClassesIterator iter(ik); + InnerClassesIterator iter(this); for (; !iter.done(); iter.next()) { int ioff = iter.inner_class_info_index(); // Inner class attribute can be zero, skip it. @@ -2590,8 +2577,8 @@ jint InstanceKlass::compute_modifier_flags(TRAPS) const { // only look at classes that are already loaded // since we are looking for the flags for our self. - Symbol* inner_name = ik->constants()->klass_name_at(ioff); - if ((ik->name() == inner_name)) { + Symbol* inner_name = constants()->klass_name_at(ioff); + if (name() == inner_name) { // This is really a member class. access = iter.inner_access_flags(); break; @@ -3612,7 +3599,7 @@ void InstanceKlass::mark_newly_obsolete_methods(Array* old_methods, // Save the scratch_class as the previous version if any of the methods are running. // The previous_versions are used to set breakpoints in EMCP methods and they are // also used to clean MethodData links to redefined methods that are no longer running. -void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, +void InstanceKlass::add_previous_version(InstanceKlass* scratch_class, int emcp_method_count) { assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions"); @@ -3638,7 +3625,7 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, log_trace(redefine, class, iklass, add)("scratch class not added; no methods are running"); // For debugging purposes. scratch_class->set_is_scratch_class(); - scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class()); + scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class); return; } @@ -3671,7 +3658,7 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack."); assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); scratch_class->link_previous_versions(previous_versions()); - link_previous_versions(scratch_class()); + link_previous_versions(scratch_class); } // end add_previous_version() #endif // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 1756b9fc86d..cc31ad7d46b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -472,7 +472,7 @@ class InstanceKlass: public Klass { TRAPS); // Find InnerClasses attribute for k and return outer_class_info_index & inner_name_index. - static bool find_inner_classes_attr(instanceKlassHandle k, + static bool find_inner_classes_attr(const InstanceKlass* k, int* ooff, int* noff, TRAPS); private: @@ -524,7 +524,7 @@ class InstanceKlass: public Klass { void unlink_class(); void rewrite_class(TRAPS); void link_methods(TRAPS); - Method* class_initializer(); + Method* class_initializer() const; // set the class to initialized if no static initializer is present void eager_initialize(Thread *thread); @@ -711,7 +711,7 @@ class InstanceKlass: public Klass { void set_is_being_redefined(bool value) { _is_being_redefined = value; } // RedefineClasses() support for previous versions: - void add_previous_version(instanceKlassHandle ikh, int emcp_method_count); + void add_previous_version(InstanceKlass* ik, int emcp_method_count); void purge_previous_version_list(); InstanceKlass* previous_versions() const { return _previous_versions; } @@ -883,9 +883,9 @@ public: u2 method_index); // jmethodID support - static jmethodID get_jmethod_id(instanceKlassHandle ik_h, + static jmethodID get_jmethod_id(InstanceKlass* ik, const methodHandle& method_h); - static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h, + static jmethodID get_jmethod_id_fetch_or_update(InstanceKlass* ik, size_t idnum, jmethodID new_id, jmethodID* new_jmeths, jmethodID* to_dealloc_id_p, jmethodID** to_dealloc_jmeths_p); @@ -1308,17 +1308,17 @@ private: // Static methods that are used to implement member methods where an exposed this pointer // is needed due to possible GCs - static bool link_class_impl (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS); - static bool verify_code (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS); - static void initialize_impl (instanceKlassHandle this_k, TRAPS); - static void initialize_super_interfaces (instanceKlassHandle this_k, TRAPS); - static void eager_initialize_impl (instanceKlassHandle this_k); - static void set_initialization_state_and_notify_impl (instanceKlassHandle this_k, ClassState state, TRAPS); - static void call_class_initializer_impl (instanceKlassHandle this_k, TRAPS); - static Klass* array_klass_impl (instanceKlassHandle this_k, bool or_null, int n, TRAPS); - static void do_local_static_fields_impl (instanceKlassHandle this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS); + static bool link_class_impl (InstanceKlass* this_k, bool throw_verifyerror, TRAPS); + static bool verify_code (InstanceKlass* this_k, bool throw_verifyerror, TRAPS); + static void initialize_impl (InstanceKlass* this_k, TRAPS); + static void initialize_super_interfaces (InstanceKlass* this_k, TRAPS); + static void eager_initialize_impl (InstanceKlass* this_k); + static void set_initialization_state_and_notify_impl (InstanceKlass* this_k, ClassState state, TRAPS); + static void call_class_initializer_impl (InstanceKlass* this_k, TRAPS); + static Klass* array_klass_impl (InstanceKlass* this_k, bool or_null, int n, TRAPS); + static void do_local_static_fields_impl (InstanceKlass* this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS); /* jni_id_for_impl for jfieldID only */ - static JNIid* jni_id_for_impl (instanceKlassHandle this_k, int offset); + static JNIid* jni_id_for_impl (InstanceKlass* this_k, int offset); // Returns the array class for the n'th dimension Klass* array_klass_impl(bool or_null, int n, TRAPS); @@ -1447,7 +1447,7 @@ class InnerClassesIterator : public StackObj { int _idx; public: - InnerClassesIterator(instanceKlassHandle k) { + InnerClassesIterator(const InstanceKlass* k) { _inner_classes = k->inner_classes(); if (k->inner_classes() != NULL) { _length = _inner_classes->length(); diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp index 72edd471c5f..325e4c0e4ee 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -39,23 +39,21 @@ int InstanceMirrorKlass::_offset_of_static_fields = 0; -int InstanceMirrorKlass::instance_size(KlassHandle k) { - if (k() != NULL && k->is_instance_klass()) { - return align_object_size(size_helper() + InstanceKlass::cast(k())->static_field_size()); +int InstanceMirrorKlass::instance_size(Klass* k) { + if (k != NULL && k->is_instance_klass()) { + return align_object_size(size_helper() + InstanceKlass::cast(k)->static_field_size()); } return size_helper(); } -instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) { +instanceOop InstanceMirrorKlass::allocate_instance(Klass* k, TRAPS) { // Query before forming handle. int size = instance_size(k); - KlassHandle h_k(THREAD, this); - assert(size > 0, "total object size must be positive: %d", size); // Since mirrors can be variable sized because of the static fields, store // the size in the mirror itself. - return (instanceOop)CollectedHeap::class_allocate(h_k, size, CHECK_NULL); + return (instanceOop)CollectedHeap::class_allocate(this, size, CHECK_NULL); } int InstanceMirrorKlass::oop_size(oop obj) const { diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp index 48baee477d7..bb0da20e96c 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,10 +82,10 @@ class InstanceMirrorKlass: public InstanceKlass { int compute_static_oop_field_count(oop obj); // Given a Klass return the size of the instance - int instance_size(KlassHandle k); + int instance_size(Klass* k); // allocation - instanceOop allocate_instance(KlassHandle k, TRAPS); + instanceOop allocate_instance(Klass* k, TRAPS); // GC specific object visitors // diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index eaa40839ee7..04c204ef62a 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -264,7 +264,6 @@ void Klass::initialize_supers(Klass* k, TRAPS) { } if (secondary_supers() == NULL) { - KlassHandle this_kh (THREAD, this); // Now compute the list of secondary supertypes. // Secondaries can occasionally be on the super chain, @@ -286,7 +285,7 @@ void Klass::initialize_supers(Klass* k, TRAPS) { GrowableArray* primaries = new GrowableArray(extras); - for (p = this_kh->super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) { + for (p = super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) { int i; // Scan for overflow primaries being duplicates of 2nd'arys // This happens frequently for very deeply nested arrays: the @@ -324,7 +323,7 @@ void Klass::initialize_supers(Klass* k, TRAPS) { } #endif - this_kh->set_secondary_supers(s2); + set_secondary_supers(s2); } } @@ -698,7 +697,7 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { } klassVtable* Klass::vtable() const { - return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size()); + return new klassVtable(const_cast(this), start_of_vtable(), vtable_length() / vtableEntry::size()); } vtableEntry* Klass::start_of_vtable() const { diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 9715d2b087a..3a1fcc450ea 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -40,7 +40,7 @@ #include "utilities/copy.hpp" inline InstanceKlass* klassVtable::ik() const { - return InstanceKlass::cast(_klass()); + return InstanceKlass::cast(_klass); } bool klassVtable::is_preinitialized_vtable() { @@ -128,8 +128,8 @@ int klassVtable::index_of(Method* m, int len) const { // Copy super class's vtable to the first part (prefix) of this class's vtable, // and return the number of entries copied. Expects that 'super' is the Java // super class (arrays can have "array" super classes that must be skipped). -int klassVtable::initialize_from_super(KlassHandle super) { - if (super.is_null()) { +int klassVtable::initialize_from_super(Klass* super) { + if (super == NULL) { return 0; } else if (is_preinitialized_vtable()) { // A shared class' vtable is preinitialized at dump time. No need to copy @@ -160,18 +160,18 @@ int klassVtable::initialize_from_super(KlassHandle super) { void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { // Note: Arrays can have intermediate array supers. Use java_super to skip them. - KlassHandle super (THREAD, klass()->java_super()); + Klass* super = _klass->java_super(); int nofNewEntries = 0; bool is_shared = _klass->is_shared(); - if (!klass()->is_array_klass()) { + if (!_klass->is_array_klass()) { ResourceMark rm(THREAD); log_develop_debug(vtables)("Initializing: %s", _klass->name()->as_C_string()); } #ifdef ASSERT - oop* end_of_obj = (oop*)_klass() + _klass()->size(); + oop* end_of_obj = (oop*)_klass + _klass->size(); oop* end_of_vtable = (oop*)&table()[_length]; assert(end_of_vtable <= end_of_obj, "vtable extends beyond end"); #endif @@ -184,7 +184,7 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { } int super_vtable_len = initialize_from_super(super); - if (klass()->is_array_klass()) { + if (_klass->is_array_klass()) { assert(super_vtable_len == _length, "arrays shouldn't introduce new methods"); } else { assert(_klass->is_instance_klass(), "must be InstanceKlass"); @@ -327,7 +327,7 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper } static void log_vtables(int i, bool overrides, methodHandle target_method, - KlassHandle target_klass, Method* super_method, + Klass* target_klass, Method* super_method, Thread* thread) { #ifndef PRODUCT if (log_develop_is_enabled(Trace, vtables)) { @@ -432,7 +432,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar Symbol* name = target_method()->name(); Symbol* signature = target_method()->signature(); - KlassHandle target_klass(THREAD, target_method()->method_holder()); + Klass* target_klass = target_method()->method_holder(); if (target_klass == NULL) { target_klass = _klass; } @@ -955,7 +955,7 @@ void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name if (!(*trace_name_printed)) { log_info(redefine, class, update) ("adjust: klassname=%s for methods from name=%s", - klass()->external_name(), old_method->method_holder()->external_name()); + _klass->external_name(), old_method->method_holder()->external_name()); *trace_name_printed = true; } log_debug(redefine, class, update, vtables) @@ -1025,17 +1025,17 @@ void itableMethodEntry::initialize(Method* m) { } } -klassItable::klassItable(instanceKlassHandle klass) { +klassItable::klassItable(InstanceKlass* klass) { _klass = klass; if (klass->itable_length() > 0) { itableOffsetEntry* offset_entry = (itableOffsetEntry*)klass->start_of_itable(); if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized // First offset entry points to the first method_entry - intptr_t* method_entry = (intptr_t *)(((address)klass()) + offset_entry->offset()); + intptr_t* method_entry = (intptr_t *)(((address)klass) + offset_entry->offset()); intptr_t* end = klass->end_of_itable(); - _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass(); + _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass; _size_offset_table = (method_entry - ((intptr_t*)offset_entry)) / itableOffsetEntry::size(); _size_method_table = (end - method_entry) / itableMethodEntry::size(); assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation"); @@ -1056,7 +1056,7 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) { if (_klass->is_interface()) { // This needs to go after vtable indices are assigned but // before implementors need to know the number of itable indices. - assign_itable_indices_for_interface(_klass()); + assign_itable_indices_for_interface(_klass); } // Cannot be setup doing bootstrapping, interfaces don't have @@ -1078,9 +1078,9 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) { for(i = 0; i < num_interfaces; i++) { itableOffsetEntry* ioe = offset_entry(i); HandleMark hm(THREAD); - KlassHandle interf_h (THREAD, ioe->interface_klass()); - assert(interf_h() != NULL && ioe->offset() != 0, "bad offset entry in itable"); - initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK); + Klass* interf = ioe->interface_klass(); + assert(interf != NULL && ioe->offset() != 0, "bad offset entry in itable"); + initialize_itable_for_interface(ioe->offset(), interf, checkconstraints, CHECK); } } @@ -1169,14 +1169,14 @@ int klassItable::method_count_for_interface(Klass* interf) { } -void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) { - Array* methods = InstanceKlass::cast(interf_h())->methods(); +void klassItable::initialize_itable_for_interface(int method_table_offset, Klass* interf, bool checkconstraints, TRAPS) { + Array* methods = InstanceKlass::cast(interf)->methods(); int nof_methods = methods->length(); HandleMark hm; assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); - Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader()); + Handle interface_loader (THREAD, InstanceKlass::cast(interf)->class_loader()); - int ime_count = method_count_for_interface(interf_h()); + int ime_count = method_count_for_interface(interf); for (int i = 0; i < nof_methods; i++) { Method* m = methods->at(i); methodHandle target; @@ -1189,7 +1189,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass // Entry does not resolve. Leave it empty for AbstractMethodError. if (!(target == NULL) && !target->is_public()) { // Stuff an IllegalAccessError throwing method in there instead. - itableOffsetEntry::method_entry(_klass(), method_table_offset)[m->itable_index()]. + itableOffsetEntry::method_entry(_klass, method_table_offset)[m->itable_index()]. initialize(Universe::throw_illegal_access_error()); } } else { @@ -1215,7 +1215,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass const char* loader1 = SystemDictionary::loader_name(method_holder_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(interface_loader()); - char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string(); + char* iface = InstanceKlass::cast(interf)->name()->as_C_string(); char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + strlen(current) + strlen(loader2) + strlen(iface) + @@ -1231,14 +1231,14 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass // ime may have moved during GC so recalculate address int ime_num = m->itable_index(); assert(ime_num < ime_count, "oob"); - itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target()); + itableOffsetEntry::method_entry(_klass, method_table_offset)[ime_num].initialize(target()); if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm(THREAD); if (target() != NULL) { outputStream* logst = Log(itables)::trace_stream(); char* sig = target()->name_and_sig_as_C_string(); logst->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ", - interf_h()->internal_name(), ime_num, sig, + interf->internal_name(), ime_num, sig, target()->method_holder()->internal_name()); logst->print("target_method flags: "); target()->print_linkage_flags(logst); @@ -1408,7 +1408,7 @@ int klassItable::compute_itable_size(Array* transitive_interfaces) { // Fill out offset table and interface klasses into the itable space -void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { +void klassItable::setup_itable_offset_table(InstanceKlass* klass) { if (klass->itable_length() == 0) return; assert(!klass->is_interface(), "Should have zero length itable"); @@ -1433,7 +1433,7 @@ void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); // Visit all interfaces and initialize itable offset table - SetupItableClosure sic((address)klass(), ioe, ime); + SetupItableClosure sic((address)klass, ioe, ime); visit_all_interfaces(klass->transitive_interfaces(), &sic); #ifdef ASSERT @@ -1476,7 +1476,7 @@ void klassVtable::verify(outputStream* st, bool forced) { if (!forced && _verify_count == Universe::verify_count()) return; _verify_count = Universe::verify_count(); #endif - oop* end_of_obj = (oop*)_klass() + _klass()->size(); + oop* end_of_obj = (oop*)_klass + _klass->size(); oop* end_of_vtable = (oop *)&table()[_length]; if (end_of_vtable > end_of_obj) { fatal("klass %s: klass object too short (vtable extends beyond end)", @@ -1516,8 +1516,7 @@ void klassVtable::print() { void vtableEntry::verify(klassVtable* vt, outputStream* st) { NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true)); - KlassHandle vtklass_h = vt->klass(); - Klass* vtklass = vtklass_h(); + Klass* vtklass = vt->klass(); if (vtklass->is_instance_klass() && (InstanceKlass::cast(vtklass)->major_version() >= klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION)) { assert(method() != NULL, "must have set method"); @@ -1525,7 +1524,7 @@ void vtableEntry::verify(klassVtable* vt, outputStream* st) { if (method() != NULL) { method()->verify(); // we sub_type, because it could be a miranda method - if (!vtklass_h->is_subtype_of(method()->method_holder())) { + if (!vtklass->is_subtype_of(method()->method_holder())) { #ifndef PRODUCT print(); #endif diff --git a/hotspot/src/share/vm/oops/klassVtable.hpp b/hotspot/src/share/vm/oops/klassVtable.hpp index 06e84034214..7fa6806107c 100644 --- a/hotspot/src/share/vm/oops/klassVtable.hpp +++ b/hotspot/src/share/vm/oops/klassVtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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,7 +42,7 @@ class vtableEntry; class klassVtable : public ResourceObj { - KlassHandle _klass; // my klass + Klass* _klass; // my klass int _tableOffset; // offset of start of vtable data within klass int _length; // length of vtable (number of entries) #ifndef PRODUCT @@ -57,13 +57,13 @@ class klassVtable : public ResourceObj { }; public: - klassVtable(KlassHandle h_klass, void* base, int length) : _klass(h_klass) { - _tableOffset = (address)base - (address)h_klass(); _length = length; + klassVtable(Klass* klass, void* base, int length) : _klass(klass) { + _tableOffset = (address)base - (address)klass; _length = length; } // accessors - vtableEntry* table() const { return (vtableEntry*)(address(_klass()) + _tableOffset); } - KlassHandle klass() const { return _klass; } + vtableEntry* table() const { return (vtableEntry*)(address(_klass) + _tableOffset); } + Klass* klass() const { return _klass; } int length() const { return _length; } inline Method* method_at(int i) const; inline Method* unchecked_method_at(int i) const; @@ -125,7 +125,7 @@ class klassVtable : public ResourceObj { private: void copy_vtable_to(vtableEntry* start); - int initialize_from_super(KlassHandle super); + int initialize_from_super(Klass* super); int index_of(Method* m, int len) const; // same as index_of, but search only up to len void put_method_at(Method* m, int index); static bool needs_new_vtable_entry(methodHandle m, @@ -290,14 +290,14 @@ class itableMethodEntry VALUE_OBJ_CLASS_SPEC { // class klassItable : public ResourceObj { private: - instanceKlassHandle _klass; // my klass + InstanceKlass* _klass; // my klass int _table_offset; // offset of start of itable data within klass (in words) int _size_offset_table; // size of offset table (in itableOffset entries) int _size_method_table; // size of methodtable (in itableMethodEntry entries) - void initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS); + void initialize_itable_for_interface(int method_table_offset, Klass* interf_h, bool checkconstraints, TRAPS); public: - klassItable(instanceKlassHandle klass); + klassItable(InstanceKlass* klass); itableOffsetEntry* offset_entry(int i) { assert(0 <= i && i <= _size_offset_table, "index out of bounds"); return &((itableOffsetEntry*)vtable_start())[i]; } @@ -329,7 +329,7 @@ class klassItable : public ResourceObj { static int assign_itable_indices_for_interface(Klass* klass); static int method_count_for_interface(Klass* klass); static int compute_itable_size(Array* transitive_interfaces); - static void setup_itable_offset_table(instanceKlassHandle klass); + static void setup_itable_offset_table(InstanceKlass* klass); // Resolving of method to index static Method* method_for_itable_index(Klass* klass, int itable_index); @@ -337,7 +337,7 @@ class klassItable : public ResourceObj { // Debugging/Statistics static void print_statistics() PRODUCT_RETURN; private: - intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; } + intptr_t* vtable_start() const { return ((intptr_t*)_klass) + _table_offset; } intptr_t* method_start() const { return vtable_start() + _size_offset_table * itableOffsetEntry::size(); } // Helper methods diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 8dcfa68c703..4f9218a5d47 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -173,7 +173,7 @@ char* Method::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol return buf; } -int Method::fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS) { +int Method::fast_exception_handler_bci_for(methodHandle mh, Klass* ex_klass, int throw_bci, TRAPS) { // exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index) // access exception table ExceptionTable table(mh()); @@ -192,16 +192,15 @@ int Method::fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass int klass_index = table.catch_type_index(i); if (klass_index == 0) { return handler_bci; - } else if (ex_klass.is_null()) { + } else if (ex_klass == NULL) { return handler_bci; } else { // we know the exception class => get the constraint class // this may require loading of the constraint class; if verification // fails or some other exception occurs, return handler_bci Klass* k = pool->klass_at(klass_index, CHECK_(handler_bci)); - KlassHandle klass = KlassHandle(THREAD, k); - assert(klass.not_null(), "klass not loaded"); - if (ex_klass->is_subtype_of(klass())) { + assert(k != NULL, "klass not loaded"); + if (ex_klass->is_subtype_of(k)) { return handler_bci; } } @@ -1271,7 +1270,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, ResourceMark rm; methodHandle empty; - KlassHandle holder = SystemDictionary::MethodHandle_klass(); + InstanceKlass* holder = SystemDictionary::MethodHandle_klass(); Symbol* name = MethodHandles::signature_polymorphic_intrinsic_name(iid); assert(iid == MethodHandles::signature_polymorphic_name_id(name), ""); if (TraceMethodHandles) { @@ -1289,7 +1288,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, ConstantPool* cp_oop = ConstantPool::allocate(loader_data, cp_length, CHECK_(empty)); cp = constantPoolHandle(THREAD, cp_oop); } - cp->set_pool_holder(InstanceKlass::cast(holder())); + cp->set_pool_holder(holder); cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); cp->set_has_preresolution(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index a3e636388cd..98fa587db4c 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -323,7 +323,7 @@ class Method : public Metadata { // exception handler which caused the exception to be thrown, which // is needed for proper retries. See, for example, // InterpreterRuntime::exception_handler_for_exception. - static int fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS); + static int fast_exception_handler_bci_for(methodHandle mh, Klass* ex_klass, int throw_bci, TRAPS); // method data access MethodData* method_data() const { @@ -811,8 +811,7 @@ class Method : public Metadata { static void print_jmethod_ids(ClassLoaderData* loader_data, outputStream* out) PRODUCT_RETURN; // Get this method's jmethodID -- allocate if it doesn't exist - jmethodID jmethod_id() { methodHandle this_h(this); - return InstanceKlass::get_jmethod_id(method_holder(), this_h); } + jmethodID jmethod_id() { return InstanceKlass::get_jmethod_id(method_holder(), this); } // Lookup the jmethodID for this method. Return NULL if not found. // NOTE that this function can be called from a signal handler diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index bf2672daa78..f381789f10d 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -46,26 +46,26 @@ #include "utilities/copy.hpp" #include "utilities/macros.hpp" -ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) { +ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) { assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), "array klasses must be same size as InstanceKlass"); int size = ArrayKlass::static_size(ObjArrayKlass::header_size()); - return new (loader_data, size, THREAD) ObjArrayKlass(n, klass_handle, name); + return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name); } Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, - int n, KlassHandle element_klass, TRAPS) { + int n, Klass* element_klass, TRAPS) { // Eagerly allocate the direct array supertype. - KlassHandle super_klass = KlassHandle(); + Klass* super_klass = NULL; if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) { - KlassHandle element_super (THREAD, element_klass->super()); - if (element_super.not_null()) { + Klass* element_super = element_klass->super(); + if (element_super != NULL) { // The element type has a direct super. E.g., String[] has direct super of Object[]. - super_klass = KlassHandle(THREAD, element_super->array_klass_or_null()); - bool supers_exist = super_klass.not_null(); + super_klass = element_super->array_klass_or_null(); + bool supers_exist = super_klass != NULL; // Also, see if the element has secondary supertypes. // We need an array type for each. Array* element_supers = element_klass->secondary_supers(); @@ -78,34 +78,30 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, } if (!supers_exist) { // Oops. Not allocated yet. Back out, allocate it, and retry. - KlassHandle ek; + Klass* ek = NULL; { MutexUnlocker mu(MultiArray_lock); MutexUnlocker mc(Compile_lock); // for vtables - Klass* sk = element_super->array_klass(CHECK_0); - super_klass = KlassHandle(THREAD, sk); + super_klass = element_super->array_klass(CHECK_0); for( int i = element_supers->length()-1; i >= 0; i-- ) { - KlassHandle elem_super (THREAD, element_supers->at(i)); + Klass* elem_super = element_supers->at(i); elem_super->array_klass(CHECK_0); } // Now retry from the beginning - Klass* klass_oop = element_klass->array_klass(n, CHECK_0); - // Create a handle because the enclosing brace, when locking - // can cause a gc. Better to have this function return a Handle. - ek = KlassHandle(THREAD, klass_oop); + ek = element_klass->array_klass(n, CHECK_0); } // re-lock - return ek(); + return ek; } } else { // The element type is already Object. Object[] has direct super of Object. - super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass()); + super_klass = SystemDictionary::Object_klass(); } } // Create type name for klass. Symbol* name = NULL; if (!element_klass->is_instance_klass() || - (name = InstanceKlass::cast(element_klass())->array_name()) == NULL) { + (name = InstanceKlass::cast(element_klass)->array_name()) == NULL) { ResourceMark rm(THREAD); char *name_str = element_klass->name()->as_C_string(); @@ -124,7 +120,7 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, new_str[idx++] = '\0'; name = SymbolTable::new_permanent_symbol(new_str, CHECK_0); if (element_klass->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(element_klass()); + InstanceKlass* ik = InstanceKlass::cast(element_klass); ik->set_array_name(name); } } @@ -146,9 +142,9 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, return oak; } -ObjArrayKlass::ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name) : ArrayKlass(name) { +ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name) { this->set_dimension(n); - this->set_element_klass(element_klass()); + this->set_element_klass(element_klass); // decrement refcount because object arrays are not explicitly freed. The // InstanceKlass array_name() keeps the name counted while the klass is // loaded. @@ -156,9 +152,9 @@ ObjArrayKlass::ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name) : A Klass* bk; if (element_klass->is_objArray_klass()) { - bk = ObjArrayKlass::cast(element_klass())->bottom_klass(); + bk = ObjArrayKlass::cast(element_klass)->bottom_klass(); } else { - bk = element_klass(); + bk = element_klass; } assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass"); this->set_bottom_klass(bk); @@ -178,8 +174,7 @@ objArrayOop ObjArrayKlass::allocate(int length, TRAPS) { if (length >= 0) { if (length <= arrayOopDesc::max_array_length(T_OBJECT)) { int size = objArrayOopDesc::object_size(length); - KlassHandle h_k(THREAD, this); - return (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, THREAD); + return (objArrayOop)CollectedHeap::array_allocate(this, size, length, THREAD); } else { report_java_out_of_memory("Requested array size exceeds VM limit"); JvmtiExport::post_array_size_exhausted(); @@ -196,14 +191,14 @@ oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { int length = *sizes; // Call to lower_dimension uses this pointer, so most be called before a // possible GC - KlassHandle h_lower_dimension(THREAD, lower_dimension()); + Klass* ld_klass = lower_dimension(); // If length < 0 allocate will throw an exception. objArrayOop array = allocate(length, CHECK_NULL); objArrayHandle h_array (THREAD, array); if (rank > 1) { if (length != 0) { for (int index = 0; index < length; index++) { - ArrayKlass* ak = ArrayKlass::cast(h_lower_dimension()); + ArrayKlass* ak = ArrayKlass::cast(ld_klass); oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL); h_array->obj_at_put(index, sub_array); } diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index c2d1f7930ba..6bd1d0eebbf 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -39,8 +39,8 @@ class ObjArrayKlass : public ArrayKlass { Klass* _bottom_klass; // The one-dimensional type (InstanceKlass or TypeArrayKlass) // Constructor - ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name); - static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS); + ObjArrayKlass(int n, Klass* element_klass, Symbol* name); + static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS); public: // For dummy objects ObjArrayKlass() {} @@ -69,7 +69,7 @@ class ObjArrayKlass : public ArrayKlass { // Allocation static Klass* allocate_objArray_klass(ClassLoaderData* loader_data, - int n, KlassHandle element_klass, TRAPS); + int n, Klass* element_klass, TRAPS); objArrayOop allocate(int length, TRAPS); oop multi_allocate(int rank, jint* sizes, TRAPS); diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 5ce156026a9..067b1415b5f 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -102,13 +102,12 @@ typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { if (length >= 0) { if (length <= max_length()) { size_t size = typeArrayOopDesc::object_size(layout_helper(), length); - KlassHandle h_k(THREAD, this); typeArrayOop t; CollectedHeap* ch = Universe::heap(); if (do_zero) { - t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); + t = (typeArrayOop)CollectedHeap::array_allocate(this, (int)size, length, CHECK_NULL); } else { - t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL); + t = (typeArrayOop)CollectedHeap::array_allocate_nozero(this, (int)size, length, CHECK_NULL); } return t; } else { diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index f519e5e2788..c38c0ee1296 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -386,8 +386,8 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) Handle loader; Handle protection_domain; // Find calling class - instanceKlassHandle k (THREAD, thread->security_get_caller_class(0)); - if (k.not_null()) { + Klass* k = thread->security_get_caller_class(0); + if (k != NULL) { loader = Handle(THREAD, k->class_loader()); // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed // in the correct class context. @@ -395,9 +395,9 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) { JavaValue result(T_OBJECT); JavaCalls::call_static(&result, k, - vmSymbols::getFromClass_name(), - vmSymbols::void_class_signature(), - thread); + vmSymbols::getFromClass_name(), + vmSymbols::void_class_signature(), + thread); if (HAS_PENDING_EXCEPTION) { Handle ex(thread, thread->pending_exception()); CLEAR_PENDING_EXCEPTION; @@ -455,12 +455,11 @@ JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) mirror = java_lang_reflect_Method::clazz(reflected); slot = java_lang_reflect_Method::slot(reflected); } - Klass* k = java_lang_Class::as_Klass(mirror); + Klass* k1 = java_lang_Class::as_Klass(mirror); - KlassHandle k1(THREAD, k); // Make sure class is initialized before handing id's out to methods - k1()->initialize(CHECK_NULL); - Method* m = InstanceKlass::cast(k1())->method_with_idnum(slot); + k1->initialize(CHECK_NULL); + Method* m = InstanceKlass::cast(k1)->method_with_idnum(slot); ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted return ret; JNI_END @@ -479,18 +478,17 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) // field is a handle to a java.lang.reflect.Field object oop reflected = JNIHandles::resolve_non_null(field); oop mirror = java_lang_reflect_Field::clazz(reflected); - Klass* k = java_lang_Class::as_Klass(mirror); + Klass* k1 = java_lang_Class::as_Klass(mirror); int slot = java_lang_reflect_Field::slot(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); - KlassHandle k1(THREAD, k); // Make sure class is initialized before handing id's out to fields - k1()->initialize(CHECK_NULL); + k1->initialize(CHECK_NULL); // First check if this is a static field if (modifiers & JVM_ACC_STATIC) { - intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot ); - JNIid* id = InstanceKlass::cast(k1())->jni_id_for(offset); + intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); + JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset); assert(id != NULL, "corrupt Field object"); debug_only(id->set_is_static_field_id();) // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass* @@ -501,9 +499,9 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) // The slot is the index of the field description in the field-array // The jfieldID is the offset of the field within the object // It may also have hash bits for k, if VerifyJNIFields is turned on. - intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot ); - assert(InstanceKlass::cast(k1())->contains_field_offset(offset), "stay within object"); - ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); + intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); + assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object"); + ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset); return ret; JNI_END @@ -677,8 +675,7 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) JavaValue result(T_VOID); JavaCalls::call_virtual(&result, ex, - KlassHandle(THREAD, - SystemDictionary::Throwable_klass()), + SystemDictionary::Throwable_klass(), vmSymbols::printStackTrace_name(), vmSymbols::void_method_signature(), THREAD); @@ -1156,11 +1153,9 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive } } else { // interface call - KlassHandle h_holder(THREAD, holder); - int itbl_index = m->itable_index(); Klass* k = h_recv->klass(); - selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); + selected_method = InstanceKlass::cast(k)->method_at_itable(holder, itbl_index, CHECK); } } @@ -1192,14 +1187,14 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive static instanceOop alloc_object(jclass clazz, TRAPS) { - KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); if (k == NULL) { ResourceMark rm(THREAD); THROW_(vmSymbols::java_lang_InstantiationException(), NULL); } - k()->check_valid_for_instantiation(false, CHECK_NULL); - InstanceKlass::cast(k())->initialize(CHECK_NULL); - instanceOop ih = InstanceKlass::cast(k())->allocate_instance(THREAD); + k->check_valid_for_instantiation(false, CHECK_NULL); + k->initialize(CHECK_NULL); + instanceOop ih = InstanceKlass::cast(k)->allocate_instance(THREAD); return ih; } @@ -1338,26 +1333,25 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); } - KlassHandle klass(THREAD, - java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); + Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); // Make sure class is linked and initialized before handing id's out to // Method*s. - klass()->initialize(CHECK_NULL); + klass->initialize(CHECK_NULL); Method* m; if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) { // Never search superclasses for constructors if (klass->is_instance_klass()) { - m = InstanceKlass::cast(klass())->find_method(name, signature); + m = InstanceKlass::cast(klass)->find_method(name, signature); } else { m = NULL; } } else { m = klass->lookup_method(name, signature); if (m == NULL && klass->is_instance_klass()) { - m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature); + m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name, signature); } } if (m == NULL || (m->is_static() != is_static)) { @@ -1879,8 +1873,8 @@ JNI_ENTRY(ResultType, \ JavaValue jvalue(Tag); \ JNI_ArgumentPusherVaArg ap(methodID, args); \ /* Make sure class is initialized before trying to invoke its method */ \ - KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); \ - k()->initialize(CHECK_0); \ + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); \ + k->initialize(CHECK_0); \ jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ va_end(args); \ ret = jvalue.get_##ResultType(); \ @@ -2037,20 +2031,19 @@ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, if (fieldname == NULL || signame == NULL) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } - KlassHandle k(THREAD, - java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); // Make sure class is initialized before handing id's out to fields - k()->initialize(CHECK_NULL); + k->initialize(CHECK_NULL); fieldDescriptor fd; - if (!k()->is_instance_klass() || - !InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) { + if (!k->is_instance_klass() || + !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } // A jfieldID for a non-static field is simply the offset of the field within the instanceOop // It may also have hash bits for k, if VerifyJNIFields is turned on. - ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset()); + ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset()); return ret; JNI_END @@ -2292,14 +2285,13 @@ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, if (fieldname == NULL || signame == NULL) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } - KlassHandle k(THREAD, - java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); // Make sure class is initialized before handing id's out to static fields - k()->initialize(CHECK_NULL); + k->initialize(CHECK_NULL); fieldDescriptor fd; - if (!k()->is_instance_klass() || - !InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) { + if (!k->is_instance_klass() || + !InstanceKlass::cast(k)->find_field(fieldname, signame, true, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } @@ -2603,11 +2595,10 @@ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass ele HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(env, length, elementClass, initialElement); jobjectArray ret = NULL; DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); - KlassHandle ek(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass))); - Klass* ako = ek()->array_klass(CHECK_NULL); - KlassHandle ak = KlassHandle(THREAD, ako); - ObjArrayKlass::cast(ak())->initialize(CHECK_NULL); - objArrayOop result = ObjArrayKlass::cast(ak())->allocate(length, CHECK_NULL); + Klass* ek = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass)); + Klass* ak = ek->array_klass(CHECK_NULL); + ObjArrayKlass::cast(ak)->initialize(CHECK_NULL); + objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL); oop initial_value = JNIHandles::resolve(initialElement); if (initial_value != NULL) { // array already initialized with NULL for (int index = 0; index < length; index++) { @@ -2936,8 +2927,7 @@ DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double // is not native. Ask JVM TI what prefixes have been specified. Then check // to see if the native method is now wrapped with the prefixes. See the // SetNativeMethodPrefix(es) functions in the JVM TI Spec for details. -static Method* find_prefixed_native(KlassHandle k, - Symbol* name, Symbol* signature, TRAPS) { +static Method* find_prefixed_native(Klass* k, Symbol* name, Symbol* signature, TRAPS) { #if INCLUDE_JVMTI ResourceMark rm(THREAD); Method* method; @@ -2958,7 +2948,7 @@ static Method* find_prefixed_native(KlassHandle k, if (trial_name == NULL) { continue; // no such symbol, so this prefix wasn't used, try the next prefix } - method = k()->lookup_method(trial_name, signature); + method = k->lookup_method(trial_name, signature); if (method == NULL) { continue; // signature doesn't match, try the next prefix } @@ -2974,13 +2964,13 @@ static Method* find_prefixed_native(KlassHandle k, return NULL; // not found } -static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) { - Method* method = k()->lookup_method(name, signature); +static bool register_native(Klass* k, Symbol* name, Symbol* signature, address entry, TRAPS) { + Method* method = k->lookup_method(name, signature); if (method == NULL) { ResourceMark rm; stringStream st; st.print("Method %s name or signature does not match", - Method::name_and_sig_as_C_string(k(), name, signature)); + Method::name_and_sig_as_C_string(k, name, signature)); THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); } if (!method->is_native()) { @@ -2990,7 +2980,7 @@ static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, addr ResourceMark rm; stringStream st; st.print("Method %s is not declared as native", - Method::name_and_sig_as_C_string(k(), name, signature)); + Method::name_and_sig_as_C_string(k, name, signature)); THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); } } @@ -3021,7 +3011,7 @@ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, jint ret = 0; DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret); - KlassHandle h_k(thread, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); for (int index = 0; index < nMethods; index++) { const char* meth_name = methods[index].name; @@ -3037,12 +3027,12 @@ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, if (name == NULL || signature == NULL) { ResourceMark rm; stringStream st; - st.print("Method %s.%s%s not found", h_k()->external_name(), meth_name, meth_sig); + st.print("Method %s.%s%s not found", k->external_name(), meth_name, meth_sig); // Must return negative value on failure THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1); } - bool res = register_native(h_k, name, signature, + bool res = register_native(k, name, signature, (address) methods[index].fnPtr, THREAD); if (!res) { ret = -1; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 8da1e5d3ef1..f41c4a55afa 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -341,7 +341,7 @@ static void set_property(Handle props, const char* key, const char* value, TRAPS Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK); JavaCalls::call_virtual(&r, props, - KlassHandle(THREAD, SystemDictionary::Properties_klass()), + SystemDictionary::Properties_klass(), vmSymbols::put_name(), vmSymbols::object_object_object_signature(), key_str, @@ -621,7 +621,7 @@ JVM_END JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) JVMWrapper("JVM_Clone"); Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); - const KlassHandle klass (THREAD, obj->klass()); + Klass* klass = obj->klass(); JvmtiVMObjectAllocEventCollector oam; #ifdef ASSERT @@ -997,9 +997,7 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name) if (k == NULL) { // If the class is not already loaded, try to see if it's in the shared // archive for the current classloader (h_loader). - instanceKlassHandle ik = SystemDictionaryShared::find_or_load_shared_class( - klass_name, h_loader, CHECK_NULL); - k = ik(); + k = SystemDictionaryShared::find_or_load_shared_class(klass_name, h_loader, CHECK_NULL); } #endif return (k == NULL) ? NULL : @@ -1077,11 +1075,11 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) return (jobjectArray) JNIHandles::make_local(env, r); } - KlassHandle klass(thread, java_lang_Class::as_Klass(mirror)); + Klass* klass = java_lang_Class::as_Klass(mirror); // Figure size of result array int size; if (klass->is_instance_klass()) { - size = InstanceKlass::cast(klass())->local_interfaces()->length(); + size = InstanceKlass::cast(klass)->local_interfaces()->length(); } else { assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass"); size = 2; @@ -1094,7 +1092,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) if (klass->is_instance_klass()) { // Regular instance klass, fill in all local interfaces for (int index = 0; index < size; index++) { - Klass* k = InstanceKlass::cast(klass())->local_interfaces()->at(index); + Klass* k = InstanceKlass::cast(klass)->local_interfaces()->at(index); result->obj_at_put(index, k->java_mirror()); } } else { @@ -1178,7 +1176,7 @@ JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls)) JVM_END -static bool is_authorized(Handle context, instanceKlassHandle klass, TRAPS) { +static bool is_authorized(Handle context, InstanceKlass* klass, TRAPS) { // If there is a security manager and protection domain, check the access // in the protection domain, otherwise it is authorized. if (java_lang_System::has_security_manager()) { @@ -1218,7 +1216,7 @@ oop create_dummy_access_control_context(TRAPS) { Handle obj = pd_klass->allocate_instance_handle(CHECK_NULL); // Call constructor ProtectionDomain(null, null); JavaValue result(T_VOID); - JavaCalls::call_special(&result, obj, KlassHandle(THREAD, pd_klass), + JavaCalls::call_special(&result, obj, pd_klass, vmSymbols::object_initializer_name(), vmSymbols::codesource_permissioncollection_signature(), Handle(), Handle(), CHECK_NULL); @@ -1249,7 +1247,7 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job } Method* method = vfst.method(); - instanceKlassHandle klass (THREAD, method->method_holder()); + InstanceKlass* klass = method->method_holder(); // Check that action object understands "Object run()" Handle h_context; @@ -1452,7 +1450,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) return (jobjectArray)JNIHandles::make_local(env, result); } - instanceKlassHandle k(thread, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); + InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); InnerClassesIterator iter(k); if (iter.length() == 0) { @@ -1479,9 +1477,9 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) // before attempting to find the class. if (cp->klass_name_at_matches(k, ooff)) { Klass* outer_klass = cp->klass_at(ooff, CHECK_NULL); - if (outer_klass == k()) { + if (outer_klass == k) { Klass* ik = cp->klass_at(ioff, CHECK_NULL); - instanceKlassHandle inner_klass (THREAD, ik); + InstanceKlass* inner_klass = InstanceKlass::cast(ik); // Throws an exception if outer klass has not declared k as // an inner klass @@ -1532,7 +1530,7 @@ JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls)) !java_lang_Class::as_Klass(mirror)->is_instance_klass()) { return NULL; } - instanceKlassHandle k(THREAD, InstanceKlass::cast(java_lang_Class::as_Klass(mirror))); + InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); int ooff = 0, noff = 0; if (InstanceKlass::find_inner_classes_attr(k, &ooff, &noff, THREAD)) { if (noff != 0) { @@ -1590,19 +1588,19 @@ static bool jvm_get_field_common(jobject field, fieldDescriptor& fd, TRAPS) { int slot = java_lang_reflect_Field::slot(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); - KlassHandle kh(THREAD, k); - intptr_t offset = InstanceKlass::cast(kh())->field_offset(slot); + InstanceKlass* ik = InstanceKlass::cast(k); + intptr_t offset = ik->field_offset(slot); if (modifiers & JVM_ACC_STATIC) { // for static fields we only look in the current class - if (!InstanceKlass::cast(kh())->find_local_field_from_offset(offset, true, &fd)) { + if (!ik->find_local_field_from_offset(offset, true, &fd)) { assert(false, "cannot find static field"); return false; } } else { // for instance fields we start with the current class and work // our way up through the superclass chain - if (!InstanceKlass::cast(kh())->find_field_from_offset(offset, false, &fd)) { + if (!ik->find_field_from_offset(offset, false, &fd)) { assert(false, "cannot find instance field"); return false; } @@ -1757,7 +1755,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, return (jobjectArray) JNIHandles::make_local(env, res); } - instanceKlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); + InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); constantPoolHandle cp(THREAD, k->constants()); // Ensure class is linked @@ -1768,7 +1766,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, if (publicOnly) { num_fields = 0; - for (JavaFieldStream fs(k()); !fs.done(); fs.next()) { + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (fs.access_flags().is_public()) ++num_fields; } } else { @@ -1782,7 +1780,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, fieldDescriptor fd; for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (!publicOnly || fs.access_flags().is_public()) { - fd.reinitialize(k(), fs.index()); + fd.reinitialize(k, fs.index()); oop field = Reflection::new_field(&fd, CHECK_NULL); result->obj_at_put(out_idx, field); ++out_idx; @@ -1817,7 +1815,7 @@ static jobjectArray get_class_declared_methods_helper( return (jobjectArray) JNIHandles::make_local(env, res); } - instanceKlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); + InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); // Ensure class is linked k->link_class(CHECK_NULL); @@ -1913,7 +1911,7 @@ JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls)) if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); if (k->is_instance_klass()) { - instanceKlassHandle k_h(THREAD, k); + InstanceKlass* k_h = InstanceKlass::cast(k); Handle jcp = reflect_ConstantPool::create(CHECK_NULL); reflect_ConstantPool::set_cp(jcp(), k_h->constants()); return JNIHandles::make_local(jcp()); @@ -1975,7 +1973,7 @@ static jobject get_method_at_helper(constantPoolHandle cp, jint index, bool forc k_o = ConstantPool::klass_at_if_loaded(cp, klass_ref); if (k_o == NULL) return NULL; } - instanceKlassHandle k(THREAD, k_o); + InstanceKlass* k = InstanceKlass::cast(k_o); Symbol* name = cp->uncached_name_ref_at(index); Symbol* sig = cp->uncached_signature_ref_at(index); methodHandle m (THREAD, k->find_method(name, sig)); @@ -2026,7 +2024,7 @@ static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force k_o = ConstantPool::klass_at_if_loaded(cp, klass_ref); if (k_o == NULL) return NULL; } - instanceKlassHandle k(THREAD, k_o); + InstanceKlass* k = InstanceKlass::cast(k_o); Symbol* name = cp->uncached_name_ref_at(index); Symbol* sig = cp->uncached_signature_ref_at(index); fieldDescriptor fd; @@ -2616,7 +2614,8 @@ JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, j case JVM_CONSTANT_Fieldref: { Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - for (JavaFieldStream fs(k_called); !fs.done(); fs.next()) { + InstanceKlass* ik = InstanceKlass::cast(k_called); + for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { if (fs.name() == name && fs.signature() == signature) { return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS; } @@ -2770,7 +2769,7 @@ static void thread_entry(JavaThread* thread, TRAPS) { JavaValue result(T_VOID); JavaCalls::call_virtual(&result, obj, - KlassHandle(THREAD, SystemDictionary::Thread_klass()), + SystemDictionary::Thread_klass(), vmSymbols::run_method_name(), vmSymbols::void_method_signature(), THREAD); @@ -3226,7 +3225,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env)) } // Collect method holders - GrowableArray* klass_array = new GrowableArray(); + GrowableArray* klass_array = new GrowableArray(); for (; !vfst.at_end(); vfst.security_next()) { Method* m = vfst.method(); // Native frames are not returned @@ -3593,12 +3592,11 @@ jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, // if there is no security manager in 3-arg Class.forName(). Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); - KlassHandle klass_handle(THREAD, klass); // Check if we should initialize the class - if (init && klass_handle->is_instance_klass()) { - klass_handle->initialize(CHECK_NULL); + if (init && klass->is_instance_klass()) { + klass->initialize(CHECK_NULL); } - return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror()); + return (jclass) JNIHandles::make_local(env, klass->java_mirror()); } @@ -3746,25 +3744,25 @@ JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)) if (!k->is_instance_klass()) { return NULL; } - instanceKlassHandle ik_h(THREAD, k); - int encl_method_class_idx = ik_h->enclosing_method_class_index(); + InstanceKlass* ik = InstanceKlass::cast(k); + int encl_method_class_idx = ik->enclosing_method_class_index(); if (encl_method_class_idx == 0) { return NULL; } objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); - Klass* enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL); + Klass* enc_k = ik->constants()->klass_at(encl_method_class_idx, CHECK_NULL); dest->obj_at_put(0, enc_k->java_mirror()); - int encl_method_method_idx = ik_h->enclosing_method_method_index(); + int encl_method_method_idx = ik->enclosing_method_method_index(); if (encl_method_method_idx != 0) { - Symbol* sym = ik_h->constants()->symbol_at( + Symbol* sym = ik->constants()->symbol_at( extract_low_short_from_int( - ik_h->constants()->name_and_type_at(encl_method_method_idx))); + ik->constants()->name_and_type_at(encl_method_method_idx))); Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); dest->obj_at_put(1, str()); - sym = ik_h->constants()->symbol_at( + sym = ik->constants()->symbol_at( extract_high_short_from_int( - ik_h->constants()->name_and_type_at(encl_method_method_idx))); + ik->constants()->name_and_type_at(encl_method_method_idx))); str = java_lang_String::create_from_symbol(sym, CHECK_NULL); dest->obj_at_put(2, str()); } @@ -3799,8 +3797,8 @@ JVM_ENTRY(jobjectArray, JVM_GetVmArguments(JNIEnv *env)) int num_flags = Arguments::num_jvm_flags(); int num_args = Arguments::num_jvm_args(); - instanceKlassHandle ik (THREAD, SystemDictionary::String_klass()); - objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL); + InstanceKlass* ik = SystemDictionary::String_klass(); + objArrayOop r = oopFactory::new_objArray(ik, num_args + num_flags, CHECK_NULL); objArrayHandle result_h(THREAD, r); int index = 0; diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp index c197919eb1c..1ee825f78c3 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -40,20 +40,20 @@ // JVMSpec| field_info fields[fields_count]; void JvmtiClassFileReconstituter::write_field_infos() { HandleMark hm(thread()); - Array* fields_anno = ikh()->fields_annotations(); - Array* fields_type_anno = ikh()->fields_type_annotations(); + Array* fields_anno = ik()->fields_annotations(); + Array* fields_type_anno = ik()->fields_type_annotations(); // Compute the real number of Java fields - int java_fields = ikh()->java_fields_count(); + int java_fields = ik()->java_fields_count(); write_u2(java_fields); - for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) { + for (JavaFieldStream fs(ik()); !fs.done(); fs.next()) { AccessFlags access_flags = fs.access_flags(); int name_index = fs.name_index(); int signature_index = fs.signature_index(); int initial_value_index = fs.initval_index(); guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field"); - // int offset = ikh()->field_offset( index ); + // int offset = ik()->field_offset( index ); int generic_signature_index = fs.generic_signature_index(); AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index()); AnnotationArray* type_anno = fields_type_anno == NULL ? NULL : fields_type_anno->at(fs.index()); @@ -278,11 +278,11 @@ void JvmtiClassFileReconstituter::write_exceptions_attribute(ConstMethod* const_ // JVMSpec| u2 sourcefile_index; // JVMSpec| } void JvmtiClassFileReconstituter::write_source_file_attribute() { - assert(ikh()->source_file_name() != NULL, "caller must check"); + assert(ik()->source_file_name() != NULL, "caller must check"); write_attribute_name_index("SourceFile"); write_u4(2); // always length 2 - write_u2(symbol_to_cpool_index(ikh()->source_file_name())); + write_u2(symbol_to_cpool_index(ik()->source_file_name())); } // Write SourceDebugExtension attribute @@ -292,12 +292,12 @@ void JvmtiClassFileReconstituter::write_source_file_attribute() { // JSR45| u1 debug_extension[attribute_length]; // JSR45| } void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() { - assert(ikh()->source_debug_extension() != NULL, "caller must check"); + assert(ik()->source_debug_extension() != NULL, "caller must check"); write_attribute_name_index("SourceDebugExtension"); - int len = (int)strlen(ikh()->source_debug_extension()); + int len = (int)strlen(ik()->source_debug_extension()); write_u4(len); - u1* ext = (u1*)ikh()->source_debug_extension(); + u1* ext = (u1*)ik()->source_debug_extension(); for (int i=0; igeneric_signature(); - AnnotationArray* anno = ikh()->class_annotations(); - AnnotationArray* type_anno = ikh()->class_type_annotations(); + Symbol* generic_signature = ik()->generic_signature(); + AnnotationArray* anno = ik()->class_annotations(); + AnnotationArray* type_anno = ik()->class_type_annotations(); int attr_count = 0; if (generic_signature != NULL) { ++attr_count; } - if (ikh()->source_file_name() != NULL) { + if (ik()->source_file_name() != NULL) { ++attr_count; } - if (ikh()->source_debug_extension() != NULL) { + if (ik()->source_debug_extension() != NULL) { ++attr_count; } if (inner_classes_length > 0) { @@ -650,10 +650,10 @@ void JvmtiClassFileReconstituter::write_class_attributes() { if (generic_signature != NULL) { write_signature_attribute(symbol_to_cpool_index(generic_signature)); } - if (ikh()->source_file_name() != NULL) { + if (ik()->source_file_name() != NULL) { write_source_file_attribute(); } - if (ikh()->source_debug_extension() != NULL) { + if (ik()->source_debug_extension() != NULL) { write_source_debug_extension_attribute(); } if (inner_classes_length > 0) { @@ -675,7 +675,7 @@ void JvmtiClassFileReconstituter::write_class_attributes() { // JVMSpec| method_info methods[methods_count]; void JvmtiClassFileReconstituter::write_method_infos() { HandleMark hm(thread()); - Array* methods = ikh()->methods(); + Array* methods = ik()->methods(); int num_methods = methods->length(); int num_overpass = 0; @@ -697,7 +697,7 @@ void JvmtiClassFileReconstituter::write_method_infos() { // invert the method order mapping for (index = 0; index < num_methods; index++) { - original_index = ikh()->method_ordering()->at(index); + original_index = ik()->method_ordering()->at(index); assert(original_index >= 0 && original_index < num_methods, "invalid original method index"); method_order.at_put(original_index, index); @@ -727,8 +727,8 @@ void JvmtiClassFileReconstituter::write_class_file_format() { // JVMSpec| u2 minor_version; // JVMSpec| u2 major_version; - write_u2(ikh()->minor_version()); - u2 major = ikh()->major_version(); + write_u2(ik()->minor_version()); + u2 major = ik()->major_version(); write_u2(major); // JVMSpec| u2 constant_pool_count; @@ -737,24 +737,24 @@ void JvmtiClassFileReconstituter::write_class_file_format() { copy_cpool_bytes(writeable_address(cpool_size())); // JVMSpec| u2 access_flags; - write_u2(ikh()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS); + write_u2(ik()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS); // JVMSpec| u2 this_class; // JVMSpec| u2 super_class; - write_u2(class_symbol_to_cpool_index(ikh()->name())); - Klass* super_class = ikh()->super(); + write_u2(class_symbol_to_cpool_index(ik()->name())); + Klass* super_class = ik()->super(); write_u2(super_class == NULL? 0 : // zero for java.lang.Object class_symbol_to_cpool_index(super_class->name())); // JVMSpec| u2 interfaces_count; // JVMSpec| u2 interfaces[interfaces_count]; - Array* interfaces = ikh()->local_interfaces(); + Array* interfaces = ik()->local_interfaces(); int num_interfaces = interfaces->length(); write_u2(num_interfaces); for (int index = 0; index < num_interfaces; index++) { HandleMark hm(thread()); - instanceKlassHandle iikh(thread(), interfaces->at(index)); - write_u2(class_symbol_to_cpool_index(iikh->name())); + InstanceKlass* iik = InstanceKlass::cast(interfaces->at(index)); + write_u2(class_symbol_to_cpool_index(iik->name())); } // JVMSpec| u2 fields_count; diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp index 0dfdec9532c..f3b6349d9ef 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,11 +34,11 @@ class JvmtiConstantPoolReconstituter : public StackObj { SymbolHashMap* _symmap; SymbolHashMap* _classmap; constantPoolHandle _cpool; - instanceKlassHandle _ikh; + InstanceKlass* _ik; jvmtiError _err; protected: - instanceKlassHandle ikh() { return _ikh; }; + InstanceKlass* ik() { return _ik; }; constantPoolHandle cpool() { return _cpool; }; u2 symbol_to_cpool_index(Symbol* sym) { @@ -52,10 +52,10 @@ class JvmtiConstantPoolReconstituter : public StackObj { public: // Calls to this constructor must be proceeded by a ResourceMark // and a HandleMark - JvmtiConstantPoolReconstituter(instanceKlassHandle ikh){ + JvmtiConstantPoolReconstituter(InstanceKlass* ik){ set_error(JVMTI_ERROR_NONE); - _ikh = ikh; - _cpool = constantPoolHandle(Thread::current(), ikh->constants()); + _ik = ik; + _cpool = constantPoolHandle(Thread::current(), ik->constants()); _symmap = new SymbolHashMap(); _classmap = new SymbolHashMap(); _cpool_size = _cpool->hash_entries_to(_symmap, _classmap); @@ -138,8 +138,8 @@ class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter { public: // Calls to this constructor must be proceeded by a ResourceMark // and a HandleMark - JvmtiClassFileReconstituter(instanceKlassHandle ikh) : - JvmtiConstantPoolReconstituter(ikh) { + JvmtiClassFileReconstituter(InstanceKlass* ik) : + JvmtiConstantPoolReconstituter(ik) { _buffer_size = initial_buffer_size; _buffer = _buffer_ptr = NEW_RESOURCE_ARRAY(u1, _buffer_size); _thread = Thread::current(); diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index f9dc315a552..16ade16ac61 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -400,21 +400,20 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { return JVMTI_ERROR_UNMODIFIABLE_CLASS; } - Klass* k_oop = java_lang_Class::as_Klass(k_mirror); - KlassHandle klass(current_thread, k_oop); + Klass* klass = java_lang_Class::as_Klass(k_mirror); jint status = klass->jvmti_class_status(); if (status & (JVMTI_CLASS_STATUS_ERROR)) { return JVMTI_ERROR_INVALID_CLASS; } - instanceKlassHandle ikh(current_thread, k_oop); - if (ikh->get_cached_class_file_bytes() == NULL) { + InstanceKlass* ik = InstanceKlass::cast(klass); + if (ik->get_cached_class_file_bytes() == NULL) { // Not cached, we need to reconstitute the class file from the // VM representation. We don't attach the reconstituted class // bytes to the InstanceKlass here because they have not been // validated and we're not at a safepoint. - JvmtiClassFileReconstituter reconstituter(ikh); + JvmtiClassFileReconstituter reconstituter(ik); if (reconstituter.get_error() != JVMTI_ERROR_NONE) { return reconstituter.get_error(); } @@ -424,8 +423,8 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { reconstituter.class_file_bytes(); } else { // it is cached, get it from the cache - class_definitions[index].class_byte_count = ikh->get_cached_class_file_len(); - class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes(); + class_definitions[index].class_byte_count = ik->get_cached_class_file_len(); + class_definitions[index].class_bytes = ik->get_cached_class_file_bytes(); } class_definitions[index].klass = jcls; } @@ -667,8 +666,6 @@ JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) { return JVMTI_ERROR_INTERNAL; } - instanceKlassHandle loader_ik(THREAD, loader->klass()); - // Invoke the appendToClassPathForInstrumentation method - if the method // is not found it means the loader doesn't support adding to the class path // in the live phase. @@ -676,7 +673,7 @@ JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) { JavaValue res(T_VOID); JavaCalls::call_special(&res, loader, - loader_ik, + loader->klass(), vmSymbols::appendToClassPathForInstrumentation_name(), vmSymbols::appendToClassPathForInstrumentation_signature(), path, @@ -1781,7 +1778,7 @@ JvmtiEnv::ForceEarlyReturnVoid(JavaThread* java_thread) { jvmtiError JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) { // check klass if provided - Klass* k_oop = NULL; + Klass* k = NULL; if (klass != NULL) { oop k_mirror = JNIHandles::resolve_external_guard(klass); if (k_mirror == NULL) { @@ -1790,18 +1787,17 @@ JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_objec if (java_lang_Class::is_primitive(k_mirror)) { return JVMTI_ERROR_NONE; } - k_oop = java_lang_Class::as_Klass(k_mirror); - if (k_oop == NULL) { + k = java_lang_Class::as_Klass(k_mirror); + if (klass == NULL) { return JVMTI_ERROR_INVALID_CLASS; } } Thread *thread = Thread::current(); HandleMark hm(thread); - KlassHandle kh (thread, k_oop); TraceTime t("FollowReferences", TRACETIME_LOG(Debug, jvmti, objecttagging)); - JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, kh, initial_object, callbacks, user_data); + JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, k, initial_object, callbacks, user_data); return JVMTI_ERROR_NONE; } /* end FollowReferences */ @@ -1812,7 +1808,7 @@ JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_objec jvmtiError JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { // check klass if provided - Klass* k_oop = NULL; + Klass* k = NULL; if (klass != NULL) { oop k_mirror = JNIHandles::resolve_external_guard(klass); if (k_mirror == NULL) { @@ -1821,18 +1817,14 @@ JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCall if (java_lang_Class::is_primitive(k_mirror)) { return JVMTI_ERROR_NONE; } - k_oop = java_lang_Class::as_Klass(k_mirror); - if (k_oop == NULL) { + k = java_lang_Class::as_Klass(k_mirror); + if (k == NULL) { return JVMTI_ERROR_INVALID_CLASS; } } - Thread *thread = Thread::current(); - HandleMark hm(thread); - KlassHandle kh (thread, k_oop); - TraceTime t("IterateThroughHeap", TRACETIME_LOG(Debug, jvmti, objecttagging)); - JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, kh, callbacks, user_data); + JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, k, callbacks, user_data); return JVMTI_ERROR_NONE; } /* end IterateThroughHeap */ @@ -1909,7 +1901,7 @@ JvmtiEnv::IterateOverHeap(jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCa TraceTime t("IterateOverHeap", TRACETIME_LOG(Debug, jvmti, objecttagging)); Thread *thread = Thread::current(); HandleMark hm(thread); - JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, KlassHandle(), heap_object_callback, user_data); + JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, NULL, heap_object_callback, user_data); return JVMTI_ERROR_NONE; } /* end IterateOverHeap */ @@ -1923,13 +1915,10 @@ JvmtiEnv::IterateOverInstancesOfClass(oop k_mirror, jvmtiHeapObjectFilter object // DO PRIMITIVE CLASS PROCESSING return JVMTI_ERROR_NONE; } - Klass* k_oop = java_lang_Class::as_Klass(k_mirror); - if (k_oop == NULL) { + Klass* klass = java_lang_Class::as_Klass(k_mirror); + if (klass == NULL) { return JVMTI_ERROR_INVALID_CLASS; } - Thread *thread = Thread::current(); - HandleMark hm(thread); - KlassHandle klass (thread, k_oop); TraceTime t("IterateOverInstancesOfClass", TRACETIME_LOG(Debug, jvmti, objecttagging)); JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, klass, heap_object_callback, user_data); return JVMTI_ERROR_NONE; @@ -2408,9 +2397,9 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); return JVMTI_ERROR_NONE; } - instanceKlassHandle instanceK_h(current_thread, k); + InstanceKlass* ik = InstanceKlass::cast(k); // Allocate the result and fill it in - int result_length = instanceK_h->methods()->length(); + int result_length = ik->methods()->length(); jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); int index; bool jmethodids_found = true; @@ -2419,8 +2408,8 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth // Use the original method ordering indices stored in the class, so we can emit // jmethodIDs in the order they appeared in the class file for (index = 0; index < result_length; index++) { - Method* m = instanceK_h->methods()->at(index); - int original_index = instanceK_h->method_ordering()->at(index); + Method* m = ik->methods()->at(index); + int original_index = ik->method_ordering()->at(index); assert(original_index >= 0 && original_index < result_length, "invalid original method index"); jmethodID id; if (jmethodids_found) { @@ -2429,7 +2418,7 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth // If we find an uninitialized value, make sure there is // enough space for all the uninitialized values we might // find. - instanceK_h->ensure_space_for_methodids(index); + ik->ensure_space_for_methodids(index); jmethodids_found = false; id = m->jmethod_id(); } @@ -2441,7 +2430,7 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth } else { // otherwise just copy in any order for (index = 0; index < result_length; index++) { - Method* m = instanceK_h->methods()->at(index); + Method* m = ik->methods()->at(index); jmethodID id; if (jmethodids_found) { id = m->find_jmethod_id_or_null(); @@ -2449,7 +2438,7 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth // If we find an uninitialized value, make sure there is // enough space for all the uninitialized values we might // find. - instanceK_h->ensure_space_for_methodids(index); + ik->ensure_space_for_methodids(index); jmethodids_found = false; id = m->jmethod_id(); } @@ -2494,11 +2483,11 @@ JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ } - instanceKlassHandle instanceK_h(current_thread, k); + InstanceKlass* ik = InstanceKlass::cast(k); int result_count = 0; // First, count the fields. - FilteredFieldStream flds(instanceK_h, true, true); + FilteredFieldStream flds(ik, true, true); result_count = flds.field_count(); // Allocate the result and fill it in @@ -2507,9 +2496,9 @@ JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ // this is the reverse order of what FieldStream hands out. int id_index = (result_count - 1); - for (FilteredFieldStream src_st(instanceK_h, true, true); !src_st.eos(); src_st.next()) { + for (FilteredFieldStream src_st(ik, true, true); !src_st.eos(); src_st.next()) { result_list[id_index--] = jfieldIDWorkaround::to_jfieldID( - instanceK_h, src_st.offset(), + ik, src_st.offset(), src_st.access_flags().is_static()); } assert(id_index == -1, "just checking"); @@ -2574,10 +2563,7 @@ JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* ma if (java_lang_Class::is_primitive(k_mirror)) { return JVMTI_ERROR_ABSENT_INFORMATION; } - Klass* k_oop = java_lang_Class::as_Klass(k_mirror); - Thread *thread = Thread::current(); - HandleMark hm(thread); - KlassHandle klass(thread, k_oop); + Klass* klass = java_lang_Class::as_Klass(k_mirror); jint status = klass->jvmti_class_status(); if (status & (JVMTI_CLASS_STATUS_ERROR)) { @@ -2587,7 +2573,7 @@ JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* ma return JVMTI_ERROR_ABSENT_INFORMATION; } - instanceKlassHandle ik(thread, k_oop); + InstanceKlass* ik = InstanceKlass::cast(klass); *minor_version_ptr = ik->minor_version(); *major_version_ptr = ik->major_version(); @@ -2605,11 +2591,9 @@ JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* con return JVMTI_ERROR_ABSENT_INFORMATION; } - Klass* k_oop = java_lang_Class::as_Klass(k_mirror); + Klass* klass = java_lang_Class::as_Klass(k_mirror); Thread *thread = Thread::current(); - HandleMark hm(thread); ResourceMark rm(thread); - KlassHandle klass(thread, k_oop); jint status = klass->jvmti_class_status(); if (status & (JVMTI_CLASS_STATUS_ERROR)) { @@ -2619,8 +2603,8 @@ JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* con return JVMTI_ERROR_ABSENT_INFORMATION; } - instanceKlassHandle ikh(thread, k_oop); - JvmtiConstantPoolReconstituter reconstituter(ikh); + InstanceKlass* ik = InstanceKlass::cast(klass); + JvmtiConstantPoolReconstituter reconstituter(ik); if (reconstituter.get_error() != JVMTI_ERROR_NONE) { return reconstituter.get_error(); } @@ -2639,7 +2623,7 @@ JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* con return reconstituter.get_error(); } - constantPoolHandle constants(thread, ikh->constants()); + constantPoolHandle constants(thread, ik->constants()); *constant_pool_count_ptr = constants->length(); *constant_pool_byte_count_ptr = cpool_size; *constant_pool_bytes_ptr = cpool_bytes; diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index f3018e13c0b..09c4134261e 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1366,13 +1366,13 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa if (tos == atos && jobj != NULL) { // NULL reference is allowed Handle ob_h(current_thread, JNIHandles::resolve_external_guard(jobj)); NULL_CHECK(ob_h, JVMTI_ERROR_INVALID_OBJECT); - KlassHandle ob_kh = KlassHandle(current_thread, ob_h()->klass()); - NULL_CHECK(ob_kh, JVMTI_ERROR_INVALID_OBJECT); + Klass* ob_k = ob_h()->klass(); + NULL_CHECK(ob_k, JVMTI_ERROR_INVALID_OBJECT); // Method return type signature. char* ty_sign = 1 + strchr(signature->as_C_string(), ')'); - if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_kh(), current_thread)) { + if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_k, current_thread)) { return JVMTI_ERROR_TYPE_MISMATCH; } *ret_ob_h = ob_h; diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index ad7984c4a8f..0d41a17de6e 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -267,14 +267,14 @@ private: public: JvmtiClassFileLoadEventMark(JavaThread *thread, Symbol* name, - Handle class_loader, Handle prot_domain, KlassHandle *class_being_redefined) : JvmtiThreadEventMark(thread) { + Handle class_loader, Handle prot_domain, Klass* class_being_redefined) : JvmtiThreadEventMark(thread) { _class_name = name != NULL? name->as_utf8() : NULL; _jloader = (jobject)to_jobject(class_loader()); _protection_domain = (jobject)to_jobject(prot_domain()); if (class_being_redefined == NULL) { _class_being_redefined = NULL; } else { - _class_being_redefined = (jclass)to_jclass((*class_being_redefined)()); + _class_being_redefined = (jclass)to_jclass(class_being_redefined); } }; const char *class_name() { @@ -735,7 +735,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { JvmtiEnv * _curr_env; JvmtiCachedClassFileData ** _cached_class_file_ptr; JvmtiThreadState * _state; - KlassHandle * _h_class_being_redefined; + Klass* _class_being_redefined; JvmtiClassLoadKind _load_kind; bool _has_been_modified; @@ -758,9 +758,9 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _state = _thread->jvmti_thread_state(); if (_state != NULL) { - _h_class_being_redefined = _state->get_class_being_redefined(); + _class_being_redefined = _state->get_class_being_redefined(); _load_kind = _state->get_class_load_kind(); - Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)(); + Klass* klass = (_class_being_redefined == NULL) ? NULL : _class_being_redefined; if (_load_kind != jvmti_class_load_kind_load && klass != NULL) { ModuleEntry* module_entry = InstanceKlass::cast(klass)->module(); assert(module_entry != NULL, "module_entry should always be set"); @@ -783,7 +783,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _state->clear_class_being_redefined(); } else { // redefine and retransform will always set the thread state - _h_class_being_redefined = (KlassHandle *) NULL; + _class_being_redefined = NULL; _load_kind = jvmti_class_load_kind_load; } } @@ -828,7 +828,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { jint new_len = 0; JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader, _h_protection_domain, - _h_class_being_redefined); + _class_being_redefined); JvmtiJavaThreadEventTransition jet(_thread); jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook; if (callback != NULL) { @@ -1155,7 +1155,6 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) { return; } HandleMark hm(thread); - KlassHandle kh(thread, klass); EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_LOAD, ("[%s] Trg Class Load triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -1172,8 +1171,8 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) { } EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("[%s] Evt Class Load sent %s", JvmtiTrace::safe_get_thread_name(thread), - kh()==NULL? "NULL" : kh()->external_name() )); - JvmtiClassEventMark jem(thread, kh()); + klass==NULL? "NULL" : klass->external_name() )); + JvmtiClassEventMark jem(thread, klass); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventClassLoad callback = env->callbacks()->ClassLoad; if (callback != NULL) { @@ -1189,7 +1188,6 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) { return; } HandleMark hm(thread); - KlassHandle kh(thread, klass); EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("[%s] Trg Class Prepare triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -1206,8 +1204,8 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) { } EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("[%s] Evt Class Prepare sent %s", JvmtiTrace::safe_get_thread_name(thread), - kh()==NULL? "NULL" : kh()->external_name() )); - JvmtiClassEventMark jem(thread, kh()); + klass==NULL? "NULL" : klass->external_name() )); + JvmtiClassEventMark jem(thread, klass); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare; if (callback != NULL) { @@ -1223,7 +1221,6 @@ void JvmtiExport::post_class_unload(Klass* klass) { } Thread *thread = Thread::current(); HandleMark hm(thread); - KlassHandle kh(thread, klass); EVT_TRIG_TRACE(EXT_EVENT_CLASS_UNLOAD, ("[?] Trg Class Unload triggered" )); if (JvmtiEventController::is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) { @@ -1244,12 +1241,12 @@ void JvmtiExport::post_class_unload(Klass* klass) { } if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) { EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("[?] Evt Class Unload sent %s", - kh()==NULL? "NULL" : kh()->external_name() )); + klass==NULL? "NULL" : klass->external_name() )); // do everything manually, since this is a proxy - needs special care JNIEnv* jni_env = real_thread->jni_environment(); jthread jt = (jthread)JNIHandles::make_local(real_thread, real_thread->threadObj()); - jclass jk = (jclass)JNIHandles::make_local(real_thread, kh()->java_mirror()); + jclass jk = (jclass)JNIHandles::make_local(real_thread, klass->java_mirror()); // Before we call the JVMTI agent, we have to set the state in the // thread for which we are proxying. @@ -1595,7 +1592,7 @@ void JvmtiExport::post_exception_throw(JavaThread *thread, Method* method, addre current_bci = st.bci(); do { should_repeat = false; - KlassHandle eh_klass(thread, exception_handle()->klass()); + Klass* eh_klass = exception_handle()->klass(); current_bci = Method::fast_exception_handler_bci_for( current_mh, eh_klass, current_bci, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -1743,7 +1740,6 @@ void JvmtiExport::post_field_access_by_jni(JavaThread *thread, oop obj, if (!fd.is_field_access_watched()) return; HandleMark hm(thread); - KlassHandle h_klass(thread, klass); Handle h_obj; if (!is_static) { // non-static field accessors have an object, but we need a handle @@ -1753,11 +1749,11 @@ void JvmtiExport::post_field_access_by_jni(JavaThread *thread, oop obj, post_field_access(thread, thread->last_frame().interpreter_frame_method(), thread->last_frame().interpreter_frame_bcp(), - h_klass, h_obj, fieldID); + klass, h_obj, fieldID); } void JvmtiExport::post_field_access(JavaThread *thread, Method* method, - address location, KlassHandle field_klass, Handle object, jfieldID field) { + address location, Klass* field_klass, Handle object, jfieldID field) { HandleMark hm(thread); methodHandle mh(thread, method); @@ -1779,7 +1775,7 @@ void JvmtiExport::post_field_access(JavaThread *thread, Method* method, JvmtiEnv *env = ets->get_env(); JvmtiLocationEventMark jem(thread, mh, location); - jclass field_jclass = jem.to_jclass(field_klass()); + jclass field_jclass = jem.to_jclass(field_klass); jobject field_jobject = jem.to_jobject(object()); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventFieldAccess callback = env->callbacks()->FieldAccess; @@ -1847,22 +1843,21 @@ void JvmtiExport::post_field_modification_by_jni(JavaThread *thread, oop obj, assert(obj != NULL, "non-static needs an object"); h_obj = Handle(thread, obj); } - KlassHandle h_klass(thread, klass); post_field_modification(thread, thread->last_frame().interpreter_frame_method(), thread->last_frame().interpreter_frame_bcp(), - h_klass, h_obj, fieldID, sig_type, value); + klass, h_obj, fieldID, sig_type, value); } void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method, - address location, KlassHandle field_klass, Handle object, jfieldID field, + address location, Klass* field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. // determine which it really is, and convert fieldDescriptor fd; - bool found = JvmtiEnv::get_field_descriptor(field_klass(), field, &fd); + bool found = JvmtiEnv::get_field_descriptor(field_klass, field, &fd); // should be found (if not, leave as is) if (found) { jint ival = value->i; @@ -1917,7 +1912,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method } void JvmtiExport::post_field_modification(JavaThread *thread, Method* method, - address location, KlassHandle field_klass, Handle object, jfieldID field, + address location, Klass* field_klass, Handle object, jfieldID field, char sig_type, jvalue *value_ptr) { HandleMark hm(thread); @@ -1943,7 +1938,7 @@ void JvmtiExport::post_field_modification(JavaThread *thread, Method* method, JvmtiEnv *env = ets->get_env(); JvmtiLocationEventMark jem(thread, mh, location); - jclass field_jclass = jem.to_jclass(field_klass()); + jclass field_jclass = jem.to_jclass(field_klass); jobject field_jobject = jem.to_jobject(object()); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventFieldModification callback = env->callbacks()->FieldModification; diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 8599656ab7d..fe59759f728 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -150,7 +150,7 @@ class JvmtiExport : public AllStatic { }; static void post_field_modification(JavaThread *thread, Method* method, address location, - KlassHandle field_klass, Handle object, jfieldID field, + Klass* field_klass, Handle object, jfieldID field, char sig_type, jvalue *value); @@ -310,7 +310,7 @@ class JvmtiExport : public AllStatic { static void post_field_access_by_jni (JavaThread *thread, oop obj, Klass* klass, jfieldID fieldID, bool is_static) NOT_JVMTI_RETURN; static void post_field_access (JavaThread *thread, Method* method, - address location, KlassHandle field_klass, Handle object, jfieldID field) NOT_JVMTI_RETURN; + address location, Klass* field_klass, Handle object, jfieldID field) NOT_JVMTI_RETURN; static oop jni_SetField_probe (JavaThread *thread, jobject jobj, oop obj, Klass* klass, jfieldID fieldID, bool is_static, char sig_type, jvalue *value) NOT_JVMTI_RETURN_(NULL); @@ -321,7 +321,7 @@ class JvmtiExport : public AllStatic { Klass* klass, jfieldID fieldID, bool is_static, char sig_type, jvalue *value); static void post_raw_field_modification(JavaThread *thread, Method* method, - address location, KlassHandle field_klass, Handle object, jfieldID field, + address location, Klass* field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) NOT_JVMTI_RETURN; static void post_method_entry (JavaThread *thread, Method* method, frame current_frame) NOT_JVMTI_RETURN; diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index 072a0912d4b..1429f292841 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -287,12 +287,12 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { // add/remove breakpoint to/from versions of the method that are EMCP. Thread *thread = Thread::current(); - instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder()); + InstanceKlass* ik = _method->method_holder(); Symbol* m_name = _method->name(); Symbol* m_signature = _method->signature(); // search previous versions if they exist - for (InstanceKlass* pv_node = ikh->previous_versions(); + for (InstanceKlass* pv_node = ik->previous_versions(); pv_node != NULL; pv_node = pv_node->previous_versions()) { Array* methods = pv_node->methods(); @@ -696,10 +696,10 @@ bool VM_GetOrSetLocal::check_slot_type(javaVFrame* jvf) { Handle obj(cur_thread, JNIHandles::resolve_external_guard(jobj)); NULL_CHECK(obj, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); - KlassHandle ob_kh = KlassHandle(cur_thread, obj->klass()); - NULL_CHECK(ob_kh, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); + Klass* ob_k = obj->klass(); + NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); - if (!is_assignable(signature, ob_kh(), cur_thread)) { + if (!is_assignable(signature, ob_k, cur_thread)) { _result = JVMTI_ERROR_TYPE_MISMATCH; return false; } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index c1f8dd7306c..ab33f733647 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -58,7 +58,7 @@ Method** VM_RedefineClasses::_added_methods = NULL; int VM_RedefineClasses::_matching_methods_length = 0; int VM_RedefineClasses::_deleted_methods_length = 0; int VM_RedefineClasses::_added_methods_length = 0; -Klass* VM_RedefineClasses::_the_class_oop = NULL; +Klass* VM_RedefineClasses::_the_class = NULL; VM_RedefineClasses::VM_RedefineClasses(jint class_count, @@ -227,8 +227,8 @@ void VM_RedefineClasses::doit_epilogue() { // Free os::malloc allocated memory. os::free(_scratch_classes); - // Reset the_class_oop to null for error printing. - _the_class_oop = NULL; + // Reset the_class to null for error printing. + _the_class = NULL; if (log_is_enabled(Info, redefine, class, timer)) { // Used to have separate timers for "doit" and "all", but the timer @@ -657,8 +657,8 @@ void VM_RedefineClasses::finalize_operands_merge(const constantPoolHandle& merge jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( - instanceKlassHandle the_class, - instanceKlassHandle scratch_class) { + InstanceKlass* the_class, + InstanceKlass* scratch_class) { int i; // Check superclasses, or rather their names, since superclasses themselves can be @@ -993,8 +993,8 @@ bool VM_RedefineClasses::is_unresolved_class_mismatch(const constantPoolHandle& jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // For consistency allocate memory using os::malloc wrapper. - _scratch_classes = (Klass**) - os::malloc(sizeof(Klass*) * _class_count, mtClass); + _scratch_classes = (InstanceKlass**) + os::malloc(sizeof(InstanceKlass*) * _class_count, mtClass); if (_scratch_classes == NULL) { return JVMTI_ERROR_OUT_OF_MEMORY; } @@ -1014,7 +1014,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // versions are deleted. Constant pools are deallocated while merging // constant pools HandleMark hm(THREAD); - instanceKlassHandle the_class(THREAD, get_ik(_class_defs[i].klass)); + InstanceKlass* the_class = get_ik(_class_defs[i].klass); Symbol* the_class_sym = the_class->name(); log_debug(redefine, class, load) @@ -1032,24 +1032,23 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // Set redefined class handle in JvmtiThreadState class. // This redefined class is sent to agent event handler for class file // load hook event. - state->set_class_being_redefined(&the_class, _class_load_kind); + state->set_class_being_redefined(the_class, _class_load_kind); - Klass* k = SystemDictionary::parse_stream(the_class_sym, - the_class_loader, - protection_domain, - &st, - THREAD); + InstanceKlass* scratch_class = SystemDictionary::parse_stream( + the_class_sym, + the_class_loader, + protection_domain, + &st, + THREAD); // Clear class_being_redefined just to be sure. state->clear_class_being_redefined(); // TODO: if this is retransform, and nothing changed we can skip it - instanceKlassHandle scratch_class (THREAD, k); - // Need to clean up allocated InstanceKlass if there's an error so assign // the result here. Caller deallocates all the scratch classes in case of // an error. - _scratch_classes[i] = k; + _scratch_classes[i] = scratch_class; if (HAS_PENDING_EXCEPTION) { Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); @@ -1106,7 +1105,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // the_class to scratch_class in the JVM_* functions called by the // verifier. Please, refer to jvmtiThreadState.hpp for the detailed // description. - RedefineVerifyMark rvm(&the_class, &scratch_class, state); + RedefineVerifyMark rvm(the_class, scratch_class, state); Verifier::verify( scratch_class, Verifier::ThrowException, true, THREAD); } @@ -1138,7 +1137,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { if (VerifyMergedCPBytecodes) { // verify what we have done during constant pool merging { - RedefineVerifyMark rvm(&the_class, &scratch_class, state); + RedefineVerifyMark rvm(the_class, scratch_class, state); Verifier::verify(scratch_class, Verifier::ThrowException, true, THREAD); } @@ -1434,7 +1433,7 @@ class MergeCPCleaner { // potentially rewrite bytecodes in scratch_class to use the merged // constant pool. jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( - instanceKlassHandle the_class, instanceKlassHandle scratch_class, + InstanceKlass* the_class, InstanceKlass* scratch_class, TRAPS) { // worst case merged constant pool length is old and new combined int merge_cp_length = the_class->constants()->length() @@ -1483,7 +1482,7 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( _operands_index_map_p = new intArray(operands_index_map_len, operands_index_map_len, -1); // reference to the cp holder is needed for copy_operands() - merge_cp->set_pool_holder(scratch_class()); + merge_cp->set_pool_holder(scratch_class); bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, &merge_cp_length, THREAD); merge_cp->set_pool_holder(NULL); @@ -1568,7 +1567,7 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // Rewrite constant pool references in klass scratch_class. -bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class, +bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class, TRAPS) { // rewrite constant pool references in the methods: @@ -1655,7 +1654,7 @@ bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class, // Rewrite constant pool references in the methods. bool VM_RedefineClasses::rewrite_cp_refs_in_methods( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { Array* methods = scratch_class->methods(); @@ -1834,7 +1833,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, // Rewrite constant pool references in the class_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_class_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { AnnotationArray* class_annotations = scratch_class->class_annotations(); if (class_annotations == NULL || class_annotations->length() == 0) { @@ -2124,7 +2123,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value( // Rewrite constant pool references in a fields_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { Array* fields_annotations = scratch_class->fields_annotations(); @@ -2157,7 +2156,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations( // Rewrite constant pool references in a methods_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { for (int i = 0; i < scratch_class->methods()->length(); i++) { Method* m = scratch_class->methods()->at(i); @@ -2195,7 +2194,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations( // } // bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { for (int i = 0; i < scratch_class->methods()->length(); i++) { Method* m = scratch_class->methods()->at(i); @@ -2244,7 +2243,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations( // } // bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { for (int i = 0; i < scratch_class->methods()->length(); i++) { Method* m = scratch_class->methods()->at(i); @@ -2271,7 +2270,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations( // Rewrite constant pool references in a class_type_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { AnnotationArray* class_type_annotations = scratch_class->class_type_annotations(); if (class_type_annotations == NULL || class_type_annotations->length() == 0) { @@ -2289,7 +2288,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations( // Rewrite constant pool references in a fields_type_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { Array* fields_type_annotations = scratch_class->fields_type_annotations(); if (fields_type_annotations == NULL || fields_type_annotations->length() == 0) { @@ -2321,7 +2320,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations( // Rewrite constant pool references in a methods_type_annotations field. bool VM_RedefineClasses::rewrite_cp_refs_in_methods_type_annotations( - instanceKlassHandle scratch_class, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { for (int i = 0; i < scratch_class->methods()->length(); i++) { Method* m = scratch_class->methods()->at(i); @@ -3074,7 +3073,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_verification_type_info( // smaller constant pool is associated with scratch_class. void VM_RedefineClasses::set_new_constant_pool( ClassLoaderData* loader_data, - instanceKlassHandle scratch_class, constantPoolHandle scratch_cp, + InstanceKlass* scratch_class, constantPoolHandle scratch_cp, int scratch_cp_length, TRAPS) { assert(scratch_cp->length() >= scratch_cp_length, "sanity check"); @@ -3091,7 +3090,7 @@ void VM_RedefineClasses::set_new_constant_pool( // attach klass to new constant pool // reference to the cp holder is needed for copy_operands() - smaller_cp->set_pool_holder(scratch_class()); + smaller_cp->set_pool_holder(scratch_class); scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -3268,11 +3267,11 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // This is a very busy routine. We don't want too much tracing // printed out. bool trace_name_printed = false; - InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop); + InstanceKlass *the_class = InstanceKlass::cast(_the_class); // If the class being redefined is java.lang.Object, we need to fix all // array class vtables also - if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { + if (k->is_array_klass() && _the_class == SystemDictionary::Object_klass()) { k->vtable()->adjust_method_entries(the_class, &trace_name_printed); } else if (k->is_instance_klass()) { @@ -3291,8 +3290,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // If the current class being redefined has a user-defined class // loader as its defining class loader, then we can skip all // classes loaded by the bootstrap class loader. - bool is_user_defined = - InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; + bool is_user_defined = (_the_class->class_loader() != NULL); if (is_user_defined && ik->class_loader() == NULL) { return; } @@ -3311,9 +3309,9 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // This must be done after we adjust the default_methods and // default_vtable_indices for methods already in the vtable. // If redefining Unsafe, walk all the vtables looking for entries. - if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() - || _the_class_oop == SystemDictionary::internal_Unsafe_klass() - || ik->is_subtype_of(_the_class_oop))) { + if (ik->vtable_length() > 0 && (_the_class->is_interface() + || _the_class == SystemDictionary::internal_Unsafe_klass() + || ik->is_subtype_of(_the_class))) { // ik->vtable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); @@ -3328,9 +3326,9 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // every InstanceKlass that has an itable since there isn't a // subclass relationship between an interface and an InstanceKlass. // If redefining Unsafe, walk all the itables looking for entries. - if (ik->itable_length() > 0 && (_the_class_oop->is_interface() - || _the_class_oop == SystemDictionary::internal_Unsafe_klass() - || ik->is_subclass_of(_the_class_oop))) { + if (ik->itable_length() > 0 && (_the_class->is_interface() + || _the_class == SystemDictionary::internal_Unsafe_klass() + || ik->is_subclass_of(_the_class))) { // ik->itable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); @@ -3353,7 +3351,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { constantPoolHandle other_cp; ConstantPoolCache* cp_cache; - if (ik != _the_class_oop) { + if (ik != _the_class) { // this klass' constant pool cache may need adjustment other_cp = constantPoolHandle(ik->constants()); cp_cache = other_cp->cache(); @@ -3499,7 +3497,7 @@ int VM_RedefineClasses::check_methods_and_mark_as_obsolete() { // obsolete methods need a unique idnum so they become new entries in // the jmethodID cache in InstanceKlass assert(old_method->method_idnum() == new_method->method_idnum(), "must match"); - u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum(); + u2 num = InstanceKlass::cast(_the_class)->next_method_idnum(); if (num != ConstMethod::UNSET_IDNUM) { old_method->set_method_idnum(num); } @@ -3563,7 +3561,7 @@ int VM_RedefineClasses::check_methods_and_mark_as_obsolete() { // class TransferNativeFunctionRegistration { private: - instanceKlassHandle the_class; + InstanceKlass* the_class; int prefix_count; char** prefixes; @@ -3578,7 +3576,7 @@ class TransferNativeFunctionRegistration { Symbol* signature) { TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len); if (name_symbol != NULL) { - Method* method = the_class()->lookup_method(name_symbol, signature); + Method* method = the_class->lookup_method(name_symbol, signature); if (method != NULL) { // Even if prefixed, intermediate methods must exist. if (method->is_native()) { @@ -3641,7 +3639,7 @@ class TransferNativeFunctionRegistration { public: // Construct a native method transfer processor for this class. - TransferNativeFunctionRegistration(instanceKlassHandle _the_class) { + TransferNativeFunctionRegistration(InstanceKlass* _the_class) { assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); the_class = _the_class; @@ -3668,7 +3666,7 @@ class TransferNativeFunctionRegistration { }; // Don't lose the association between a native method and its JNI function. -void VM_RedefineClasses::transfer_old_native_function_registrations(instanceKlassHandle the_class) { +void VM_RedefineClasses::transfer_old_native_function_registrations(InstanceKlass* the_class) { TransferNativeFunctionRegistration transfer(the_class); transfer.transfer_registrations(_deleted_methods, _deleted_methods_length); transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); @@ -3689,13 +3687,13 @@ void VM_RedefineClasses::transfer_old_native_function_registrations(instanceKlas // subsequent calls to RedefineClasses need only throw away code // that depends on the class. // -void VM_RedefineClasses::flush_dependent_code(instanceKlassHandle k_h, TRAPS) { +void VM_RedefineClasses::flush_dependent_code(InstanceKlass* ik, TRAPS) { assert_locked_or_safepoint(Compile_lock); // All dependencies have been recorded from startup or this is a second or // subsequent use of RedefineClasses if (JvmtiExport::all_dependencies_are_recorded()) { - CodeCache::flush_evol_dependents_on(k_h); + CodeCache::flush_evol_dependents_on(ik); } else { CodeCache::mark_all_nmethods_for_deoptimization(); @@ -3775,8 +3773,8 @@ void VM_RedefineClasses::compute_added_deleted_matching_methods() { } -void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class, - instanceKlassHandle scratch_class) { +void VM_RedefineClasses::swap_annotations(InstanceKlass* the_class, + InstanceKlass* scratch_class) { // Swap annotation fields values Annotations* old_annotations = the_class->annotations(); the_class->set_annotations(scratch_class->annotations()); @@ -3797,7 +3795,7 @@ void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class, // that we would like to pass to the helper method are saved in // static global fields in the VM operation. void VM_RedefineClasses::redefine_single_class(jclass the_jclass, - Klass* scratch_class_oop, TRAPS) { + InstanceKlass* scratch_class, TRAPS) { HandleMark hm(THREAD); // make sure handles from this call are freed @@ -3805,25 +3803,24 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, _timer_rsc_phase1.start(); } - instanceKlassHandle scratch_class(THREAD, scratch_class_oop); - instanceKlassHandle the_class(THREAD, get_ik(the_jclass)); + InstanceKlass* the_class = get_ik(the_jclass); // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); - jvmti_breakpoints.clearall_in_class_at_safepoint(the_class()); + jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); // Deoptimize all compiled code that depends on this class flush_dependent_code(the_class, THREAD); _old_methods = the_class->methods(); _new_methods = scratch_class->methods(); - _the_class_oop = the_class(); + _the_class = the_class; compute_added_deleted_matching_methods(); update_jmethod_ids(); // Attach new constant pool to the original klass. The original // klass still refers to the old constant pool (for now). - scratch_class->constants()->set_pool_holder(the_class()); + scratch_class->constants()->set_pool_holder(the_class); #if 0 // In theory, with constant pool merging in place we should be able @@ -3853,13 +3850,11 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, { // walk all previous versions of the klass - InstanceKlass *ik = (InstanceKlass *)the_class(); + InstanceKlass *ik = the_class; PreviousVersionWalker pvw(ik); - instanceKlassHandle ikh; do { - ikh = pvw.next_previous_version(); - if (!ikh.is_null()) { - ik = ikh(); + ik = pvw.next_previous_version(); + if (ik != NULL) { // attach previous version of klass to the new constant pool ik->set_constants(scratch_class->constants()); @@ -3872,7 +3867,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, method->set_constants(scratch_class->constants()); } } - } while (!ikh.is_null()); + } while (ik != NULL); } #endif @@ -4041,7 +4036,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, MemberNameTable* mnt = the_class->member_names(); if (mnt != NULL) { bool trace_name_printed = false; - mnt->adjust_method_entries(the_class(), &trace_name_printed); + mnt->adjust_method_entries(the_class, &trace_name_printed); } if (the_class->oop_map_cache() != NULL) { @@ -4050,11 +4045,11 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, the_class->oop_map_cache()->flush_obsolete_entries(); } + increment_class_counter((InstanceKlass *)the_class, THREAD); { ResourceMark rm(THREAD); // increment the classRedefinedCount field in the_class and in any // direct and indirect subclasses of the_class - increment_class_counter((InstanceKlass *)the_class(), THREAD); log_info(redefine, class, load) ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10); @@ -4075,8 +4070,8 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; java_lang_Class::set_classRedefinedCount(class_mirror, new_count); - if (class_oop != _the_class_oop) { - // _the_class_oop count is printed at end of redefine_single_class() + if (class_oop != _the_class) { + // _the_class count is printed at end of redefine_single_class() log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count); } @@ -4212,8 +4207,8 @@ void VM_RedefineClasses::dump_methods() { void VM_RedefineClasses::print_on_error(outputStream* st) const { VM_Operation::print_on_error(st); - if (_the_class_oop != NULL) { + if (_the_class != NULL) { ResourceMark rm; - st->print_cr(", redefining class %s", _the_class_oop->external_name()); + st->print_cr(", redefining class %s", _the_class->external_name()); } } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index edba3dd51a0..c24a9d23419 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -348,7 +348,7 @@ class VM_RedefineClasses: public VM_Operation { static int _matching_methods_length; static int _deleted_methods_length; static int _added_methods_length; - static Klass* _the_class_oop; + static Klass* _the_class; // The instance fields are used to pass information from // doit_prologue() to doit() and doit_epilogue(). @@ -371,7 +371,7 @@ class VM_RedefineClasses: public VM_Operation { intArray * _operands_index_map_p; // ptr to _class_count scratch_classes - Klass** _scratch_classes; + InstanceKlass** _scratch_classes; jvmtiError _res; // Performance measurement support. These timers do not cover all @@ -393,7 +393,7 @@ class VM_RedefineClasses: public VM_Operation { // the restrictions of RedefineClasses. Normalize the order of // overloaded methods as needed. jvmtiError compare_and_normalize_class_versions( - instanceKlassHandle the_class, instanceKlassHandle scratch_class); + InstanceKlass* the_class, InstanceKlass* scratch_class); // Figure out which new methods match old methods in name and signature, // which methods have been added, and which are no longer present @@ -405,14 +405,14 @@ class VM_RedefineClasses: public VM_Operation { // In addition to marking methods as old and/or obsolete, this routine // counts the number of methods that are EMCP (Equivalent Module Constant Pool). int check_methods_and_mark_as_obsolete(); - void transfer_old_native_function_registrations(instanceKlassHandle the_class); + void transfer_old_native_function_registrations(InstanceKlass* the_class); // Install the redefinition of a class void redefine_single_class(jclass the_jclass, - Klass* scratch_class_oop, TRAPS); + InstanceKlass* scratch_class_oop, TRAPS); - void swap_annotations(instanceKlassHandle new_class, - instanceKlassHandle scratch_class); + void swap_annotations(InstanceKlass* new_class, + InstanceKlass* scratch_class); // Increment the classRedefinedCount field in the specific InstanceKlass // and in all direct and indirect subclasses. @@ -437,18 +437,18 @@ class VM_RedefineClasses: public VM_Operation { bool merge_constant_pools(const constantPoolHandle& old_cp, const constantPoolHandle& scratch_cp, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); - jvmtiError merge_cp_and_rewrite(instanceKlassHandle the_class, - instanceKlassHandle scratch_class, TRAPS); + jvmtiError merge_cp_and_rewrite(InstanceKlass* the_class, + InstanceKlass* scratch_class, TRAPS); u2 rewrite_cp_ref_in_annotation_data( AnnotationArray* annotations_typeArray, int &byte_i_ref, const char * trace_mesg, TRAPS); - bool rewrite_cp_refs(instanceKlassHandle scratch_class, TRAPS); + bool rewrite_cp_refs(InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_annotation_struct( AnnotationArray* class_annotations, int &byte_i_ref, TRAPS); bool rewrite_cp_refs_in_annotations_typeArray( AnnotationArray* annotations_typeArray, int &byte_i_ref, TRAPS); bool rewrite_cp_refs_in_class_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_element_value( AnnotationArray* class_annotations, int &byte_i_ref, TRAPS); bool rewrite_cp_refs_in_type_annotations_typeArray( @@ -463,31 +463,31 @@ class VM_RedefineClasses: public VM_Operation { bool skip_type_annotation_type_path( AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS); bool rewrite_cp_refs_in_fields_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); void rewrite_cp_refs_in_method(methodHandle method, methodHandle * new_method_p, TRAPS); - bool rewrite_cp_refs_in_methods(instanceKlassHandle scratch_class, TRAPS); + bool rewrite_cp_refs_in_methods(InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_methods_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_methods_default_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_methods_parameter_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_class_type_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_fields_type_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); bool rewrite_cp_refs_in_methods_type_annotations( - instanceKlassHandle scratch_class, TRAPS); + InstanceKlass* scratch_class, TRAPS); void rewrite_cp_refs_in_stack_map_table(const methodHandle& method, TRAPS); void rewrite_cp_refs_in_verification_type_info( address& stackmap_addr_ref, address stackmap_end, u2 frame_i, u1 frame_size, TRAPS); void set_new_constant_pool(ClassLoaderData* loader_data, - instanceKlassHandle scratch_class, + InstanceKlass* scratch_class, constantPoolHandle scratch_cp, int scratch_cp_length, TRAPS); - void flush_dependent_code(instanceKlassHandle k_h, TRAPS); + void flush_dependent_code(InstanceKlass* ik, TRAPS); // lock classes to redefine since constant pool merging isn't thread safe. void lock_classes(); diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index e90420d03b8..7aaa1341dd6 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -783,7 +783,7 @@ class ClassFieldMap: public CHeapObj { void add(int index, char type, int offset); // returns the field count for the given class - static int compute_field_count(instanceKlassHandle ikh); + static int compute_field_count(InstanceKlass* ik); public: ~ClassFieldMap(); @@ -819,16 +819,16 @@ void ClassFieldMap::add(int index, char type, int offset) { // ClassFieldMap* ClassFieldMap::create_map_of_static_fields(Klass* k) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); + InstanceKlass* ik = InstanceKlass::cast(k); // create the field map ClassFieldMap* field_map = new ClassFieldMap(); - FilteredFieldStream f(ikh, false, false); + FilteredFieldStream f(ik, false, false); int max_field_index = f.field_count()-1; int index = 0; - for (FilteredFieldStream fld(ikh, true, true); !fld.eos(); fld.next(), index++) { + for (FilteredFieldStream fld(ik, true, true); !fld.eos(); fld.next(), index++) { // ignore instance fields if (!fld.access_flags().is_static()) { continue; @@ -844,17 +844,17 @@ ClassFieldMap* ClassFieldMap::create_map_of_static_fields(Klass* k) { // ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), obj->klass()); + InstanceKlass* ik = InstanceKlass::cast(obj->klass()); // create the field map ClassFieldMap* field_map = new ClassFieldMap(); - FilteredFieldStream f(ikh, false, false); + FilteredFieldStream f(ik, false, false); int max_field_index = f.field_count()-1; int index = 0; - for (FilteredFieldStream fld(ikh, false, false); !fld.eos(); fld.next(), index++) { + for (FilteredFieldStream fld(ik, false, false); !fld.eos(); fld.next(), index++) { // ignore static fields if (fld.access_flags().is_static()) { continue; @@ -1008,9 +1008,9 @@ static inline bool is_filtered_by_heap_filter(jlong obj_tag, } // helper function to indicate if an object is filtered by a klass filter -static inline bool is_filtered_by_klass_filter(oop obj, KlassHandle klass_filter) { - if (!klass_filter.is_null()) { - if (obj->klass() != klass_filter()) { +static inline bool is_filtered_by_klass_filter(oop obj, Klass* klass_filter) { + if (klass_filter != NULL) { + if (obj->klass() != klass_filter) { return true; } } @@ -1272,7 +1272,7 @@ class VM_HeapIterateOperation: public VM_Operation { class IterateOverHeapObjectClosure: public ObjectClosure { private: JvmtiTagMap* _tag_map; - KlassHandle _klass; + Klass* _klass; jvmtiHeapObjectFilter _object_filter; jvmtiHeapObjectCallback _heap_object_callback; const void* _user_data; @@ -1281,7 +1281,7 @@ class IterateOverHeapObjectClosure: public ObjectClosure { JvmtiTagMap* tag_map() const { return _tag_map; } jvmtiHeapObjectFilter object_filter() const { return _object_filter; } jvmtiHeapObjectCallback object_callback() const { return _heap_object_callback; } - KlassHandle klass() const { return _klass; } + Klass* klass() const { return _klass; } const void* user_data() const { return _user_data; } // indicates if iteration has been aborted @@ -1291,7 +1291,7 @@ class IterateOverHeapObjectClosure: public ObjectClosure { public: IterateOverHeapObjectClosure(JvmtiTagMap* tag_map, - KlassHandle klass, + Klass* klass, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) : @@ -1316,7 +1316,7 @@ void IterateOverHeapObjectClosure::do_object(oop o) { if (!ServiceUtil::visible_oop(o)) return; // instanceof check when filtering by klass - if (!klass().is_null() && !o->is_a(klass()())) { + if (klass() != NULL && !o->is_a(klass())) { return; } // prepare for the calllback @@ -1345,7 +1345,7 @@ void IterateOverHeapObjectClosure::do_object(oop o) { class IterateThroughHeapObjectClosure: public ObjectClosure { private: JvmtiTagMap* _tag_map; - KlassHandle _klass; + Klass* _klass; int _heap_filter; const jvmtiHeapCallbacks* _callbacks; const void* _user_data; @@ -1354,7 +1354,7 @@ class IterateThroughHeapObjectClosure: public ObjectClosure { JvmtiTagMap* tag_map() const { return _tag_map; } int heap_filter() const { return _heap_filter; } const jvmtiHeapCallbacks* callbacks() const { return _callbacks; } - KlassHandle klass() const { return _klass; } + Klass* klass() const { return _klass; } const void* user_data() const { return _user_data; } // indicates if the iteration has been aborted @@ -1374,7 +1374,7 @@ class IterateThroughHeapObjectClosure: public ObjectClosure { public: IterateThroughHeapObjectClosure(JvmtiTagMap* tag_map, - KlassHandle klass, + Klass* klass, int heap_filter, const jvmtiHeapCallbacks* heap_callbacks, const void* user_data) : @@ -1470,7 +1470,7 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { // Deprecated function to iterate over all objects in the heap void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter, - KlassHandle klass, + Klass* klass, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { @@ -1487,7 +1487,7 @@ void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter, // Iterates over all objects in the heap void JvmtiTagMap::iterate_through_heap(jint heap_filter, - KlassHandle klass, + Klass* klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { @@ -1806,14 +1806,14 @@ class BasicHeapWalkContext: public HeapWalkContext { class AdvancedHeapWalkContext: public HeapWalkContext { private: jint _heap_filter; - KlassHandle _klass_filter; + Klass* _klass_filter; const jvmtiHeapCallbacks* _heap_callbacks; public: AdvancedHeapWalkContext() : HeapWalkContext(false) { } AdvancedHeapWalkContext(jint heap_filter, - KlassHandle klass_filter, + Klass* klass_filter, const jvmtiHeapCallbacks* heap_callbacks) : HeapWalkContext(true), _heap_filter(heap_filter), @@ -1823,7 +1823,7 @@ class AdvancedHeapWalkContext: public HeapWalkContext { // accessors jint heap_filter() const { return _heap_filter; } - KlassHandle klass_filter() const { return _klass_filter; } + Klass* klass_filter() const { return _klass_filter; } const jvmtiHeapReferenceCallback heap_reference_callback() const { return _heap_callbacks->heap_reference_callback; @@ -3296,7 +3296,7 @@ void JvmtiTagMap::iterate_over_objects_reachable_from_object(jobject object, // follow references from an initial object or the GC roots void JvmtiTagMap::follow_references(jint heap_filter, - KlassHandle klass, + Klass* klass, jobject object, const jvmtiHeapCallbacks* callbacks, const void* user_data) diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp index 196abda21b8..73d5577ac5a 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -91,7 +91,7 @@ class JvmtiTagMap : public CHeapObj { // deprecated heap iteration functions void iterate_over_heap(jvmtiHeapObjectFilter object_filter, - KlassHandle klass, + Klass* klass, jvmtiHeapObjectCallback heap_object_callback, const void* user_data); @@ -107,12 +107,12 @@ class JvmtiTagMap : public CHeapObj { // advanced (JVMTI 1.1) heap iteration functions void iterate_through_heap(jint heap_filter, - KlassHandle klass, + Klass* klass, const jvmtiHeapCallbacks* callbacks, const void* user_data); void follow_references(jint heap_filter, - KlassHandle klass, + Klass* klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data); diff --git a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp index b025161a413..3a7ddb66fc3 100644 --- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp +++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp @@ -93,7 +93,7 @@ class JvmtiThreadState : public CHeapObj { // Used to send class being redefined/retransformed and kind of transform // info to the class file load hook event handler. - KlassHandle *_class_being_redefined; + Klass* _class_being_redefined; JvmtiClassLoadKind _class_load_kind; // This is only valid when is_interp_only_mode() returns true @@ -220,8 +220,8 @@ class JvmtiThreadState : public CHeapObj { // when class file load hook event is posted. // It is set while loading redefined class and cleared before the // class file load hook event is posted. - inline void set_class_being_redefined(KlassHandle *h_class, JvmtiClassLoadKind kind) { - _class_being_redefined = h_class; + inline void set_class_being_redefined(Klass* k, JvmtiClassLoadKind kind) { + _class_being_redefined = k; _class_load_kind = kind; } @@ -230,7 +230,7 @@ class JvmtiThreadState : public CHeapObj { _class_load_kind = jvmti_class_load_kind_load; } - inline KlassHandle *get_class_being_redefined() { + inline Klass* get_class_being_redefined() { return _class_being_redefined; } @@ -271,12 +271,12 @@ class JvmtiThreadState : public CHeapObj { // used by the verifier, so there is no extra performance issue with it. private: - KlassHandle *_the_class_for_redefinition_verification; - KlassHandle *_scratch_class_for_redefinition_verification; + Klass* _the_class_for_redefinition_verification; + Klass* _scratch_class_for_redefinition_verification; public: - inline void set_class_versions_map(KlassHandle *the_class, - KlassHandle *scratch_class) { + inline void set_class_versions_map(Klass* the_class, + Klass* scratch_class) { _the_class_for_redefinition_verification = the_class; _scratch_class_for_redefinition_verification = scratch_class; } @@ -288,8 +288,8 @@ class JvmtiThreadState : public CHeapObj { JavaThread *thread) { JvmtiThreadState *state = thread->jvmti_thread_state(); if (state != NULL && state->_the_class_for_redefinition_verification != NULL) { - if ((*(state->_the_class_for_redefinition_verification))() == klass) { - klass = (*(state->_scratch_class_for_redefinition_verification))(); + if (state->_the_class_for_redefinition_verification == klass) { + klass = state->_scratch_class_for_redefinition_verification; } } return klass; @@ -409,17 +409,17 @@ public: class RedefineVerifyMark : public StackObj { private: - JvmtiThreadState *_state; - KlassHandle _scratch_class; + JvmtiThreadState* _state; + Klass* _scratch_class; Handle _scratch_mirror; public: - RedefineVerifyMark(KlassHandle *the_class, KlassHandle *scratch_class, - JvmtiThreadState *state) : _state(state), _scratch_class(*scratch_class) + RedefineVerifyMark(Klass* the_class, Klass* scratch_class, + JvmtiThreadState *state) : _state(state), _scratch_class(scratch_class) { _state->set_class_versions_map(the_class, scratch_class); _scratch_mirror = Handle(Thread::current(), _scratch_class->java_mirror()); - (*scratch_class)->set_java_mirror((*the_class)->java_mirror()); + _scratch_class->set_java_mirror(the_class->java_mirror()); } ~RedefineVerifyMark() { diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index caf009466ff..260710aa5fd 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -124,7 +124,7 @@ enum { Handle MethodHandles::new_MemberName(TRAPS) { Handle empty; - instanceKlassHandle k(THREAD, SystemDictionary::MemberName_klass()); + InstanceKlass* k = SystemDictionary::MemberName_klass(); if (!k->is_initialized()) k->initialize(CHECK_(empty)); return Handle(THREAD, k->allocate_instance(THREAD)); } @@ -138,9 +138,9 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { if (target_klass == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() - KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->is_instance_klass()) { - fieldDescriptor fd(InstanceKlass::cast(k()), slot); + Klass* k = java_lang_Class::as_Klass(clazz); + if (k != NULL && k->is_instance_klass()) { + fieldDescriptor fd(InstanceKlass::cast(k), slot); oop mname2 = init_field_MemberName(mname, fd); if (mname2 != NULL) { // Since we have the reified name and type handy, add them to the result. @@ -154,22 +154,22 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { } else if (target_klass == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(target_oop); int slot = java_lang_reflect_Method::slot(target_oop); - KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->is_instance_klass()) { - Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); + Klass* k = java_lang_Class::as_Klass(clazz); + if (k != NULL && k->is_instance_klass()) { + Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); if (m == NULL || is_signature_polymorphic(m->intrinsic_id())) return NULL; // do not resolve unless there is a concrete signature - CallInfo info(m, k()); + CallInfo info(m, k); return init_method_MemberName(mname, info); } } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { oop clazz = java_lang_reflect_Constructor::clazz(target_oop); int slot = java_lang_reflect_Constructor::slot(target_oop); - KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->is_instance_klass()) { - Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); + Klass* k = java_lang_Class::as_Klass(clazz); + if (k != NULL && k->is_instance_klass()) { + Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); if (m == NULL) return NULL; - CallInfo info(m, k()); + CallInfo info(m, k); return init_method_MemberName(mname, info); } } @@ -180,8 +180,8 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, bool int assert(info.resolved_appendix().is_null(), "only normal methods here"); methodHandle m = info.resolved_method(); assert(m.not_null(), "null method handle"); - KlassHandle m_klass = m->method_holder(); - assert(m.not_null(), "null holder for method handle"); + Klass* m_klass = m->method_holder(); + assert(m_klass != NULL, "null holder for method handle"); int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); int vmindex = Method::invalid_vtable_index; @@ -208,12 +208,12 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, bool int case CallInfo::vtable_call: vmindex = info.vtable_index(); flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); - assert(info.resolved_klass()->is_subtype_of(m_klass()), "virtual call must be type-safe"); + assert(info.resolved_klass()->is_subtype_of(m_klass), "virtual call must be type-safe"); if (m_klass->is_interface()) { // This is a vtable call to an interface method (abstract "miranda method" or default method). // The vtable index is meaningless without a class (not interface) receiver type, so get one. // (LinkResolver should help us figure this out.) - KlassHandle m_klass_non_interface = info.resolved_klass(); + Klass* m_klass_non_interface = info.resolved_klass(); if (m_klass_non_interface->is_interface()) { m_klass_non_interface = SystemDictionary::Object_klass(); #ifdef ASSERT @@ -229,7 +229,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, bool int assert(m->is_public(), "virtual call must be to public interface method"); return NULL; // elicit an error later in product build } - assert(info.resolved_klass()->is_subtype_of(m_klass_non_interface()), "virtual call must be type-safe"); + assert(info.resolved_klass()->is_subtype_of(m_klass_non_interface), "virtual call must be type-safe"); m_klass = m_klass_non_interface; } if (TraceInvokeDynamic) { @@ -637,7 +637,7 @@ oop MethodHandles::field_signature_type_or_null(Symbol* s) { // An unresolved member name is a mere symbolic reference. // Resolving it plants a vmtarget/vmindex in it, // which refers directly to JVM internals. -Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS) { +Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller, TRAPS) { Handle empty; assert(java_lang_invoke_MemberName::is_instance(mname()), ""); @@ -664,7 +664,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve", empty); } - instanceKlassHandle defc; + InstanceKlass* defc = NULL; { Klass* defc_klass = java_lang_Class::as_Klass(defc_oop()); if (defc_klass == NULL) return empty; // a primitive; no resolution possible @@ -672,9 +672,9 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS if (!defc_klass->is_array_klass()) return empty; defc_klass = SystemDictionary::Object_klass(); } - defc = instanceKlassHandle(THREAD, defc_klass); + defc = InstanceKlass::cast(defc_klass); } - if (defc.is_null()) { + if (defc == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "primitive class", empty); } defc->link_class(CHECK_(empty)); // possible safepoint @@ -687,7 +687,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS vmIntrinsics::ID mh_invoke_id = vmIntrinsics::_none; if ((flags & ALL_KINDS) == IS_METHOD && - (defc() == SystemDictionary::MethodHandle_klass()) && + (defc == SystemDictionary::MethodHandle_klass()) && (ref_kind == JVM_REF_invokeVirtual || ref_kind == JVM_REF_invokeSpecial || // static invocation mode is required for _linkToVirtual, etc.: @@ -705,7 +705,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS TempNewSymbol type = lookup_signature(type_str(), (mh_invoke_id != vmIntrinsics::_none), CHECK_(empty)); if (type == NULL) return empty; // no such signature exists in the VM - LinkInfo::AccessCheck access_check = caller.not_null() ? + LinkInfo::AccessCheck access_check = caller != NULL ? LinkInfo::needs_access_check : LinkInfo::skip_access_check; @@ -840,7 +840,7 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { { assert(vmtarget->is_klass(), "field vmtarget is Klass*"); if (!((Klass*) vmtarget)->is_instance_klass()) break; - instanceKlassHandle defc(THREAD, (Klass*) vmtarget); + InstanceKlass* defc = InstanceKlass::cast((Klass*) vmtarget); DEBUG_ONLY(vmtarget = NULL); // safety bool is_static = ((flags & JVM_ACC_STATIC) != 0); fieldDescriptor fd; // find_field initializes fd if found @@ -868,15 +868,15 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); } -int MethodHandles::find_MemberNames(KlassHandle k, +int MethodHandles::find_MemberNames(Klass* k, Symbol* name, Symbol* sig, - int mflags, KlassHandle caller, + int mflags, Klass* caller, int skip, objArrayHandle results) { // %%% take caller into account! Thread* thread = Thread::current(); - if (k.is_null() || !k->is_instance_klass()) return -1; + if (k == NULL || !k->is_instance_klass()) return -1; int rfill = 0, rlimit = results->length(), rskip = skip; // overflow measurement: @@ -904,7 +904,8 @@ int MethodHandles::find_MemberNames(KlassHandle k, } if ((match_flags & IS_FIELD) != 0) { - for (FieldStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { + InstanceKlass* ik = InstanceKlass::cast(k); + for (FieldStream st(ik, local_only, !search_intfc); !st.eos(); st.next()) { if (name != NULL && st.name() != name) continue; if (sig != NULL && st.signature() != sig) @@ -950,7 +951,8 @@ int MethodHandles::find_MemberNames(KlassHandle k, } else { // caller will accept either sort; no need to adjust name } - for (MethodStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { + InstanceKlass* ik = InstanceKlass::cast(k); + for (MethodStream st(ik, local_only, !search_intfc); !st.eos(); st.next()) { Method* m = st.method(); Symbol* m_name = m->name(); if (m_name == clinit_name) @@ -1238,9 +1240,8 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, } } - KlassHandle caller(THREAD, - caller_jh == NULL ? (Klass*) NULL : - java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh))); + Klass* caller = caller_jh == NULL ? NULL : + java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)); Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL); if (resolved.is_null()) { @@ -1330,7 +1331,7 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls, jclass clazz_jh, jstring name_jh, jstring sig_jh, int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) { if (clazz_jh == NULL || results_jh == NULL) return -1; - KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz_jh))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz_jh)); objArrayHandle results(THREAD, (objArrayOop) JNIHandles::resolve(results_jh)); if (results.is_null() || !results->is_objArray()) return -1; @@ -1346,11 +1347,11 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls, if (sig == NULL) return 0; // a match is not possible } - KlassHandle caller; + Klass* caller = NULL; if (caller_jh != NULL) { oop caller_oop = JNIHandles::resolve_non_null(caller_jh); if (!java_lang_Class::is_instance(caller_oop)) return -1; - caller = KlassHandle(THREAD, java_lang_Class::as_Klass(caller_oop)); + caller = java_lang_Class::as_Klass(caller_oop); } if (name != NULL && sig != NULL && results.not_null()) { diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 3a5e90305fe..669aecdaff9 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -61,15 +61,15 @@ class MethodHandles: AllStatic { public: // working with member names - static Handle resolve_MemberName(Handle mname, KlassHandle caller, TRAPS); // compute vmtarget/vmindex from name/type + static Handle resolve_MemberName(Handle mname, Klass* caller, TRAPS); // compute vmtarget/vmindex from name/type static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static Handle new_MemberName(TRAPS); // must be followed by init_MemberName static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false); static oop init_method_MemberName(Handle mname_h, CallInfo& info, bool intern = true); static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true); - static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig, - int mflags, KlassHandle caller, + static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig, + int mflags, Klass* caller, int skip, objArrayHandle results); // bit values for suppress argument to expand_MemberName: enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 0861c5120aa..dfe88062887 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -175,7 +175,7 @@ address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, } // Otherwise call static method findNative in ClassLoader - KlassHandle klass (THREAD, SystemDictionary::ClassLoader_klass()); + Klass* klass = SystemDictionary::ClassLoader_klass(); Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL); JavaValue result(T_LONG); @@ -345,9 +345,8 @@ address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in int wrapper_name_len = (int)strlen(wrapper_name); TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len); if (wrapper_symbol != NULL) { - KlassHandle kh(method->method_holder()); - Method* wrapper_method = kh()->lookup_method(wrapper_symbol, - method->signature()); + Klass* k = method->method_holder(); + Method* wrapper_method = k->lookup_method(wrapper_symbol, method->signature()); if (wrapper_method != NULL && !wrapper_method->is_native()) { // we found a wrapper method, use its native entry method->set_is_prefixed_native(); @@ -402,7 +401,7 @@ address NativeLookup::base_library_lookup(const char* class_name, const char* me // Find the class Klass* k = SystemDictionary::resolve_or_fail(c_name, true, CATCH); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* klass = InstanceKlass::cast(k); // Find method and invoke standard lookup methodHandle method (THREAD, diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index 7e307eb811f..a84922479c6 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -179,7 +179,7 @@ void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array, oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values, int i, BasicType type, TRAPS) { Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL); - instanceKlassHandle ik (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); JavaValue result(T_OBJECT); JavaCallArguments args; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 1c98add775b..f1479958d69 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -845,7 +845,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na // not just a literal string. For such ldc instructions, the verifier uses the // type Object instead of String, if the loaded constant is not in fact a String. -static instanceKlassHandle +static InstanceKlass* Unsafe_DefineAnonymousClass_impl(JNIEnv *env, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh, u1** temp_alloc, @@ -932,18 +932,17 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, return NULL; } - return instanceKlassHandle(THREAD, anonk); + return InstanceKlass::cast(anonk); } UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) { ResourceMark rm(THREAD); - instanceKlassHandle anon_klass; jobject res_jh = NULL; u1* temp_alloc = NULL; - anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD); - if (anon_klass() != NULL) { + InstanceKlass* anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD); + if (anon_klass != NULL) { res_jh = JNIHandles::make_local(env, anon_klass->java_mirror()); } @@ -955,7 +954,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, j // The anonymous class loader data has been artificially been kept alive to // this point. The mirror and any instances of this class have to keep // it alive afterwards. - if (anon_klass() != NULL) { + if (anon_klass != NULL) { anon_klass->class_loader_data()->dec_keep_alive(); } diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 35f0f607f2d..0f7bc97a186 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -782,8 +782,8 @@ WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobjec WB_END WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level)) - instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); - return WhiteBox::compile_method(ikh->class_initializer(), comp_level, InvocationEntryBci, THREAD); + InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + return WhiteBox::compile_method(ik->class_initializer(), comp_level, InvocationEntryBci, THREAD); WB_END WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level)) @@ -1517,8 +1517,8 @@ WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb)) WB_END WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass)) - instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); - return (jlong) ikh->constants(); + InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + return (jlong) ik->constants(); WB_END WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb)) @@ -1526,8 +1526,8 @@ WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb)) WB_END WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass)) - instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); - ConstantPool* cp = ikh->constants(); + InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + ConstantPool* cp = ik->constants(); if (cp->cache() == NULL) { return -1; } @@ -1535,8 +1535,8 @@ WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass kla WB_END WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index)) - instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); - ConstantPool* cp = ikh->constants(); + InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + ConstantPool* cp = ik->constants(); if (cp->cache() == NULL) { THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache"); } @@ -1950,8 +1950,8 @@ JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass)) { if (WhiteBoxAPI) { // Make sure that wbclass is loaded by the null classloader - instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass()); - Handle loader(THREAD, ikh->class_loader()); + InstanceKlass* ik = InstanceKlass::cast(JNIHandles::resolve(wbclass)->klass()); + Handle loader(THREAD, ik->class_loader()); if (loader.is_null()) { WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0])); WhiteBox::register_extended(env, wbclass, thread); diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index b6843ac3ea8..ff5468322e0 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -810,19 +810,19 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra assert(objects->at(i)->is_object(), "invalid debug information"); ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); + Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()); oop obj = NULL; if (k->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(k()); + InstanceKlass* ik = InstanceKlass::cast(k); obj = ik->allocate_instance(THREAD); } else if (k->is_typeArray_klass()) { - TypeArrayKlass* ak = TypeArrayKlass::cast(k()); + TypeArrayKlass* ak = TypeArrayKlass::cast(k); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; obj = ak->allocate(len, THREAD); } else if (k->is_objArray_klass()) { - ObjArrayKlass* ak = ObjArrayKlass::cast(k()); + ObjArrayKlass* ak = ObjArrayKlass::cast(k); obj = ak->allocate(sv->field_size(), THREAD); } @@ -1079,7 +1079,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures, bool skip_internal) { for (int i = 0; i < objects->length(); i++) { ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); + Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()); Handle obj = sv->value(); assert(obj.not_null() || realloc_failures, "reallocation was missed"); if (PrintDeoptimizationDetails) { @@ -1090,10 +1090,10 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr } if (k->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(k()); + InstanceKlass* ik = InstanceKlass::cast(k); reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal); } else if (k->is_typeArray_klass()) { - TypeArrayKlass* ak = TypeArrayKlass::cast(k()); + TypeArrayKlass* ak = TypeArrayKlass::cast(k); reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type()); } else if (k->is_objArray_klass()) { reassign_object_array_elements(fr, reg_map, sv, (objArrayOop) obj()); @@ -1137,7 +1137,7 @@ void Deoptimization::print_objects(GrowableArray* objects, bool rea for (int i = 0; i < objects->length(); i++) { ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); + Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()); Handle obj = sv->value(); tty->print(" object <" INTPTR_FORMAT "> of type ", p2i(sv->value()())); diff --git a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp index 1810a16cd3d..b1a0701df95 100644 --- a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,10 +61,10 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { reinitialize(ik, index); } Symbol* name() const { - return field()->name(_cp); + return field()->name(_cp()); } Symbol* signature() const { - return field()->signature(_cp); + return field()->signature(_cp()); } InstanceKlass* field_holder() const { return _cp->pool_holder(); } ConstantPool* constants() const { return _cp(); } diff --git a/hotspot/src/share/vm/runtime/handles.cpp b/hotspot/src/share/vm/runtime/handles.cpp index 71ef098459c..bac4652d209 100644 --- a/hotspot/src/share/vm/runtime/handles.cpp +++ b/hotspot/src/share/vm/runtime/handles.cpp @@ -218,9 +218,4 @@ ResetNoHandleMark::~ResetNoHandleMark() { area->_no_handle_mark_nesting = _no_handle_mark_nesting; } -bool instanceKlassHandle::is_instanceKlass(const Klass* k) { - // Need this to avoid circular include dependency - return k->is_instance_klass(); -} - #endif diff --git a/hotspot/src/share/vm/runtime/handles.hpp b/hotspot/src/share/vm/runtime/handles.hpp index 1a132761ed7..94a2b1fbc53 100644 --- a/hotspot/src/share/vm/runtime/handles.hpp +++ b/hotspot/src/share/vm/runtime/handles.hpp @@ -166,48 +166,6 @@ DEF_HANDLE(typeArray , is_typeArray_noinline ) DEF_METADATA_HANDLE(method, Method) DEF_METADATA_HANDLE(constantPool, ConstantPool) -// Writing this class explicitly, since DEF_METADATA_HANDLE(klass) doesn't -// provide the necessary Klass* <-> Klass* conversions. This Klass -// could be removed when we don't have the Klass* typedef anymore. -class KlassHandle : public StackObj { - Klass* _value; - protected: - Klass* obj() const { return _value; } - Klass* non_null_obj() const { assert(_value != NULL, "resolving NULL _value"); return _value; } - - public: - KlassHandle() : _value(NULL) {} - KlassHandle(const Klass* obj) : _value(const_cast(obj)) {}; - KlassHandle(Thread* thread, const Klass* obj) : _value(const_cast(obj)) {}; - - Klass* operator () () const { return obj(); } - Klass* operator -> () const { return non_null_obj(); } - - bool operator == (Klass* o) const { return obj() == o; } - bool operator == (const KlassHandle& h) const { return obj() == h.obj(); } - - bool is_null() const { return _value == NULL; } - bool not_null() const { return _value != NULL; } -}; - -class instanceKlassHandle : public KlassHandle { - public: - /* Constructors */ - instanceKlassHandle () : KlassHandle() {} - instanceKlassHandle (const Klass* k) : KlassHandle(k) { - assert(k == NULL || is_instanceKlass(k), "illegal type"); - } - instanceKlassHandle (Thread* thread, const Klass* k) : KlassHandle(thread, k) { - assert(k == NULL || is_instanceKlass(k), "illegal type"); - } - /* Access to klass part */ - InstanceKlass* operator () () const { return (InstanceKlass*)obj(); } - InstanceKlass* operator -> () const { return (InstanceKlass*)obj(); } - - debug_only(bool is_instanceKlass(const Klass* k)); -}; - - //------------------------------------------------------------------------------------------------------------------------ // Thread local handle area class HandleArea: public Arena { diff --git a/hotspot/src/share/vm/runtime/handles.inline.hpp b/hotspot/src/share/vm/runtime/handles.inline.hpp index 2e205e0a557..7037ec13779 100644 --- a/hotspot/src/share/vm/runtime/handles.inline.hpp +++ b/hotspot/src/share/vm/runtime/handles.inline.hpp @@ -40,7 +40,7 @@ inline Handle::Handle(Thread* thread, oop obj) { } } -// Constructors for metadata handles +// Constructor for metadata handles #define DEF_METADATA_HANDLE_FN(name, type) \ inline name##Handle::name##Handle(type* obj) : _value(obj), _thread(NULL) { \ if (obj != NULL) { \ diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index 5874699a1fc..c7817569182 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -179,10 +179,10 @@ static BasicType runtime_type_from(JavaValue* result) { // ============ Virtual calls ============ -void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { +void JavaCalls::call_virtual(JavaValue* result, Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; Handle receiver = args->receiver(); - KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass()); + Klass* recvrKlass = receiver.is_null() ? (Klass*)NULL : receiver->klass(); LinkInfo link_info(spec_klass, name, signature); LinkResolver::resolve_virtual_call( callinfo, receiver, recvrKlass, link_info, true, CHECK); @@ -194,13 +194,13 @@ void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* } -void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS) { +void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, TRAPS) { JavaCallArguments args(receiver); // One oop argument call_virtual(result, spec_klass, name, signature, &args, CHECK); } -void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { +void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { JavaCallArguments args(receiver); // One oop argument args.push_oop(arg1); call_virtual(result, spec_klass, name, signature, &args, CHECK); @@ -208,7 +208,7 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe -void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { +void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { JavaCallArguments args(receiver); // One oop argument args.push_oop(arg1); args.push_oop(arg2); @@ -218,7 +218,7 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe // ============ Special calls ============ -void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { +void JavaCalls::call_special(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; LinkInfo link_info(klass, name, signature); LinkResolver::resolve_special_call(callinfo, link_info, CHECK); @@ -230,20 +230,20 @@ void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, } -void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { +void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, TRAPS) { JavaCallArguments args(receiver); // One oop argument call_special(result, klass, name, signature, &args, CHECK); } -void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { +void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { JavaCallArguments args(receiver); // One oop argument args.push_oop(arg1); call_special(result, klass, name, signature, &args, CHECK); } -void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { +void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { JavaCallArguments args(receiver); // One oop argument args.push_oop(arg1); args.push_oop(arg2); @@ -253,7 +253,7 @@ void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle kla // ============ Static calls ============ -void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { +void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; LinkInfo link_info(klass, name, signature); LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK); @@ -265,19 +265,19 @@ void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, } -void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { +void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, TRAPS) { JavaCallArguments args; // No argument call_static(result, klass, name, signature, &args, CHECK); } -void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { +void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { JavaCallArguments args(arg1); // One oop argument call_static(result, klass, name, signature, &args, CHECK); } -void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { +void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { JavaCallArguments args; // One oop argument args.push_oop(arg1); args.push_oop(arg2); @@ -285,7 +285,7 @@ void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, } -void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS) { +void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS) { JavaCallArguments args; // One oop argument args.push_oop(arg1); args.push_oop(arg2); diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index efe1f8b9813..acdc96d8ad8 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,30 +187,30 @@ class JavaCalls: AllStatic { // call_special // ------------ // The receiver must be first oop in argument list - static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); + static void call_special(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); - static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args - static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); - static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); + static void call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, TRAPS); // No args + static void call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); + static void call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); // virtual call // ------------ // The receiver must be first oop in argument list - static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); + static void call_virtual(JavaValue* result, Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); - static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args - static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); - static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); + static void call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args + static void call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); + static void call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); // Static call // ----------- - static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); + static void call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); - static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); - static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); - static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); - static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS); + static void call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, TRAPS); + static void call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); + static void call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); + static void call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS); // Low-level interface static void call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS); diff --git a/hotspot/src/share/vm/runtime/jfieldIDWorkaround.hpp b/hotspot/src/share/vm/runtime/jfieldIDWorkaround.hpp index a1831ab8fc6..6c3589d2d24 100644 --- a/hotspot/src/share/vm/runtime/jfieldIDWorkaround.hpp +++ b/hotspot/src/share/vm/runtime/jfieldIDWorkaround.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -150,13 +150,13 @@ class jfieldIDWorkaround: AllStatic { return result; } - static jfieldID to_jfieldID(instanceKlassHandle k, int offset, bool is_static) { + static jfieldID to_jfieldID(InstanceKlass* k, int offset, bool is_static) { if (is_static) { JNIid *id = k->jni_id_for(offset); debug_only(id->set_is_static_field_id()); return jfieldIDWorkaround::to_static_jfieldID(id); } else { - return jfieldIDWorkaround::to_instance_jfieldID(k(), offset); + return jfieldIDWorkaround::to_instance_jfieldID(k, offset); } } }; diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index b48edb441fb..6098a0bcf89 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -291,9 +291,8 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { default: { // Dispatch the signal to java HandleMark hm(THREAD); - Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_misc_Signal(), THREAD); - KlassHandle klass (THREAD, k); - if (klass.not_null()) { + Klass* klass = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_misc_Signal(), THREAD); + if (klass != NULL) { JavaValue result(T_VOID); JavaCallArguments args; args.push_int(sig); @@ -352,8 +351,8 @@ void os::signal_init(TRAPS) { if (!ReduceSignalUsage) { // Setup JavaThread for processing signals Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK); - instanceKlassHandle klass (THREAD, k); - instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); + InstanceKlass* ik = InstanceKlass::cast(k); + instanceHandle thread_oop = ik->allocate_instance_handle(CHECK); const char thread_name[] = "Signal Dispatcher"; Handle string = java_lang_String::create_from_str(thread_name, CHECK); @@ -362,14 +361,14 @@ void os::signal_init(TRAPS) { Handle thread_group (THREAD, Universe::system_thread_group()); JavaValue result(T_VOID); JavaCalls::call_special(&result, thread_oop, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::threadgroup_string_void_signature(), thread_group, string, CHECK); - KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); + Klass* group = SystemDictionary::ThreadGroup_klass(); JavaCalls::call_special(&result, thread_group, group, diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index e6e1abdf82a..4f9dc8d9cfd 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -708,7 +708,7 @@ bool Reflection::is_same_class_package(const Klass* class1, const Klass* class2) // If inner_is_member, require the inner to be a member of the outer. // If !inner_is_member, require the inner to be anonymous (a non-member). // Caller is responsible for figuring out in advance which case must be true. -void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, +void Reflection::check_for_inner_class(const InstanceKlass* outer, const InstanceKlass* inner, bool inner_is_member, TRAPS) { InnerClassesIterator iter(outer); constantPoolHandle cp (THREAD, outer->constants()); @@ -718,9 +718,9 @@ void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassH if (inner_is_member && ioff != 0 && ooff != 0) { Klass* o = cp->klass_at(ooff, CHECK); - if (o == outer()) { + if (o == outer) { Klass* i = cp->klass_at(ioff, CHECK); - if (i == inner()) { + if (i == inner) { return; } } @@ -728,7 +728,7 @@ void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassH if (!inner_is_member && ioff != 0 && ooff == 0 && cp->klass_name_at_matches(inner, ioff)) { Klass* i = cp->klass_at(ioff, CHECK); - if (i == inner()) { + if (i == inner) { return; } } @@ -802,7 +802,7 @@ static objArrayHandle get_exception_types(methodHandle method, TRAPS) { return method->resolved_checked_exceptions(THREAD); } -static Handle new_type(Symbol* signature, KlassHandle k, TRAPS) { +static Handle new_type(Symbol* signature, Klass* k, TRAPS) { // Basic types BasicType type = vmSymbols::signature_type(signature); if (type != T_OBJECT) { @@ -829,7 +829,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac assert(!method()->is_initializer() || (for_constant_pool_access && method()->is_static()), "should call new_constructor instead"); - instanceKlassHandle holder (THREAD, method->method_holder()); + InstanceKlass* holder = method->method_holder(); int slot = method->method_idnum(); Symbol* signature = method->signature(); @@ -890,7 +890,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac oop Reflection::new_constructor(const methodHandle& method, TRAPS) { assert(method()->is_initializer(), "should call new_method instead"); - instanceKlassHandle holder (THREAD, method->method_holder()); + InstanceKlass* holder = method->method_holder(); int slot = method->method_idnum(); Symbol* signature = method->signature(); @@ -938,7 +938,7 @@ oop Reflection::new_field(fieldDescriptor* fd, TRAPS) { oop name_oop = StringTable::intern(field_name, CHECK_NULL); Handle name = Handle(THREAD, name_oop); Symbol* signature = fd->signature(); - instanceKlassHandle holder (THREAD, fd->field_holder()); + InstanceKlass* holder = fd->field_holder(); Handle type = new_type(signature, holder, CHECK_NULL); Handle rh = java_lang_reflect_Field::create(CHECK_NULL); @@ -985,9 +985,9 @@ oop Reflection::new_parameter(Handle method, int index, Symbol* sym, } -static methodHandle resolve_interface_call(instanceKlassHandle klass, +static methodHandle resolve_interface_call(InstanceKlass* klass, const methodHandle& method, - KlassHandle recv_klass, + Klass* recv_klass, Handle receiver, TRAPS) { @@ -1035,7 +1035,7 @@ static void narrow(jvalue* value, BasicType narrow_type, TRAPS) { // Method call (shared by invoke_method and invoke_constructor) -static oop invoke(instanceKlassHandle klass, +static oop invoke(InstanceKlass* klass, methodHandle reflected_method, Handle receiver, bool override, @@ -1048,7 +1048,7 @@ static oop invoke(instanceKlassHandle klass, ResourceMark rm(THREAD); methodHandle method; // actual method to invoke - KlassHandle target_klass; // target klass, receiver's klass for non-static + Klass* target_klass; // target klass, receiver's klass for non-static // Ensure klass is initialized klass->initialize(CHECK_NULL); @@ -1064,11 +1064,11 @@ static oop invoke(instanceKlassHandle klass, THROW_0(vmSymbols::java_lang_NullPointerException()); } // Check class of receiver against class declaring method - if (!receiver->is_a(klass())) { + if (!receiver->is_a(klass)) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class"); } // target klass is receiver's klass - target_klass = KlassHandle(THREAD, receiver->klass()); + target_klass = receiver->klass(); // no need to resolve if method is private or if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) { method = reflected_method; @@ -1109,7 +1109,7 @@ static oop invoke(instanceKlassHandle klass, ResourceMark rm(THREAD); Handle h_origexception = Exceptions::new_exception(THREAD, vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(target_klass(), + Method::name_and_sig_as_C_string(target_klass, method->name(), method->signature())); JavaCallArguments args(h_origexception); @@ -1127,7 +1127,7 @@ static oop invoke(instanceKlassHandle klass, if (method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(klass(), + Method::name_and_sig_as_C_string(klass, reflected_method->name(), reflected_method->signature())); } @@ -1229,7 +1229,7 @@ oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle rtype = T_OBJECT; } - instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror)); + InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); Method* m = klass->method_with_idnum(slot); if (m == NULL) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); @@ -1246,7 +1246,7 @@ oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, bool override = java_lang_reflect_Constructor::override(constructor_mirror) != 0; objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror))); - instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror)); + InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); Method* m = klass->method_with_idnum(slot); if (m == NULL) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); diff --git a/hotspot/src/share/vm/runtime/reflection.hpp b/hotspot/src/share/vm/runtime/reflection.hpp index 75ba5d77820..bd7abb2d287 100644 --- a/hotspot/src/share/vm/runtime/reflection.hpp +++ b/hotspot/src/share/vm/runtime/reflection.hpp @@ -103,8 +103,8 @@ class Reflection: public AllStatic { // If inner_is_member, require the inner to be a member of the outer. // If !inner_is_member, require the inner to be anonymous (a non-member). // Caller is responsible for figuring out in advance which case must be true. - static void check_for_inner_class(instanceKlassHandle outer, - instanceKlassHandle inner, + static void check_for_inner_class(const InstanceKlass* outer, + const InstanceKlass* inner, bool inner_is_member, TRAPS); diff --git a/hotspot/src/share/vm/runtime/reflectionUtils.cpp b/hotspot/src/share/vm/runtime/reflectionUtils.cpp index b32d083d7e4..6bc79d5f468 100644 --- a/hotspot/src/share/vm/runtime/reflectionUtils.cpp +++ b/hotspot/src/share/vm/runtime/reflectionUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "memory/universe.inline.hpp" #include "runtime/reflectionUtils.hpp" -KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, +KlassStream::KlassStream(InstanceKlass* klass, bool local_only, bool classes_only, bool walk_defaults) { _klass = _base_klass = klass; _base_class_search_defaults = false; @@ -48,7 +48,7 @@ bool KlassStream::eos() { if (_local_only) return true; if (!_klass->is_interface() && _klass->super() != NULL) { // go up superclass chain (not for interfaces) - _klass = _klass->super(); + _klass = InstanceKlass::cast(_klass->super()); // Next for method walks, walk default methods } else if (_walk_defaults && (_defaults_checked == false) && (_base_klass->default_methods() != NULL)) { _base_class_search_defaults = true; @@ -57,7 +57,7 @@ bool KlassStream::eos() { } else { // Next walk transitive interfaces if (_interface_index > 0) { - _klass = _interfaces->at(--_interface_index); + _klass = InstanceKlass::cast(_interfaces->at(--_interface_index)); } else { return true; } diff --git a/hotspot/src/share/vm/runtime/reflectionUtils.hpp b/hotspot/src/share/vm/runtime/reflectionUtils.hpp index 1f5b87f8d39..28abd1c0234 100644 --- a/hotspot/src/share/vm/runtime/reflectionUtils.hpp +++ b/hotspot/src/share/vm/runtime/reflectionUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -45,8 +45,8 @@ class KlassStream VALUE_OBJ_CLASS_SPEC { protected: - instanceKlassHandle _klass; // current klass/interface iterated over - instanceKlassHandle _base_klass; // initial klass/interface to iterate over + InstanceKlass* _klass; // current klass/interface iterated over + InstanceKlass* _base_klass; // initial klass/interface to iterate over Array* _interfaces; // transitive interfaces for initial class int _interface_index; // current interface being processed bool _local_only; // process initial class/interface only @@ -60,7 +60,7 @@ class KlassStream VALUE_OBJ_CLASS_SPEC { public: // constructor - KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults); + KlassStream(InstanceKlass* klass, bool local_only, bool classes_only, bool walk_defaults); // testing bool eos(); @@ -69,7 +69,7 @@ class KlassStream VALUE_OBJ_CLASS_SPEC { virtual void next() = 0; // accessors - instanceKlassHandle klass() const { return _klass; } + InstanceKlass* klass() const { return _klass; } int index() const { return _index; } bool base_class_search_defaults() const { return _base_class_search_defaults; } void base_class_search_defaults(bool b) { _base_class_search_defaults = b; } @@ -97,7 +97,7 @@ class MethodStream : public KlassStream { } } public: - MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only) + MethodStream(InstanceKlass* klass, bool local_only, bool classes_only) : KlassStream(klass, local_only, classes_only, true) { _index = length(); next(); @@ -125,7 +125,7 @@ class FieldStream : public KlassStream { fieldDescriptor _fd_buf; public: - FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) + FieldStream(InstanceKlass* klass, bool local_only, bool classes_only) : KlassStream(klass, local_only, classes_only, false) { _index = length(); next(); @@ -152,7 +152,7 @@ class FieldStream : public KlassStream { // bridge to a heavier API: fieldDescriptor& field_descriptor() const { fieldDescriptor& field = const_cast(_fd_buf); - field.reinitialize(_klass(), _index); + field.reinitialize(_klass, _index); return field; } }; @@ -222,15 +222,15 @@ class FilteredFieldStream : public FieldStream { bool has_filtered_field() { return (_filtered_fields_count > 0); } public: - FilteredFieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) + FilteredFieldStream(InstanceKlass* klass, bool local_only, bool classes_only) : FieldStream(klass, local_only, classes_only) { - _filtered_fields_count = FilteredFieldsMap::filtered_fields_count((Klass*)klass(), local_only); + _filtered_fields_count = FilteredFieldsMap::filtered_fields_count(klass, local_only); } int field_count(); void next() { _index -= 1; if (has_filtered_field()) { - while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass(), offset())) { + while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass, offset())) { _index -= 1; } } diff --git a/hotspot/src/share/vm/runtime/serviceThread.cpp b/hotspot/src/share/vm/runtime/serviceThread.cpp index ccdf00ce702..a3411422758 100644 --- a/hotspot/src/share/vm/runtime/serviceThread.cpp +++ b/hotspot/src/share/vm/runtime/serviceThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -40,7 +40,7 @@ ServiceThread* ServiceThread::_instance = NULL; void ServiceThread::initialize() { EXCEPTION_MARK; - instanceKlassHandle klass (THREAD, SystemDictionary::Thread_klass()); + InstanceKlass* klass = SystemDictionary::Thread_klass(); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); const char* name = "Service Thread"; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index afd8c1d5d32..24ecc0a649e 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -675,7 +675,7 @@ address SharedRuntime::compute_compiled_exc_handler(CompiledMethod* cm, address do { bool skip_scope_increment = false; // exception handler lookup - KlassHandle ek (THREAD, exception->klass()); + Klass* ek = exception->klass(); methodHandle mh(THREAD, sd->method()); handler_bci = Method::fast_exception_handler_bci_for(mh, ek, bci, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -1185,7 +1185,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls if (has_receiver) { assert(receiver.not_null(), "should have thrown exception"); - KlassHandle receiver_klass(THREAD, receiver->klass()); + Klass* receiver_klass = receiver->klass(); Klass* rk = NULL; if (attached_method.not_null()) { // In case there's resolved method attached, use its holder during the check. @@ -1195,16 +1195,16 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, constantPoolHandle constants(THREAD, caller->constants()); rk = constants->klass_ref_at(bytecode_index, CHECK_NH); } - KlassHandle static_receiver_klass(THREAD, rk); + Klass* static_receiver_klass = rk; methodHandle callee = callinfo.selected_method(); - assert(receiver_klass->is_subtype_of(static_receiver_klass()), + assert(receiver_klass->is_subtype_of(static_receiver_klass), "actual receiver must be subclass of static receiver klass"); if (receiver_klass->is_instance_klass()) { - if (InstanceKlass::cast(receiver_klass())->is_not_initialized()) { + if (InstanceKlass::cast(receiver_klass)->is_not_initialized()) { tty->print_cr("ERROR: Klass not yet initialized!!"); - receiver_klass()->print(); + receiver_klass->print(); } - assert(!InstanceKlass::cast(receiver_klass())->is_not_initialized(), "receiver_klass must be initialized"); + assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized(), "receiver_klass must be initialized"); } } #endif @@ -1363,8 +1363,8 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, if (is_virtual) { assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check"); bool static_bound = call_info.resolved_method()->can_be_statically_bound(); - KlassHandle h_klass(THREAD, invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass()); - CompiledIC::compute_monomorphic_entry(callee_method, h_klass, + Klass* klass = invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass(); + CompiledIC::compute_monomorphic_entry(callee_method, klass, is_optimized, static_bound, is_nmethod, virtual_call_info, CHECK_(methodHandle())); } else { @@ -1625,7 +1625,7 @@ methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, TRAPS) { // and now we have (or had) a compiled entry. We correct the IC // by using a new icBuffer. CompiledICInfo info; - KlassHandle receiver_klass(THREAD, receiver()->klass()); + Klass* receiver_klass = receiver()->klass(); inline_cache->compute_monomorphic_entry(callee_method, receiver_klass, inline_cache->is_optimized(), diff --git a/hotspot/src/share/vm/runtime/statSampler.cpp b/hotspot/src/share/vm/runtime/statSampler.cpp index cc88f88bead..6cdd0743ad1 100644 --- a/hotspot/src/share/vm/runtime/statSampler.cpp +++ b/hotspot/src/share/vm/runtime/statSampler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,7 @@ const char* StatSampler::get_system_property(const char* name, TRAPS) { // public static String getProperty(String key, String def); JavaCalls::call_static(&result, - KlassHandle(THREAD, SystemDictionary::System_klass()), + SystemDictionary::System_klass(), vmSymbols::getProperty_name(), vmSymbols::string_string_signature(), key_str, diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 9c073eb543b..9f7eecceb2b 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -950,27 +950,27 @@ static void initialize_class(Symbol* class_name, TRAPS) { // Creates the initial ThreadGroup static Handle create_initial_thread_group(TRAPS) { Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ThreadGroup(), true, CHECK_NH); - instanceKlassHandle klass (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); - Handle system_instance = klass->allocate_instance_handle(CHECK_NH); + Handle system_instance = ik->allocate_instance_handle(CHECK_NH); { JavaValue result(T_VOID); JavaCalls::call_special(&result, system_instance, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::void_method_signature(), CHECK_NH); } Universe::set_system_thread_group(system_instance()); - Handle main_instance = klass->allocate_instance_handle(CHECK_NH); + Handle main_instance = ik->allocate_instance_handle(CHECK_NH); { JavaValue result(T_VOID); Handle string = java_lang_String::create_from_str("main", CHECK_NH); JavaCalls::call_special(&result, main_instance, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::threadgroup_string_void_signature(), system_instance, @@ -984,8 +984,8 @@ static Handle create_initial_thread_group(TRAPS) { static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS) { Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL); - instanceKlassHandle klass (THREAD, k); - instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL); + InstanceKlass* ik = InstanceKlass::cast(k); + instanceHandle thread_oop = ik->allocate_instance_handle(CHECK_NULL); java_lang_Thread::set_thread(thread_oop(), thread); java_lang_Thread::set_priority(thread_oop(), NormPriority); @@ -995,7 +995,7 @@ static oop create_initial_thread(Handle thread_group, JavaThread* thread, JavaValue result(T_VOID); JavaCalls::call_special(&result, thread_oop, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::threadgroup_string_void_signature(), thread_group, @@ -1054,9 +1054,8 @@ static const char* get_java_runtime_version(TRAPS) { // General purpose hook into Java code, run once when the VM is initialized. // The Java library method itself may be changed independently from the VM. static void call_postVMInitHook(TRAPS) { - Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_vm_PostVMInitHook(), THREAD); - instanceKlassHandle klass (THREAD, k); - if (klass.not_null()) { + Klass* klass = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_vm_PostVMInitHook(), THREAD); + if (klass != NULL) { JavaValue result(T_VOID); JavaCalls::call_static(&result, klass, vmSymbols::run_method_name(), vmSymbols::void_method_signature(), @@ -1070,8 +1069,7 @@ static void reset_vm_info_property(TRAPS) { const char *vm_info = VM_Version::vm_info_string(); // java.lang.System class - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); - instanceKlassHandle klass (THREAD, k); + Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); // setProperty arguments Handle key_str = java_lang_String::create_from_str("java.vm.info", CHECK); @@ -1097,8 +1095,8 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name assert(threadObj() == NULL, "should only create Java thread object once"); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK); - instanceKlassHandle klass (THREAD, k); - instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); + InstanceKlass* ik = InstanceKlass::cast(k); + instanceHandle thread_oop = ik->allocate_instance_handle(CHECK); java_lang_Thread::set_thread(thread_oop(), this); java_lang_Thread::set_priority(thread_oop(), NormPriority); @@ -1110,7 +1108,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name // Thread gets assigned specified name and null target JavaCalls::call_special(&result, thread_oop, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::threadgroup_string_void_signature(), thread_group, // Argument 1 @@ -1121,7 +1119,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name // (java.lang.Thread doesn't have a constructor taking only a ThreadGroup argument) JavaCalls::call_special(&result, thread_oop, - klass, + ik, vmSymbols::object_initializer_name(), vmSymbols::threadgroup_runnable_void_signature(), thread_group, // Argument 1 @@ -1138,7 +1136,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name return; } - KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); + Klass* group = SystemDictionary::ThreadGroup_klass(); Handle threadObj(THREAD, this->threadObj()); JavaCalls::call_special(&result, @@ -1779,7 +1777,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { if (uncaught_exception.not_null()) { EXCEPTION_MARK; // Call method Thread.dispatchUncaughtException(). - KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); + Klass* thread_klass = SystemDictionary::Thread_klass(); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, threadObj, thread_klass, @@ -1817,7 +1815,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) { EXCEPTION_MARK; JavaValue result(T_VOID); - KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); + Klass* thread_klass = SystemDictionary::Thread_klass(); JavaCalls::call_virtual(&result, threadObj, thread_klass, vmSymbols::exit_method_name(), @@ -3388,9 +3386,7 @@ void Threads::threads_do(ThreadClosure* tc) { // fields in, out, and err. Set up java signal handlers, OS-specific // system settings, and thread group of the main thread. static void call_initPhase1(TRAPS) { - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); - instanceKlassHandle klass (THREAD, k); - + Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); JavaValue result(T_VOID); JavaCalls::call_static(&result, klass, vmSymbols::initPhase1_name(), vmSymbols::void_method_signature(), CHECK); @@ -3410,8 +3406,7 @@ static void call_initPhase1(TRAPS) { static void call_initPhase2(TRAPS) { TraceTime timer("Phase2 initialization", TRACETIME_LOG(Info, modules, startuptime)); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); - instanceKlassHandle klass (THREAD, k); + Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); JavaValue result(T_VOID); JavaCalls::call_static(&result, klass, vmSymbols::initPhase2_name(), @@ -3426,9 +3421,7 @@ static void call_initPhase2(TRAPS) { // and system class loader may be a custom class loaded from -Xbootclasspath/a, // other modules or the application's classpath. static void call_initPhase3(TRAPS) { - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); - instanceKlassHandle klass (THREAD, k); - + Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); JavaValue result(T_VOID); JavaCalls::call_static(&result, klass, vmSymbols::initPhase3_name(), vmSymbols::void_method_signature(), CHECK); @@ -4064,10 +4057,10 @@ void JavaThread::invoke_shutdown_hooks() { } EXCEPTION_MARK; - Klass* k = + Klass* shutdown_klass = SystemDictionary::resolve_or_null(vmSymbols::java_lang_Shutdown(), THREAD); - if (k != NULL) { + if (shutdown_klass != NULL) { // SystemDictionary::resolve_or_null will return null if there was // an exception. If we cannot load the Shutdown class, just don't // call Shutdown.shutdown() at all. This will mean the shutdown hooks @@ -4075,7 +4068,6 @@ void JavaThread::invoke_shutdown_hooks() { // Note that if a shutdown hook was registered or runFinalizersOnExit // was called, the Shutdown class would have already been loaded // (Runtime.addShutdownHook and runFinalizersOnExit will load it). - instanceKlassHandle shutdown_klass (THREAD, k); JavaValue result(T_VOID); JavaCalls::call_static(&result, shutdown_klass, diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index db7b310c9e1..af415ef6da4 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.cpp @@ -521,14 +521,14 @@ void vframeStreamCommon::skip_prefixed_method_and_wrappers() { int method_prefix_count = 0; char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count); - KlassHandle prefixed_klass(method()->method_holder()); + Klass* prefixed_klass = method()->method_holder(); const char* prefixed_name = method()->name()->as_C_string(); size_t prefixed_name_len = strlen(prefixed_name); int prefix_index = method_prefix_count-1; while (!at_end()) { next(); - if (method()->method_holder() != prefixed_klass()) { + if (method()->method_holder() != prefixed_klass) { break; // classes don't match, can't be a wrapper } const char* name = method()->name()->as_C_string(); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index d5b9e3db03c..55411ccfdd8 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -194,9 +194,9 @@ typedef Hashtable IntptrHashtable; typedef Hashtable SymbolHashtable; typedef HashtableEntry SymbolHashtableEntry; typedef Hashtable StringHashtable; -typedef TwoOopHashtable KlassTwoOopHashtable; -typedef Hashtable KlassHashtable; -typedef HashtableEntry KlassHashtableEntry; +typedef TwoOopHashtable KlassTwoOopHashtable; +typedef Hashtable KlassHashtable; +typedef HashtableEntry KlassHashtableEntry; typedef TwoOopHashtable SymbolTwoOopHashtable; typedef CompactHashtable SymbolCompactHashTable; diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 2807768339f..2dd1ce13d34 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -292,7 +292,7 @@ class VM_DeoptimizeFrame: public VM_Operation { #ifndef PRODUCT class VM_DeoptimizeAll: public VM_Operation { private: - KlassHandle _dependee; + Klass* _dependee; public: VM_DeoptimizeAll() {} VMOp_Type type() const { return VMOp_DeoptimizeAll; } diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index 0de704d6913..1e49bec6b52 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -46,13 +46,13 @@ volatile bool AttachListener::_initialized; // Invokes VMSupport.serializePropertiesToByteArray to serialize // the system properties into a byte array. -static Klass* load_and_initialize_klass(Symbol* sh, TRAPS) { +static InstanceKlass* load_and_initialize_klass(Symbol* sh, TRAPS) { Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); - instanceKlassHandle ik (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); if (ik->should_be_initialized()) { ik->initialize(CHECK_NULL); } - return ik(); + return ik; } static jint get_properties(AttachOperation* op, outputStream* out, Symbol* serializePropertiesMethod) { @@ -61,13 +61,12 @@ static jint get_properties(AttachOperation* op, outputStream* out, Symbol* seria // load VMSupport Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport(); - Klass* k = load_and_initialize_klass(klass, THREAD); + InstanceKlass* k = load_and_initialize_klass(klass, THREAD); if (HAS_PENDING_EXCEPTION) { java_lang_Throwable::print(PENDING_EXCEPTION, out); CLEAR_PENDING_EXCEPTION; return JNI_ERR; } - instanceKlassHandle ik(THREAD, k); // invoke the serializePropertiesToByteArray method JavaValue result(T_OBJECT); @@ -76,11 +75,11 @@ static jint get_properties(AttachOperation* op, outputStream* out, Symbol* seria Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); JavaCalls::call_static(&result, - ik, - serializePropertiesMethod, - signature, - &args, - THREAD); + k, + serializePropertiesMethod, + signature, + &args, + THREAD); if (HAS_PENDING_EXCEPTION) { java_lang_Throwable::print(PENDING_EXCEPTION, out); CLEAR_PENDING_EXCEPTION; @@ -374,7 +373,7 @@ void AttachListener::init() { return; } - instanceKlassHandle klass (THREAD, k); + InstanceKlass* klass = InstanceKlass::cast(k); instanceHandle thread_oop = klass->allocate_instance_handle(THREAD); if (has_init_error(THREAD)) { return; @@ -401,7 +400,7 @@ void AttachListener::init() { return; } - KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); + Klass* group = SystemDictionary::ThreadGroup_klass(); JavaCalls::call_special(&result, thread_group, group, diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 185c04eeafa..49c45ca0cd1 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -197,24 +197,21 @@ void ClassLoadingService::reset_trace_class_unloading() { LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload)); } -GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; -Thread* LoadedClassesEnumerator::_current_thread = NULL; +GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; -LoadedClassesEnumerator::LoadedClassesEnumerator(Thread* cur_thread) { - assert(cur_thread == Thread::current(), "Check current thread"); +LoadedClassesEnumerator::LoadedClassesEnumerator() { int init_size = ClassLoadingService::loaded_class_count(); - _klass_handle_array = new GrowableArray(init_size); + _klass_array = new GrowableArray(init_size); // For consistency of the loaded classes, grab the SystemDictionary lock MutexLocker sd_mutex(SystemDictionary_lock); - // Set _loaded_classes and _current_thread and begin enumerating all classes. + // Set _loaded_classes and begin enumerating all classes. // Only one thread will do the enumeration at a time. // These static variables are needed and they are used by the static method // add_loaded_class called from classes_do(). - _loaded_classes = _klass_handle_array; - _current_thread = cur_thread; + _loaded_classes = _klass_array; SystemDictionary::classes_do(&add_loaded_class); diff --git a/hotspot/src/share/vm/services/classLoadingService.hpp b/hotspot/src/share/vm/services/classLoadingService.hpp index 763abcc1656..65d573b626a 100644 --- a/hotspot/src/share/vm/services/classLoadingService.hpp +++ b/hotspot/src/share/vm/services/classLoadingService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -120,17 +120,14 @@ public: // FIXME: make this piece of code to be shared by M&M and JVMTI class LoadedClassesEnumerator : public StackObj { private: - static GrowableArray* _loaded_classes; - // _current_thread is for creating a KlassHandle with a faster version constructor - static Thread* _current_thread; - - GrowableArray* _klass_handle_array; + static GrowableArray* _loaded_classes; + GrowableArray* _klass_array; public: - LoadedClassesEnumerator(Thread* cur_thread); + LoadedClassesEnumerator(); - int num_loaded_classes() { return _klass_handle_array->length(); } - KlassHandle get_klass(int index) { return _klass_handle_array->at(index); } + int num_loaded_classes() { return _klass_array->length(); } + Klass* get_klass(int index) { return _klass_array->at(index); } static void add_loaded_class(Klass* k) { // FIXME: For now - don't include array klasses @@ -138,11 +135,9 @@ public: // and also indirect creation of array of super class and secondaries // // for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - // KlassHandle h(_current_thread, l); - // _loaded_classes->append(h); + // _loaded_classes->append(l); // } - KlassHandle h(_current_thread, k); - _loaded_classes->append(h); + _loaded_classes->append(k); } }; diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index a34a33fc3d4..fba237f28f5 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -324,7 +324,7 @@ void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) { // load VMSupport Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport(); Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK); - instanceKlassHandle ik (THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); if (ik->should_be_initialized()) { ik->initialize(THREAD); } @@ -405,9 +405,8 @@ void SystemGCDCmd::execute(DCmdSource source, TRAPS) { void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) { Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); - instanceKlassHandle klass(THREAD, k); JavaValue result(T_VOID); - JavaCalls::call_static(&result, klass, + JavaCalls::call_static(&result, k, vmSymbols::run_finalization_name(), vmSymbols::void_method_signature(), CHECK); } @@ -423,13 +422,12 @@ void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) { Klass* k = SystemDictionary::resolve_or_fail( vmSymbols::finalizer_histogram_klass(), true, CHECK); - instanceKlassHandle klass(THREAD, k); JavaValue result(T_ARRAY); // We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method // and expect it to return array of FinalizerHistogramEntry as Object[] - JavaCalls::call_static(&result, klass, + JavaCalls::call_static(&result, k, vmSymbols::get_finalizer_histogram_name(), vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK); @@ -753,7 +751,6 @@ void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) { Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); - instanceKlassHandle ik (THREAD, k); JavaValue result(T_VOID); @@ -807,7 +804,7 @@ void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) { #undef PUT_OPTION Handle str = java_lang_String::create_from_str(options.as_string(), CHECK); - JavaCalls::call_static(&result, ik, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK); + JavaCalls::call_static(&result, k, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK); } JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) : @@ -826,10 +823,9 @@ void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) { Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); - instanceKlassHandle ik (THREAD, k); JavaValue result(T_VOID); - JavaCalls::call_static(&result, ik, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK); + JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK); } void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) { @@ -843,10 +839,9 @@ void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) { Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); - instanceKlassHandle ik (THREAD, k); JavaValue result(T_VOID); - JavaCalls::call_static(&result, ik, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK); + JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK); } JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) : @@ -864,10 +859,9 @@ void JMXStatusDCmd::execute(DCmdSource source, TRAPS) { Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); - instanceKlassHandle ik (THREAD, k); JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, ik, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK); + JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK); jvalue* jv = (jvalue*) result.get_value_addr(); oop str = (oop) jv->l; diff --git a/hotspot/src/share/vm/services/diagnosticFramework.cpp b/hotspot/src/share/vm/services/diagnosticFramework.cpp index 09c310768d5..9b1715a6782 100644 --- a/hotspot/src/share/vm/services/diagnosticFramework.cpp +++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -457,7 +457,7 @@ void DCmdFactory::send_notification_internal(TRAPS) { if (notif) { Klass* k = Management::com_sun_management_internal_DiagnosticCommandImpl_klass(CHECK); - instanceKlassHandle dcmd_mbean_klass(THREAD, k); + InstanceKlass* dcmd_mbean_klass = InstanceKlass::cast(k); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, diff --git a/hotspot/src/share/vm/services/gcNotifier.cpp b/hotspot/src/share/vm/services/gcNotifier.cpp index b037fd24a39..98d5ccdb7ab 100644 --- a/hotspot/src/share/vm/services/gcNotifier.cpp +++ b/hotspot/src/share/vm/services/gcNotifier.cpp @@ -79,8 +79,7 @@ bool GCNotifier::has_event() { static Handle getGcInfoBuilder(GCMemoryManager *gcManager,TRAPS) { - Klass* k = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_NH); - instanceKlassHandle gcMBeanKlass (THREAD, k); + Klass* gcMBeanKlass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_NH); instanceOop i = gcManager->get_memory_manager_instance(THREAD); instanceHandle ih(THREAD, i); @@ -102,16 +101,15 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR // Fill the arrays of MemoryUsage objects with before and after GC // per pool memory usage - Klass* mu_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); - instanceKlassHandle mu_kh(THREAD, mu_klass); + InstanceKlass* mu_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); // The array allocations below should use a handle containing mu_klass // as the first allocation could trigger a GC, causing the actual // klass oop to move, and leaving mu_klass pointing to the old // location. - objArrayOop bu = oopFactory::new_objArray(mu_kh(), MemoryService::num_memory_pools(), CHECK_NH); + objArrayOop bu = oopFactory::new_objArray(mu_klass, MemoryService::num_memory_pools(), CHECK_NH); objArrayHandle usage_before_gc_ah(THREAD, bu); - objArrayOop au = oopFactory::new_objArray(mu_kh(), MemoryService::num_memory_pools(), CHECK_NH); + objArrayOop au = oopFactory::new_objArray(mu_klass, MemoryService::num_memory_pools(), CHECK_NH); objArrayHandle usage_after_gc_ah(THREAD, au); for (int i = 0; i < MemoryService::num_memory_pools(); i++) { @@ -135,8 +133,7 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR // The type is 'I' objArrayOop extra_args_array = oopFactory::new_objArray(SystemDictionary::Integer_klass(), 1, CHECK_NH); objArrayHandle extra_array (THREAD, extra_args_array); - Klass* itKlass = SystemDictionary::Integer_klass(); - instanceKlassHandle intK(THREAD, itKlass); + InstanceKlass* intK = SystemDictionary::Integer_klass(); instanceHandle extra_arg_val = intK->allocate_instance_handle(CHECK_NH); @@ -155,10 +152,9 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR } extra_array->obj_at_put(0,extra_arg_val()); - Klass* gcInfoklass = Management::com_sun_management_GcInfo_klass(CHECK_NH); - instanceKlassHandle ik(THREAD, gcInfoklass); + InstanceKlass* gcInfoklass = Management::com_sun_management_GcInfo_klass(CHECK_NH); - Handle gcInfo_instance = ik->allocate_instance_handle(CHECK_NH); + Handle gcInfo_instance = gcInfoklass->allocate_instance_handle(CHECK_NH); JavaValue constructor_result(T_VOID); JavaCallArguments constructor_args(16); @@ -172,7 +168,7 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR constructor_args.push_oop(extra_array); JavaCalls::call_special(&constructor_result, - ik, + gcInfoklass, vmSymbols::object_initializer_name(), vmSymbols::com_sun_management_GcInfo_constructor_signature(), &constructor_args, @@ -216,13 +212,11 @@ void GCNotifier::sendNotificationInternal(TRAPS) { Handle objName = java_lang_String::create_from_str(request->gcManager->name(), CHECK); Handle objAction = java_lang_String::create_from_str(request->gcAction, CHECK); Handle objCause = java_lang_String::create_from_str(request->gcCause, CHECK); - Klass* k = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK); - - instanceKlassHandle gc_mbean_klass(THREAD, k); + InstanceKlass* gc_mbean_klass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK); instanceOop gc_mbean = request->gcManager->get_memory_manager_instance(THREAD); instanceHandle gc_mbean_h(THREAD, gc_mbean); - if (!gc_mbean_h->is_a(k)) { + if (!gc_mbean_h->is_a(gc_mbean_klass)) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "This GCMemoryManager doesn't have a GarbageCollectorMXBean"); } diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 2b5cd47db05..cbb71a9ce58 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -814,11 +814,11 @@ void DumperSupport::dump_field_value(DumpWriter* writer, char type, address addr // returns the size of the instance of the given class u4 DumperSupport::instance_size(Klass* k) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); + InstanceKlass* ik = InstanceKlass::cast(k); u4 size = 0; - for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { + for (FieldStream fld(ik, false, false); !fld.eos(); fld.next()) { if (!fld.access_flags().is_static()) { Symbol* sig = fld.signature(); switch (sig->byte_at(0)) { @@ -847,18 +847,18 @@ u4 DumperSupport::instance_size(Klass* k) { // dumps static fields of the given class void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); + InstanceKlass* ik = InstanceKlass::cast(k); // pass 1 - count the static fields u2 field_count = 0; - for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { + for (FieldStream fldc(ik, true, true); !fldc.eos(); fldc.next()) { if (fldc.access_flags().is_static()) field_count++; } writer->write_u2(field_count); // pass 2 - dump the field descriptors and raw values - for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { + for (FieldStream fld(ik, true, true); !fld.eos(); fld.next()) { if (fld.access_flags().is_static()) { Symbol* sig = fld.signature(); @@ -867,7 +867,7 @@ void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { // value int offset = fld.offset(); - address addr = (address)ikh->java_mirror() + offset; + address addr = (address)ik->java_mirror() + offset; dump_field_value(writer, sig->byte_at(0), addr); } @@ -877,9 +877,9 @@ void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { // dump the raw values of the instance fields of the given object void DumperSupport::dump_instance_fields(DumpWriter* writer, oop o) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), o->klass()); + InstanceKlass* ik = InstanceKlass::cast(o->klass()); - for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { + for (FieldStream fld(ik, false, false); !fld.eos(); fld.next()) { if (!fld.access_flags().is_static()) { Symbol* sig = fld.signature(); address addr = (address)o + fld.offset(); @@ -892,18 +892,18 @@ void DumperSupport::dump_instance_fields(DumpWriter* writer, oop o) { // dumps the definition of the instance fields for a given class void DumperSupport::dump_instance_field_descriptors(DumpWriter* writer, Klass* k) { HandleMark hm; - instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); + InstanceKlass* ik = InstanceKlass::cast(k); // pass 1 - count the instance fields u2 field_count = 0; - for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { + for (FieldStream fldc(ik, true, true); !fldc.eos(); fldc.next()) { if (!fldc.access_flags().is_static()) field_count++; } writer->write_u2(field_count); // pass 2 - dump the field descriptors - for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { + for (FieldStream fld(ik, true, true); !fld.eos(); fld.next()) { if (!fld.access_flags().is_static()) { Symbol* sig = fld.signature(); diff --git a/hotspot/src/share/vm/services/lowMemoryDetector.cpp b/hotspot/src/share/vm/services/lowMemoryDetector.cpp index 33e1f45957b..15284b792de 100644 --- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp +++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -293,8 +293,7 @@ void SensorInfo::process_pending_requests(TRAPS) { void SensorInfo::trigger(int count, TRAPS) { assert(count <= _pending_trigger_count, "just checking"); if (_sensor_obj != NULL) { - Klass* k = Management::sun_management_Sensor_klass(CHECK); - instanceKlassHandle sensorKlass (THREAD, k); + InstanceKlass* sensorKlass = Management::sun_management_Sensor_klass(CHECK); Handle sensor_h(THREAD, _sensor_obj); Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK); @@ -337,8 +336,7 @@ void SensorInfo::clear(int count, TRAPS) { } if (_sensor_obj != NULL) { - Klass* k = Management::sun_management_Sensor_klass(CHECK); - instanceKlassHandle sensorKlass (THREAD, k); + InstanceKlass* sensorKlass = Management::sun_management_Sensor_klass(CHECK); Handle sensor(THREAD, _sensor_obj); JavaValue result(T_VOID); diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index e99d1ea7ab5..090c8e42771 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -62,16 +62,16 @@ PerfVariable* Management::_begin_vm_creation_time = NULL; PerfVariable* Management::_end_vm_creation_time = NULL; PerfVariable* Management::_vm_init_done_time = NULL; -Klass* Management::_diagnosticCommandImpl_klass = NULL; -Klass* Management::_garbageCollectorExtImpl_klass = NULL; -Klass* Management::_garbageCollectorMXBean_klass = NULL; -Klass* Management::_gcInfo_klass = NULL; -Klass* Management::_managementFactoryHelper_klass = NULL; -Klass* Management::_memoryManagerMXBean_klass = NULL; -Klass* Management::_memoryPoolMXBean_klass = NULL; -Klass* Management::_memoryUsage_klass = NULL; -Klass* Management::_sensor_klass = NULL; -Klass* Management::_threadInfo_klass = NULL; +InstanceKlass* Management::_diagnosticCommandImpl_klass = NULL; +InstanceKlass* Management::_garbageCollectorExtImpl_klass = NULL; +InstanceKlass* Management::_garbageCollectorMXBean_klass = NULL; +InstanceKlass* Management::_gcInfo_klass = NULL; +InstanceKlass* Management::_managementFactoryHelper_klass = NULL; +InstanceKlass* Management::_memoryManagerMXBean_klass = NULL; +InstanceKlass* Management::_memoryPoolMXBean_klass = NULL; +InstanceKlass* Management::_memoryUsage_klass = NULL; +InstanceKlass* Management::_sensor_klass = NULL; +InstanceKlass* Management::_threadInfo_klass = NULL; jmmOptionalSupport Management::_optional_support = {0}; TimeStamp Management::_stamp; @@ -156,11 +156,10 @@ void Management::initialize(TRAPS) { vm_exit_during_initialization("Management agent initialization failure: " "class jdk.internal.agent.Agent not found."); } - instanceKlassHandle ik (THREAD, k); JavaValue result(T_VOID); JavaCalls::call_static(&result, - ik, + k, vmSymbols::startAgent_name(), vmSymbols::void_method_signature(), CHECK); @@ -171,30 +170,28 @@ void Management::get_optional_support(jmmOptionalSupport* support) { memcpy(support, &_optional_support, sizeof(jmmOptionalSupport)); } -Klass* Management::load_and_initialize_klass(Symbol* sh, TRAPS) { +InstanceKlass* Management::load_and_initialize_klass(Symbol* sh, TRAPS) { Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); - Klass* ik = initialize_klass(k, CHECK_NULL); - return ik; + return initialize_klass(k, CHECK_NULL); } -Klass* Management::load_and_initialize_klass_or_null(Symbol* sh, TRAPS) { +InstanceKlass* Management::load_and_initialize_klass_or_null(Symbol* sh, TRAPS) { Klass* k = SystemDictionary::resolve_or_null(sh, CHECK_NULL); if (k == NULL) { return NULL; } - Klass* ik = initialize_klass(k, CHECK_NULL); - return ik; + return initialize_klass(k, CHECK_NULL); } -Klass* Management::initialize_klass(Klass* k, TRAPS) { - instanceKlassHandle ik (THREAD, k); +InstanceKlass* Management::initialize_klass(Klass* k, TRAPS) { + InstanceKlass* ik = InstanceKlass::cast(k); if (ik->should_be_initialized()) { ik->initialize(CHECK_NULL); } // If these classes change to not be owned by the boot loader, they need // to be walked to keep their class loader alive in oops_do. assert(ik->class_loader() == NULL, "need to follow in oops_do"); - return ik(); + return ik; } void Management::record_vm_startup_time(jlong begin, jlong duration) { @@ -218,56 +215,56 @@ void Management::oops_do(OopClosure* f) { ThreadService::oops_do(f); } -Klass* Management::java_lang_management_ThreadInfo_klass(TRAPS) { +InstanceKlass* Management::java_lang_management_ThreadInfo_klass(TRAPS) { if (_threadInfo_klass == NULL) { _threadInfo_klass = load_and_initialize_klass(vmSymbols::java_lang_management_ThreadInfo(), CHECK_NULL); } return _threadInfo_klass; } -Klass* Management::java_lang_management_MemoryUsage_klass(TRAPS) { +InstanceKlass* Management::java_lang_management_MemoryUsage_klass(TRAPS) { if (_memoryUsage_klass == NULL) { _memoryUsage_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryUsage(), CHECK_NULL); } return _memoryUsage_klass; } -Klass* Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) { +InstanceKlass* Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) { if (_memoryPoolMXBean_klass == NULL) { _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryPoolMXBean(), CHECK_NULL); } return _memoryPoolMXBean_klass; } -Klass* Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) { +InstanceKlass* Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) { if (_memoryManagerMXBean_klass == NULL) { _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryManagerMXBean(), CHECK_NULL); } return _memoryManagerMXBean_klass; } -Klass* Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) { +InstanceKlass* Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) { if (_garbageCollectorMXBean_klass == NULL) { _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL); } return _garbageCollectorMXBean_klass; } -Klass* Management::sun_management_Sensor_klass(TRAPS) { +InstanceKlass* Management::sun_management_Sensor_klass(TRAPS) { if (_sensor_klass == NULL) { _sensor_klass = load_and_initialize_klass(vmSymbols::sun_management_Sensor(), CHECK_NULL); } return _sensor_klass; } -Klass* Management::sun_management_ManagementFactoryHelper_klass(TRAPS) { +InstanceKlass* Management::sun_management_ManagementFactoryHelper_klass(TRAPS) { if (_managementFactoryHelper_klass == NULL) { _managementFactoryHelper_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactoryHelper(), CHECK_NULL); } return _managementFactoryHelper_klass; } -Klass* Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) { +InstanceKlass* Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) { if (_garbageCollectorExtImpl_klass == NULL) { _garbageCollectorExtImpl_klass = load_and_initialize_klass_or_null(vmSymbols::com_sun_management_internal_GarbageCollectorExtImpl(), CHECK_NULL); @@ -275,14 +272,14 @@ Klass* Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(TRA return _garbageCollectorExtImpl_klass; } -Klass* Management::com_sun_management_GcInfo_klass(TRAPS) { +InstanceKlass* Management::com_sun_management_GcInfo_klass(TRAPS) { if (_gcInfo_klass == NULL) { _gcInfo_klass = load_and_initialize_klass(vmSymbols::com_sun_management_GcInfo(), CHECK_NULL); } return _gcInfo_klass; } -Klass* Management::com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) { +InstanceKlass* Management::com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) { if (_diagnosticCommandImpl_klass == NULL) { _diagnosticCommandImpl_klass = load_and_initialize_klass(vmSymbols::com_sun_management_internal_DiagnosticCommandImpl(), CHECK_NULL); } @@ -333,8 +330,7 @@ static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, // Helper function to construct a ThreadInfo object instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) { - Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); - instanceKlassHandle ik (THREAD, k); + InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); JavaValue result(T_VOID); JavaCallArguments args(14); @@ -363,8 +359,7 @@ instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, typeArrayHandle depths_array, objArrayHandle synchronizers_array, TRAPS) { - Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); - instanceKlassHandle ik (THREAD, k); + InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); JavaValue result(T_VOID); JavaCallArguments args(17); @@ -401,7 +396,7 @@ static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) { oop mgr_obj = JNIHandles::resolve(mgr); instanceHandle h(THREAD, (instanceOop) mgr_obj); - Klass* k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL); + InstanceKlass* k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL); if (!h->is_a(k)) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "the object is not an instance of java.lang.management.GarbageCollectorMXBean class", @@ -507,9 +502,8 @@ JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj)) } // Allocate the resulting MemoryPoolMXBean[] object - Klass* k = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL); - instanceKlassHandle ik (THREAD, k); - objArrayOop r = oopFactory::new_objArray(ik(), num_memory_pools, CHECK_NULL); + InstanceKlass* ik = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(ik, num_memory_pools, CHECK_NULL); objArrayHandle poolArray(THREAD, r); if (mgr == NULL) { @@ -552,9 +546,8 @@ JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj)) } // Allocate the resulting MemoryManagerMXBean[] object - Klass* k = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL); - instanceKlassHandle ik (THREAD, k); - objArrayOop r = oopFactory::new_objArray(ik(), num_mgrs, CHECK_NULL); + InstanceKlass* ik = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(ik, num_mgrs, CHECK_NULL); objArrayHandle mgrArray(THREAD, r); if (pool == NULL) { @@ -629,7 +622,7 @@ JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType typ THROW(vmSymbols::java_lang_NullPointerException()); } - Klass* sensor_klass = Management::sun_management_Sensor_klass(CHECK); + InstanceKlass* sensor_klass = Management::sun_management_Sensor_klass(CHECK); oop s = JNIHandles::resolve(sensorObj); assert(s->is_instance(), "Sensor should be an instanceOop"); instanceHandle sensor_h(THREAD, (instanceOop) s); @@ -1202,9 +1195,8 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo int num_snapshots = dump_result.num_snapshots(); // create the result ThreadInfo[] object - Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); - instanceKlassHandle ik (THREAD, k); - objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL); + InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(ik, num_snapshots, CHECK_NULL); objArrayHandle result_h(THREAD, r); int index = 0; @@ -1303,15 +1295,15 @@ JVM_END JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env)) ResourceMark rm(THREAD); - LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter + LoadedClassesEnumerator lce; int num_classes = lce.num_loaded_classes(); objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); objArrayHandle classes_ah(THREAD, r); for (int i = 0; i < num_classes; i++) { - KlassHandle kh = lce.get_klass(i); - oop mirror = kh()->java_mirror(); + Klass* k = lce.get_klass(i); + oop mirror = k->java_mirror(); classes_ah->obj_at_put(i, mirror); } diff --git a/hotspot/src/share/vm/services/management.hpp b/hotspot/src/share/vm/services/management.hpp index ac7f872a29c..f1168166281 100644 --- a/hotspot/src/share/vm/services/management.hpp +++ b/hotspot/src/share/vm/services/management.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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,19 +42,19 @@ private: static TimeStamp _stamp; // Timestamp since vm init done time // Management klasses - static Klass* _diagnosticCommandImpl_klass; - static Klass* _garbageCollectorExtImpl_klass; - static Klass* _garbageCollectorMXBean_klass; - static Klass* _gcInfo_klass; - static Klass* _managementFactoryHelper_klass; - static Klass* _memoryManagerMXBean_klass; - static Klass* _memoryPoolMXBean_klass; - static Klass* _memoryUsage_klass; - static Klass* _sensor_klass; - static Klass* _threadInfo_klass; - static Klass* load_and_initialize_klass(Symbol* sh, TRAPS); - static Klass* load_and_initialize_klass_or_null(Symbol* sh, TRAPS); - static Klass* initialize_klass(Klass* k, TRAPS); + static InstanceKlass* _diagnosticCommandImpl_klass; + static InstanceKlass* _garbageCollectorExtImpl_klass; + static InstanceKlass* _garbageCollectorMXBean_klass; + static InstanceKlass* _gcInfo_klass; + static InstanceKlass* _managementFactoryHelper_klass; + static InstanceKlass* _memoryManagerMXBean_klass; + static InstanceKlass* _memoryPoolMXBean_klass; + static InstanceKlass* _memoryUsage_klass; + static InstanceKlass* _sensor_klass; + static InstanceKlass* _threadInfo_klass; + static InstanceKlass* load_and_initialize_klass(Symbol* sh, TRAPS); + static InstanceKlass* load_and_initialize_klass_or_null(Symbol* sh, TRAPS); + static InstanceKlass* initialize_klass(Klass* k, TRAPS); public: static void init(); @@ -67,7 +67,7 @@ public: static void* get_jmm_interface(int version); static void get_optional_support(jmmOptionalSupport* support); - static void get_loaded_classes(JavaThread* cur_thread, GrowableArray* klass_handle_array); + static void get_loaded_classes(JavaThread* cur_thread, GrowableArray* klass_array); static void record_vm_startup_time(jlong begin, jlong duration) NOT_MANAGEMENT_RETURN; @@ -87,21 +87,21 @@ public: } // methods to return a Klass*. - static Klass* java_lang_management_ThreadInfo_klass(TRAPS); - static Klass* java_lang_management_MemoryUsage_klass(TRAPS) + static InstanceKlass* java_lang_management_ThreadInfo_klass(TRAPS); + static InstanceKlass* java_lang_management_MemoryUsage_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); - static Klass* java_lang_management_MemoryPoolMXBean_klass(TRAPS); - static Klass* java_lang_management_MemoryManagerMXBean_klass(TRAPS); - static Klass* java_lang_management_GarbageCollectorMXBean_klass(TRAPS); - static Klass* sun_management_ManagementFactoryHelper_klass(TRAPS) + static InstanceKlass* java_lang_management_MemoryPoolMXBean_klass(TRAPS); + static InstanceKlass* java_lang_management_MemoryManagerMXBean_klass(TRAPS); + static InstanceKlass* java_lang_management_GarbageCollectorMXBean_klass(TRAPS); + static InstanceKlass* sun_management_ManagementFactoryHelper_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); - static Klass* sun_management_Sensor_klass(TRAPS) + static InstanceKlass* sun_management_Sensor_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); - static Klass* com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) + static InstanceKlass* com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); - static Klass* com_sun_management_GcInfo_klass(TRAPS) + static InstanceKlass* com_sun_management_GcInfo_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); - static Klass* com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) + static InstanceKlass* com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) NOT_MANAGEMENT_RETURN_(NULL); static instanceOop create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS); diff --git a/hotspot/src/share/vm/services/memoryManager.cpp b/hotspot/src/share/vm/services/memoryManager.cpp index d42ec61a8c9..8443f437034 100644 --- a/hotspot/src/share/vm/services/memoryManager.cpp +++ b/hotspot/src/share/vm/services/memoryManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -124,7 +124,7 @@ instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { signature = vmSymbols::createMemoryManager_signature(); } - instanceKlassHandle ik(THREAD, k); + InstanceKlass* ik = InstanceKlass::cast(k); JavaCalls::call_static(&result, ik, diff --git a/hotspot/src/share/vm/services/memoryPool.cpp b/hotspot/src/share/vm/services/memoryPool.cpp index 4f5dbdafd55..a29a27310cf 100644 --- a/hotspot/src/share/vm/services/memoryPool.cpp +++ b/hotspot/src/share/vm/services/memoryPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -86,8 +86,7 @@ instanceOop MemoryPool::get_memory_pool_instance(TRAPS) { if (pool_obj == NULL) { // It's ok for more than one thread to execute the code up to the locked region. // Extra pool instances will just be gc'ed. - Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK_NULL); - instanceKlassHandle ik(THREAD, k); + InstanceKlass* ik = Management::sun_management_ManagementFactoryHelper_klass(CHECK_NULL); Handle pool_name = java_lang_String::create_from_str(_name, CHECK_NULL); jlong usage_threshold_value = (_usage_threshold->is_high_threshold_supported() ? 0 : -1L); diff --git a/hotspot/src/share/vm/services/memoryService.cpp b/hotspot/src/share/vm/services/memoryService.cpp index d2666a2f08b..aed39e9451b 100644 --- a/hotspot/src/share/vm/services/memoryService.cpp +++ b/hotspot/src/share/vm/services/memoryService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -529,8 +529,7 @@ bool MemoryService::set_verbose(bool verbose) { } Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { - Klass* k = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); - instanceKlassHandle ik(THREAD, k); + InstanceKlass* ik = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); instanceHandle obj = ik->allocate_instance_handle(CHECK_NH); diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index 69b50bc13df..1100cb07971 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -607,12 +607,11 @@ bool ThreadStackTrace::is_owned_monitor_on_stack(oop object) { } Handle ThreadStackTrace::allocate_fill_stack_trace_element_array(TRAPS) { - Klass* k = SystemDictionary::StackTraceElement_klass(); - assert(k != NULL, "must be loaded in 1.4+"); - instanceKlassHandle ik(THREAD, k); + InstanceKlass* ik = SystemDictionary::StackTraceElement_klass(); + assert(ik != NULL, "must be loaded in 1.4+"); // Allocate an array of java/lang/StackTraceElement object - objArrayOop ste = oopFactory::new_objArray(ik(), _depth, CHECK_NH); + objArrayOop ste = oopFactory::new_objArray(ik, _depth, CHECK_NH); objArrayHandle backtrace(THREAD, ste); for (int j = 0; j < _depth; j++) { StackFrameInfo* frame = _frames->at(j); diff --git a/hotspot/src/share/vm/shark/sharkRuntime.cpp b/hotspot/src/share/vm/shark/sharkRuntime.cpp index fff58022612..15404a9ad2b 100644 --- a/hotspot/src/share/vm/shark/sharkRuntime.cpp +++ b/hotspot/src/share/vm/shark/sharkRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,16 +41,15 @@ JRT_ENTRY(int, SharkRuntime::find_exception_handler(JavaThread* thread, int* indexes, int num_indexes)) constantPoolHandle pool(thread, method(thread)->constants()); - KlassHandle exc_klass(thread, ((oop) tos_at(thread, 0))->klass()); + Klass* exc_klass = ((oop) tos_at(thread, 0))->klass(); for (int i = 0; i < num_indexes; i++) { Klass* tmp = pool->klass_at(indexes[i], CHECK_0); - KlassHandle chk_klass(thread, tmp); - if (exc_klass() == chk_klass()) + if (exc_klass() == tmp) return i; - if (exc_klass()->is_subtype_of(chk_klass())) + if (exc_klass()->is_subtype_of(tmp)) return i; } @@ -85,7 +84,7 @@ JRT_END JRT_ENTRY(void, SharkRuntime::new_instance(JavaThread* thread, int index)) Klass* k_oop = method(thread)->constants()->klass_at(index, CHECK); - instanceKlassHandle klass(THREAD, k_oop); + InstanceKlass* klass = InstanceKlass::cast(k); // Make sure we are not instantiating an abstract klass klass->check_valid_for_instantiation(true, CHECK); diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index ba34813b212..09938087b9e 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -265,11 +265,10 @@ Handle Exceptions::new_exception(Thread *thread, Symbol* name, Handle h_exception; // Resolve exception klass - Klass* ik = SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread); - instanceKlassHandle klass(thread, ik); + InstanceKlass* klass = InstanceKlass::cast(SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread)); if (!thread->has_pending_exception()) { - assert(klass.not_null(), "klass must exist"); + assert(klass != NULL, "klass must exist"); // We are about to create an instance - so make sure that klass is initialized klass->initialize(thread); if (!thread->has_pending_exception()) { diff --git a/hotspot/src/share/vm/utilities/xmlstream.cpp b/hotspot/src/share/vm/utilities/xmlstream.cpp index 829de94dd4d..b9f0756a36f 100644 --- a/hotspot/src/share/vm/utilities/xmlstream.cpp +++ b/hotspot/src/share/vm/utilities/xmlstream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -422,17 +422,17 @@ void xmlStream::method_text(methodHandle method) { // ------------------------------------------------------------------ // Output a klass attribute, in the form " klass='pkg/cls'". // This is used only when there is no ciKlass available. -void xmlStream::klass(KlassHandle klass) { +void xmlStream::klass(Klass* klass) { assert_if_no_error(inside_attrs(), "printing attributes"); - if (klass.is_null()) return; + if (klass == NULL) return; print_raw(" klass='"); klass_text(klass); print_raw("'"); } -void xmlStream::klass_text(KlassHandle klass) { +void xmlStream::klass_text(Klass* klass) { assert_if_no_error(inside_attrs(), "printing attributes"); - if (klass.is_null()) return; + if (klass == NULL) return; //klass->print_short_name(log->out()); klass->name()->print_symbol_on(out()); } diff --git a/hotspot/src/share/vm/utilities/xmlstream.hpp b/hotspot/src/share/vm/utilities/xmlstream.hpp index 22a12cacda3..3114dc53d3e 100644 --- a/hotspot/src/share/vm/utilities/xmlstream.hpp +++ b/hotspot/src/share/vm/utilities/xmlstream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -138,14 +138,14 @@ class xmlStream : public outputStream { // commonly used XML attributes void stamp(); // stamp='1.234' void method(methodHandle m); // method='k n s' ... - void klass(KlassHandle k); // klass='name' + void klass(Klass* k); // klass='name' void name(const Symbol* s); // name='name' void object(const char* attr, Metadata* val); void object(const char* attr, Handle val); // print the text alone (sans ''): void method_text(methodHandle m); - void klass_text(KlassHandle k); // klass='name' + void klass_text(Klass* k); // klass='name' void name_text(const Symbol* s); // name='name' void object_text(Metadata* x); void object_text(Handle x); From 6a9ca1701d25682ec274c586ace2033cbc536670 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 16 Mar 2017 09:05:20 +0100 Subject: [PATCH 59/86] 8155094: Add logging for long lasting methods found in JDK-8152948 Adds logging for DerivedPointerTable, TLAB preparation and resizing, and new collection set setup work Reviewed-by: kbarrett, sangheki --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 32 ++++++++++++------- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 2 ++ hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 12 +++++++ hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp | 23 +++++++++++++ hotspot/test/gc/g1/TestGCLogMessages.java | 6 ++++ 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 830d7ac8584..1bef3fb306c 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1378,10 +1378,9 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, } _verifier->check_bitmaps("Full GC End"); - // Start a new incremental collection set for the next pause - collection_set()->start_incremental_building(); - - clear_cset_fast_test(); + double start = os::elapsedTime(); + start_new_collection_set(); + g1_policy()->phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0); _allocator->init_mutator_alloc_region(); @@ -2694,9 +2693,12 @@ G1CollectedHeap* G1CollectedHeap::heap() { void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { // always_do_update_barrier = false; assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); + + double start = os::elapsedTime(); // Fill TLAB's and such accumulate_statistics_all_tlabs(); ensure_parsability(true); + g1_policy()->phase_times()->record_prepare_tlab_time_ms((os::elapsedTime() - start) * 1000.0); g1_rem_set()->print_periodic_summary_info("Before GC RS summary", total_collections()); } @@ -2713,7 +2715,10 @@ void G1CollectedHeap::gc_epilogue(bool full) { #endif // always_do_update_barrier = true; + double start = os::elapsedTime(); resize_all_tlabs(); + g1_policy()->phase_times()->record_resize_tlab_time_ms((os::elapsedTime() - start) * 1000.0); + allocation_context_stats().update(full); // We have just completed a GC. Update the soft reference @@ -2996,6 +3001,15 @@ public: } }; +void G1CollectedHeap::start_new_collection_set() { + collection_set()->start_incremental_building(); + + clear_cset_fast_test(); + + guarantee(_eden.length() == 0, "eden should have been cleared"); + g1_policy()->transfer_survivors_to_cset(survivor()); +} + bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { assert_at_safepoint(true /* should_be_vm_thread */); @@ -3198,13 +3212,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { _survivor_evac_stats.adjust_desired_plab_sz(); _old_evac_stats.adjust_desired_plab_sz(); - // Start a new incremental collection set for the next pause. - collection_set()->start_incremental_building(); - - clear_cset_fast_test(); - - guarantee(_eden.length() == 0, "eden should have been cleared"); - g1_policy()->transfer_survivors_to_cset(survivor()); + start_new_collection_set(); if (evacuation_failed()) { set_used(recalculate_used()); @@ -4522,7 +4530,9 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in redirty_logged_cards(); #if defined(COMPILER2) || INCLUDE_JVMCI + double start = os::elapsedTime(); DerivedPointerTable::update_pointers(); + g1_policy()->phase_times()->record_derived_pointer_table_update_time((os::elapsedTime() - start) * 1000.0); #endif g1_policy()->print_age_table(); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 9851dca97fb..e29d4e9745f 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -159,6 +159,8 @@ private: HeapRegionSet _humongous_set; void eagerly_reclaim_humongous_regions(); + // Start a new incremental collection set for the next pause. + void start_new_collection_set(); // The number of regions we could create by expansion. uint _expansion_regions; diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 647e22fdf2e..317eec6a02f 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -112,6 +112,9 @@ void G1GCPhaseTimes::reset() { _cur_evac_fail_restore_remsets = 0.0; _cur_evac_fail_remove_self_forwards = 0.0; _cur_string_dedup_fixup_time_ms = 0.0; + _cur_prepare_tlab_time_ms = 0.0; + _cur_resize_tlab_time_ms = 0.0; + _cur_derived_pointer_table_update_time_ms = 0.0; _cur_clear_ct_time_ms = 0.0; _cur_expand_heap_time_ms = 0.0; _cur_ref_proc_time_ms = 0.0; @@ -125,6 +128,7 @@ void G1GCPhaseTimes::reset() { _recorded_redirty_logged_cards_time_ms = 0.0; _recorded_preserve_cm_referents_time_ms = 0.0; _recorded_merge_pss_time_ms = 0.0; + _recorded_start_new_cset_time_ms = 0.0; _recorded_total_free_cset_time_ms = 0.0; _recorded_serial_free_cset_time_ms = 0.0; _cur_fast_reclaim_humongous_time_ms = 0.0; @@ -288,6 +292,7 @@ double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { if (_root_region_scan_wait_time_ms > 0.0) { debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); } + debug_time("Prepare TLABs", _cur_prepare_tlab_time_ms); debug_time("Choose Collection Set", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); if (G1EagerReclaimHumongousObjects) { debug_time("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); @@ -375,6 +380,9 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms); debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms); +#if defined(COMPILER2) || INCLUDE_JVMCI + debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms); +#endif if (_recorded_clear_claimed_marks_time_ms > 0.0) { debug_time("Clear Claimed Marks", _recorded_clear_claimed_marks_time_ms); } @@ -390,6 +398,10 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { debug_time("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); trace_count("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); } + debug_time("Start New Collection Set", _recorded_start_new_cset_time_ms); + if (UseTLAB && ResizeTLAB) { + debug_time("Resize TLABs", _cur_resize_tlab_time_ms); + } debug_time("Expand Heap After Collection", _cur_expand_heap_time_ms); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index 5889951f2f7..e6b5d4cb567 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -97,6 +97,11 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_string_dedup_fixup_time_ms; + double _cur_prepare_tlab_time_ms; + double _cur_resize_tlab_time_ms; + + double _cur_derived_pointer_table_update_time_ms; + double _cur_clear_ct_time_ms; double _cur_expand_heap_time_ms; double _cur_ref_proc_time_ms; @@ -118,6 +123,8 @@ class G1GCPhaseTimes : public CHeapObj { double _recorded_merge_pss_time_ms; + double _recorded_start_new_cset_time_ms; + double _recorded_total_free_cset_time_ms; double _recorded_serial_free_cset_time_ms; @@ -172,6 +179,18 @@ class G1GCPhaseTimes : public CHeapObj { public: + void record_prepare_tlab_time_ms(double ms) { + _cur_prepare_tlab_time_ms = ms; + } + + void record_resize_tlab_time_ms(double ms) { + _cur_resize_tlab_time_ms = ms; + } + + void record_derived_pointer_table_update_time(double ms) { + _cur_derived_pointer_table_update_time_ms = ms; + } + void record_clear_ct_time(double ms) { _cur_clear_ct_time_ms = ms; } @@ -259,6 +278,10 @@ class G1GCPhaseTimes : public CHeapObj { _recorded_merge_pss_time_ms = time_ms; } + void record_start_new_cset_time_ms(double time_ms) { + _recorded_start_new_cset_time_ms = time_ms; + } + void record_cur_collection_start_sec(double time_ms) { _cur_collection_start_sec = time_ms; } diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 49d9d9f5d1a..87ad667db3d 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -115,6 +115,12 @@ public class TestGCLogMessages { new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), // Merge PSS new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG), + // TLAB handling + new LogMessageWithLevel("Prepare TLABs", Level.DEBUG), + new LogMessageWithLevel("Resize TLABs", Level.DEBUG), + + new LogMessageWithLevel("DerivedPointerTable Update", Level.DEBUG), + new LogMessageWithLevel("Start New Collection Set", Level.DEBUG), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { From 8838ae7b46ddf7da62cd84a57c9e93d573c0cfab Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 14 Dec 2016 09:14:16 +0100 Subject: [PATCH 60/86] 8170933: Cleanup Metaspace Chunk manager: Unify treatment of humongous and non-humongous chunks Reviewed-by: mgerdin, coleenp --- hotspot/src/share/vm/memory/metaspace.cpp | 509 ++++++++++++++---- .../test/native/memory/test_chunkManager.cpp | 22 +- 2 files changed, 423 insertions(+), 108 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index fd88b6da9be..fde199b1e66 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -74,6 +74,22 @@ enum ChunkIndex { NumberOfInUseLists = 4 }; +// Helper, returns a descriptive name for the given index. +static const char* chunk_size_name(ChunkIndex index) { + switch (index) { + case SpecializedIndex: + return "specialized"; + case SmallIndex: + return "small"; + case MediumIndex: + return "medium"; + case HumongousIndex: + return "humongous"; + default: + return "Invalid index"; + } +} + enum ChunkSizes { // in words. ClassSpecializedChunk = 128, SpecializedChunk = 128, @@ -102,20 +118,32 @@ class ChunkManager : public CHeapObj { // SpecializedChunk // SmallChunk // MediumChunk - // HumongousChunk ChunkList _free_chunks[NumberOfFreeLists]; + // Return non-humongous chunk list by its index. + ChunkList* free_chunks(ChunkIndex index); + + // Returns non-humongous chunk list for the given chunk word size. + ChunkList* find_free_chunks_list(size_t word_size); + // HumongousChunk ChunkTreeDictionary _humongous_dictionary; + // Returns the humongous chunk dictionary. + ChunkTreeDictionary* humongous_dictionary() { + return &_humongous_dictionary; + } + // ChunkManager in all lists of this type size_t _free_chunks_total; size_t _free_chunks_count; void dec_free_chunks_total(size_t v) { - assert(_free_chunks_count > 0 && - _free_chunks_total > 0, - "About to go negative"); + assert(_free_chunks_count > 0, + "ChunkManager::_free_chunks_count: about to go negative (" SIZE_FORMAT ").", _free_chunks_count); + assert(_free_chunks_total >= v, + "ChunkManager::_free_chunks_total: about to go negative" + "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, v); Atomic::add_ptr(-1, &_free_chunks_count); jlong minus_v = (jlong) - (jlong) v; Atomic::add_ptr(minus_v, &_free_chunks_total); @@ -156,13 +184,20 @@ class ChunkManager : public CHeapObj { // for special, small, medium, and humongous chunks. ChunkIndex list_index(size_t size); - // Remove the chunk from its freelist. It is - // expected to be on one of the _free_chunks[] lists. + // Map a given index to the chunk size. + size_t size_by_index(ChunkIndex index); + + // Take a chunk from the ChunkManager. The chunk is expected to be in + // the chunk manager (the freelist if non-humongous, the dictionary if + // humongous). void remove_chunk(Metachunk* chunk); + // Return a single chunk of type index to the ChunkManager. + void return_single_chunk(ChunkIndex index, Metachunk* chunk); + // Add the simple linked list of chunks to the freelist of chunks // of type index. - void return_chunks(ChunkIndex index, Metachunk* chunks); + void return_chunk_list(ChunkIndex index, Metachunk* chunk); // Total of the space in the free chunks list size_t free_chunks_total_words(); @@ -175,14 +210,6 @@ class ChunkManager : public CHeapObj { Atomic::add_ptr(count, &_free_chunks_count); Atomic::add_ptr(v, &_free_chunks_total); } - ChunkTreeDictionary* humongous_dictionary() { - return &_humongous_dictionary; - } - - ChunkList* free_chunks(ChunkIndex index); - - // Returns the list for the given chunk word size. - ChunkList* find_free_chunks_list(size_t word_size); // Remove from a list by size. Selects list based on size of chunk. Metachunk* free_chunks_get(size_t chunk_word_size); @@ -735,8 +762,6 @@ class SpaceManager : public CHeapObj { Mutex* lock() const { return _lock; } - const char* chunk_size_name(ChunkIndex index) const; - protected: void initialize(); @@ -1246,13 +1271,13 @@ void VirtualSpaceNode::retire(ChunkManager* chunk_manager) { DEBUG_ONLY(verify_container_count();) for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) { ChunkIndex index = (ChunkIndex)i; - size_t chunk_size = chunk_manager->free_chunks(index)->size(); + size_t chunk_size = chunk_manager->size_by_index(index); while (free_words_in_vs() >= chunk_size) { Metachunk* chunk = get_chunk_vs(chunk_size); assert(chunk != NULL, "allocation should have been successful"); - chunk_manager->return_chunks(index, chunk); + chunk_manager->return_single_chunk(index, chunk); chunk_manager->inc_free_chunks_total(chunk_size); } DEBUG_ONLY(verify_container_count();) @@ -1743,6 +1768,28 @@ size_t ChunkManager::free_chunks_count() { return _free_chunks_count; } +ChunkIndex ChunkManager::list_index(size_t size) { + if (size_by_index(SpecializedIndex) == size) { + return SpecializedIndex; + } + if (size_by_index(SmallIndex) == size) { + return SmallIndex; + } + const size_t med_size = size_by_index(MediumIndex); + if (med_size == size) { + return MediumIndex; + } + + assert(size > med_size, "Not a humongous chunk"); + return HumongousIndex; +} + +size_t ChunkManager::size_by_index(ChunkIndex index) { + index_bounds_check(index); + assert(index != HumongousIndex, "Do not call for humongous chunks."); + return free_chunks(index)->size(); +} + void ChunkManager::locked_verify_free_chunks_total() { assert_lock_strong(SpaceManager::expand_lock()); assert(sum_free_chunks() == _free_chunks_total, @@ -1923,6 +1970,73 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { return chunk; } +void ChunkManager::return_single_chunk(ChunkIndex index, Metachunk* chunk) { + assert_lock_strong(SpaceManager::expand_lock()); + assert(chunk != NULL, "Expected chunk."); + assert(chunk->container() != NULL, "Container should have been set."); + assert(chunk->is_tagged_free() == false, "Chunk should be in use."); + index_bounds_check(index); + + // Note: mangle *before* returning the chunk to the freelist or dictionary. It does not + // matter for the freelist (non-humongous chunks), but the humongous chunk dictionary + // keeps tree node pointers in the chunk payload area which mangle will overwrite. + NOT_PRODUCT(chunk->mangle(badMetaWordVal);) + + if (index != HumongousIndex) { + // Return non-humongous chunk to freelist. + ChunkList* list = free_chunks(index); + assert(list->size() == chunk->word_size(), "Wrong chunk type."); + list->return_chunk_at_head(chunk); + log_trace(gc, metaspace, freelist)("returned one %s chunk at " PTR_FORMAT " to freelist.", + chunk_size_name(index), p2i(chunk)); + } else { + // Return humongous chunk to dictionary. + assert(chunk->word_size() > free_chunks(MediumIndex)->size(), "Wrong chunk type."); + assert(chunk->word_size() % free_chunks(SpecializedIndex)->size() == 0, + "Humongous chunk has wrong alignment."); + _humongous_dictionary.return_chunk(chunk); + log_trace(gc, metaspace, freelist)("returned one %s chunk at " PTR_FORMAT " (word size " SIZE_FORMAT ") to freelist.", + chunk_size_name(index), p2i(chunk), chunk->word_size()); + } + chunk->container()->dec_container_count(); + DEBUG_ONLY(chunk->set_is_tagged_free(true);) + +} + +void ChunkManager::return_chunk_list(ChunkIndex index, Metachunk* chunks) { + index_bounds_check(index); + if (chunks == NULL) { + return; + } + LogTarget(Trace, gc, metaspace, freelist) log; + if (log.is_enabled()) { // tracing + log.print("returning list of %s chunks...", chunk_size_name(index)); + } + unsigned num_chunks_returned = 0; + size_t size_chunks_returned = 0; + Metachunk* cur = chunks; + while (cur != NULL) { + // Capture the next link before it is changed + // by the call to return_chunk_at_head(); + Metachunk* next = cur->next(); + if (log.is_enabled()) { // tracing + num_chunks_returned ++; + size_chunks_returned += cur->word_size(); + } + return_single_chunk(index, cur); + cur = next; + } + if (log.is_enabled()) { // tracing + log.print("returned %u %s chunks to freelist, total word size " SIZE_FORMAT ".", + num_chunks_returned, chunk_size_name(index), size_chunks_returned); + if (index != HumongousIndex) { + log.print("updated freelist count: " SIZE_FORMAT ".", free_chunks(index)->size()); + } else { + log.print("updated dictionary count " SIZE_FORMAT ".", _humongous_dictionary.total_count()); + } + } +} + void ChunkManager::print_on(outputStream* out) const { const_cast(this)->humongous_dictionary()->report_statistics(out); } @@ -2256,32 +2370,6 @@ void SpaceManager::initialize() { log_trace(gc, metaspace, freelist)("SpaceManager(): " PTR_FORMAT, p2i(this)); } -void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) { - if (chunks == NULL) { - return; - } - ChunkList* list = free_chunks(index); - assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes"); - assert_lock_strong(SpaceManager::expand_lock()); - Metachunk* cur = chunks; - - // This returns chunks one at a time. If a new - // class List can be created that is a base class - // of FreeList then something like FreeList::prepend() - // can be used in place of this loop - while (cur != NULL) { - assert(cur->container() != NULL, "Container should have been set"); - cur->container()->dec_container_count(); - // Capture the next link before it is changed - // by the call to return_chunk_at_head(); - Metachunk* next = cur->next(); - DEBUG_ONLY(cur->set_is_tagged_free(true);) - NOT_PRODUCT(cur->mangle(badMetaWordVal);) - list->return_chunk_at_head(cur); - cur = next; - } -} - SpaceManager::~SpaceManager() { // This call this->_lock which can't be done while holding expand_lock() assert(sum_capacity_in_chunks_in_use() == allocated_chunks_words(), @@ -2317,42 +2405,12 @@ SpaceManager::~SpaceManager() { // Follow each list of chunks-in-use and add them to the // free lists. Each list is NULL terminated. - for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) { - log.trace("returned " SIZE_FORMAT " %s chunks to freelist", sum_count_in_chunks_in_use(i), chunk_size_name(i)); + for (ChunkIndex i = ZeroIndex; i <= HumongousIndex; i = next_chunk_index(i)) { Metachunk* chunks = chunks_in_use(i); - chunk_manager()->return_chunks(i, chunks); + chunk_manager()->return_chunk_list(i, chunks); set_chunks_in_use(i, NULL); - log.trace("updated freelist count " SSIZE_FORMAT " %s", chunk_manager()->free_chunks(i)->count(), chunk_size_name(i)); - assert(i != HumongousIndex, "Humongous chunks are handled explicitly later"); } - // The medium chunk case may be optimized by passing the head and - // tail of the medium chunk list to add_at_head(). The tail is often - // the current chunk but there are probably exceptions. - - // Humongous chunks - log.trace("returned " SIZE_FORMAT " %s humongous chunks to dictionary", - sum_count_in_chunks_in_use(HumongousIndex), chunk_size_name(HumongousIndex)); - log.trace("Humongous chunk dictionary: "); - // Humongous chunks are never the current chunk. - Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); - - while (humongous_chunks != NULL) { - DEBUG_ONLY(humongous_chunks->set_is_tagged_free(true);) - NOT_PRODUCT(humongous_chunks->mangle(badMetaWordVal);) - log.trace(PTR_FORMAT " (" SIZE_FORMAT ") ", p2i(humongous_chunks), humongous_chunks->word_size()); - assert(humongous_chunks->word_size() == (size_t) - align_size_up(humongous_chunks->word_size(), - smallest_chunk_size()), - "Humongous chunk size is wrong: word size " SIZE_FORMAT - " granularity " SIZE_FORMAT, - humongous_chunks->word_size(), smallest_chunk_size()); - Metachunk* next_humongous_chunks = humongous_chunks->next(); - humongous_chunks->container()->dec_container_count(); - chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks); - humongous_chunks = next_humongous_chunks; - } - log.trace("updated dictionary count " SIZE_FORMAT " %s", chunk_manager()->humongous_dictionary()->total_count(), chunk_size_name(HumongousIndex)); chunk_manager()->slow_locked_verify(); if (_block_freelists != NULL) { @@ -2360,36 +2418,6 @@ SpaceManager::~SpaceManager() { } } -const char* SpaceManager::chunk_size_name(ChunkIndex index) const { - switch (index) { - case SpecializedIndex: - return "Specialized"; - case SmallIndex: - return "Small"; - case MediumIndex: - return "Medium"; - case HumongousIndex: - return "Humongous"; - default: - return NULL; - } -} - -ChunkIndex ChunkManager::list_index(size_t size) { - if (free_chunks(SpecializedIndex)->size() == size) { - return SpecializedIndex; - } - if (free_chunks(SmallIndex)->size() == size) { - return SmallIndex; - } - if (free_chunks(MediumIndex)->size() == size) { - return MediumIndex; - } - - assert(size > free_chunks(MediumIndex)->size(), "Not a humongous chunk"); - return HumongousIndex; -} - void SpaceManager::deallocate(MetaWord* p, size_t word_size) { assert_lock_strong(_lock); // Allocations and deallocations are in raw_word_size @@ -4073,6 +4101,273 @@ void ChunkManager_test_list_index() { } } +// ChunkManagerReturnTest stresses taking/returning chunks from the ChunkManager. It takes and +// returns chunks from/to the ChunkManager while keeping track of the expected ChunkManager +// content. +class ChunkManagerReturnTestImpl { + + VirtualSpaceNode _vsn; + ChunkManager _cm; + + // The expected content of the chunk manager. + unsigned _chunks_in_chunkmanager; + size_t _words_in_chunkmanager; + + // A fixed size pool of chunks. Chunks may be in the chunk manager (free) or not (in use). + static const int num_chunks = 256; + Metachunk* _pool[num_chunks]; + + // Helper, return a random position into the chunk pool. + static int get_random_position() { + return os::random() % num_chunks; + } + + // Asserts that ChunkManager counters match expectations. + void assert_counters() { + assert(_vsn.container_count() == num_chunks - _chunks_in_chunkmanager, "vsn counter mismatch."); + assert(_cm.free_chunks_count() == _chunks_in_chunkmanager, "cm counter mismatch."); + assert(_cm.free_chunks_total_words() == _words_in_chunkmanager, "cm counter mismatch."); + } + + // Get a random chunk size. Equal chance to get spec/med/small chunk size or + // a humongous chunk size. The latter itself is random in the range of [med+spec..4*med). + size_t get_random_chunk_size() { + const size_t sizes [] = { SpecializedChunk, SmallChunk, MediumChunk }; + const int rand = os::random() % 4; + if (rand < 3) { + return sizes[rand]; + } else { + // Note: this affects the max. size of space (see _vsn initialization in ctor). + return align_size_up(MediumChunk + 1 + (os::random() % (MediumChunk * 4)), SpecializedChunk); + } + } + + // Starting at pool index +1, find the next chunk tagged as either free or in use, depending + // on . Search wraps. Returns its position, or -1 if no matching chunk was found. + int next_matching_chunk(int start, bool is_free) const { + assert(start >= 0 && start < num_chunks, "invalid parameter"); + int pos = start; + do { + if (++pos == num_chunks) { + pos = 0; + } + if (_pool[pos]->is_tagged_free() == is_free) { + return pos; + } + } while (pos != start); + return -1; + } + + // A structure to keep information about a chunk list including which + // chunks are part of this list. This is needed to keep information about a chunk list + // we will to return to the ChunkManager, because the original list will be destroyed. + struct AChunkList { + Metachunk* head; + Metachunk* all[num_chunks]; + size_t size; + int num; + ChunkIndex index; + }; + + // Assemble, from the in-use chunks (not in the chunk manager) in the pool, + // a random chunk list of max. length of chunks with the same + // ChunkIndex (chunk size). + // Returns false if list cannot be assembled. List is returned in the + // structure. Returned list may be smaller than . + bool assemble_random_chunklist(AChunkList* out, int list_size) { + // Choose a random in-use chunk from the pool... + const int headpos = next_matching_chunk(get_random_position(), false); + if (headpos == -1) { + return false; + } + Metachunk* const head = _pool[headpos]; + out->all[0] = head; + assert(head->is_tagged_free() == false, "Chunk state mismatch"); + // ..then go from there, chain it up with up to list_size - 1 number of other + // in-use chunks of the same index. + const ChunkIndex index = _cm.list_index(head->word_size()); + int num_added = 1; + size_t size_added = head->word_size(); + int pos = headpos; + Metachunk* tail = head; + do { + pos = next_matching_chunk(pos, false); + if (pos != headpos) { + Metachunk* c = _pool[pos]; + assert(c->is_tagged_free() == false, "Chunk state mismatch"); + if (index == _cm.list_index(c->word_size())) { + tail->set_next(c); + c->set_prev(tail); + tail = c; + out->all[num_added] = c; + num_added ++; + size_added += c->word_size(); + } + } + } while (num_added < list_size && pos != headpos); + out->head = head; + out->index = index; + out->size = size_added; + out->num = num_added; + return true; + } + + // Take a single random chunk from the ChunkManager. + bool take_single_random_chunk_from_chunkmanager() { + assert_counters(); + _cm.locked_verify(); + int pos = next_matching_chunk(get_random_position(), true); + if (pos == -1) { + return false; + } + Metachunk* c = _pool[pos]; + assert(c->is_tagged_free(), "Chunk state mismatch"); + // Note: instead of using ChunkManager::remove_chunk on this one chunk, we call + // ChunkManager::free_chunks_get() with this chunk's word size. We really want + // to exercise ChunkManager::free_chunks_get() because that one gets called for + // normal chunk allocation. + Metachunk* c2 = _cm.free_chunks_get(c->word_size()); + assert(c2 != NULL, "Unexpected."); + assert(!c2->is_tagged_free(), "Chunk state mismatch"); + assert(c2->next() == NULL && c2->prev() == NULL, "Chunk should be outside of a list."); + _chunks_in_chunkmanager --; + _words_in_chunkmanager -= c->word_size(); + assert_counters(); + _cm.locked_verify(); + return true; + } + + // Returns a single random chunk to the chunk manager. Returns false if that + // was not possible (all chunks are already in the chunk manager). + bool return_single_random_chunk_to_chunkmanager() { + assert_counters(); + _cm.locked_verify(); + int pos = next_matching_chunk(get_random_position(), false); + if (pos == -1) { + return false; + } + Metachunk* c = _pool[pos]; + assert(c->is_tagged_free() == false, "wrong chunk information"); + _cm.return_single_chunk(_cm.list_index(c->word_size()), c); + _chunks_in_chunkmanager ++; + _words_in_chunkmanager += c->word_size(); + // (Note: until 8170520 is fixed, internal ChunkManager counters have to be updated + // by the caller - but only when returning chunks, ChunkManager->remove_chunk() + // already updates the counter.) + _cm.inc_free_chunks_total(c->word_size(), 1); + assert(c->is_tagged_free() == true, "wrong chunk information"); + assert_counters(); + _cm.locked_verify(); + return true; + } + + // Return a random chunk list to the chunk manager. Returns the length of the + // returned list. + int return_random_chunk_list_to_chunkmanager(int list_size) { + assert_counters(); + _cm.locked_verify(); + AChunkList aChunkList; + if (!assemble_random_chunklist(&aChunkList, list_size)) { + return 0; + } + // Before returning chunks are returned, they should be tagged in use. + for (int i = 0; i < aChunkList.num; i ++) { + assert(!aChunkList.all[i]->is_tagged_free(), "chunk state mismatch."); + } + _cm.return_chunk_list(aChunkList.index, aChunkList.head); + _chunks_in_chunkmanager += aChunkList.num; + _words_in_chunkmanager += aChunkList.size; + // (Note: until 8170520 is fixed, internal ChunkManager counters have to be updated + // by the caller - but only when returning chunks, ChunkManager->remove_chunk() + // already updates the counter.) + _cm.inc_free_chunks_total(aChunkList.size, aChunkList.num); + // After all chunks are returned, check that they are now tagged free. + for (int i = 0; i < aChunkList.num; i ++) { + assert(aChunkList.all[i]->is_tagged_free(), "chunk state mismatch."); + } + assert_counters(); + _cm.locked_verify(); + return aChunkList.num; + } + +public: + + ChunkManagerReturnTestImpl() + : _vsn(align_size_up(MediumChunk * num_chunks * 5 * sizeof(MetaWord), Metaspace::reserve_alignment())) + , _cm(SpecializedChunk, SmallChunk, MediumChunk) + , _chunks_in_chunkmanager(0) + , _words_in_chunkmanager(0) + { + MutexLockerEx ml(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); + // Allocate virtual space and allocate random chunks. Keep these chunks in the _pool. These chunks are + // "in use", because not yet added to any chunk manager. + _vsn.initialize(); + _vsn.expand_by(_vsn.reserved_words(), _vsn.reserved_words()); + for (int i = 0; i < num_chunks; i ++) { + const size_t size = get_random_chunk_size(); + _pool[i] = _vsn.get_chunk_vs(size); + assert(_pool[i] != NULL, "allocation failed"); + } + assert_counters(); + _cm.locked_verify(); + } + + // Test entry point. + // Return some chunks to the chunk manager (return phase). Take some chunks out (take phase). Repeat. + // Chunks are choosen randomly. Number of chunks to return or taken are choosen randomly, but affected + // by the argument: a factor of 0.0 will cause the test to quickly alternate between + // returning and taking, whereas a factor of 1.0 will take/return all chunks from/to the + // chunks manager, thereby emptying or filling it completely. + void do_test(float phase_length_factor) { + MutexLockerEx ml(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); + assert_counters(); + // Execute n operations, and operation being the move of a single chunk to/from the chunk manager. + const int num_max_ops = num_chunks * 100; + int num_ops = num_max_ops; + const int average_phase_length = (int)(phase_length_factor * num_chunks); + int num_ops_until_switch = MAX2(1, (int)(average_phase_length + os::random() % 8 - 4)); + bool return_phase = true; + while (num_ops > 0) { + int chunks_moved = 0; + if (return_phase) { + // Randomly switch between returning a single chunk or a random length chunk list. + if (os::random() % 2 == 0) { + if (return_single_random_chunk_to_chunkmanager()) { + chunks_moved = 1; + } + } else { + const int list_length = MAX2(1, (int)(os::random() % num_ops_until_switch)); + chunks_moved = return_random_chunk_list_to_chunkmanager(list_length); + } + } else { + // Breath out. + if (take_single_random_chunk_from_chunkmanager()) { + chunks_moved = 1; + } + } + num_ops -= chunks_moved; + num_ops_until_switch -= chunks_moved; + if (chunks_moved == 0 || num_ops_until_switch <= 0) { + return_phase = !return_phase; + num_ops_until_switch = MAX2(1, (int)(average_phase_length + os::random() % 8 - 4)); + } + } + } +}; + +void* setup_chunkmanager_returntests() { + ChunkManagerReturnTestImpl* p = new ChunkManagerReturnTestImpl(); + return p; +} + +void teardown_chunkmanager_returntests(void* p) { + delete (ChunkManagerReturnTestImpl*) p; +} + +void run_chunkmanager_returntests(void* p, float phase_length) { + ChunkManagerReturnTestImpl* test = (ChunkManagerReturnTestImpl*) p; + test->do_test(phase_length); +} // The following test is placed here instead of a gtest / unittest file // because the ChunkManager class is only available in this file. diff --git a/hotspot/test/native/memory/test_chunkManager.cpp b/hotspot/test/native/memory/test_chunkManager.cpp index 6aa5b5e392b..77a8341b89b 100644 --- a/hotspot/test/native/memory/test_chunkManager.cpp +++ b/hotspot/test/native/memory/test_chunkManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,26 @@ TEST(ChunkManager, list_index) { // The ChunkManager is only available in metaspace.cpp, // so the test code is located in that file. ChunkManager_test_list_index(); + } +extern void* setup_chunkmanager_returntests(); +extern void teardown_chunkmanager_returntests(void*); +extern void run_chunkmanager_returntests(void* p, float phase_length_factor); + +class ChunkManagerReturnTest : public ::testing::Test { +protected: + void* _test; + virtual void SetUp() { + _test = setup_chunkmanager_returntests(); + } + virtual void TearDown() { + teardown_chunkmanager_returntests(_test); + } +}; + +TEST_VM_F(ChunkManagerReturnTest, test00) { run_chunkmanager_returntests(_test, 0.0f); } +TEST_VM_F(ChunkManagerReturnTest, test05) { run_chunkmanager_returntests(_test, 0.5f); } +TEST_VM_F(ChunkManagerReturnTest, test10) { run_chunkmanager_returntests(_test, 1.0f); } + #endif // ASSERT From 6ed6fd7a3f9bef4e6bc991807e927a22923b1f4f Mon Sep 17 00:00:00 2001 From: Shafi Ahmad Date: Tue, 14 Mar 2017 22:14:33 -0700 Subject: [PATCH 61/86] 8167425: Redundant code in method PerfLongVariant::sample Reviewed-by: dholmes, coleenp, sspitsyn --- hotspot/src/share/vm/runtime/perfData.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/hotspot/src/share/vm/runtime/perfData.cpp b/hotspot/src/share/vm/runtime/perfData.cpp index 959bc7dd99b..545a66d4078 100644 --- a/hotspot/src/share/vm/runtime/perfData.cpp +++ b/hotspot/src/share/vm/runtime/perfData.cpp @@ -213,18 +213,9 @@ PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, } void PerfLongVariant::sample() { - - // JJJ - This should not happen. Maybe the first sample is taken - // while the _sample_helper is being null'ed out. - // assert(_sample_helper != NULL || _sampled != NULL, "unexpected state"); - if (_sample_helper == NULL) return; - if (_sample_helper != NULL) { *(jlong*)_valuep = _sample_helper->take_sample(); } - else if (_sampled != NULL) { - *(jlong*)_valuep = *_sampled; - } } PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u, From 6aa1dfbcf43684565938f8b6ac3af37256b1f2c8 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Fri, 17 Mar 2017 08:19:05 -0700 Subject: [PATCH 62/86] 8176831: Dead code: function jmm_GetLoadedClasses is not used in jmm_interface Remove the dead code Reviewed-by: dholmes, coleenp --- .../share/vm/services/classLoadingService.cpp | 22 ----------------- .../share/vm/services/classLoadingService.hpp | 24 ------------------- hotspot/src/share/vm/services/management.cpp | 19 --------------- 3 files changed, 65 deletions(-) diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 49c45ca0cd1..dd9e9c72217 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -197,26 +197,4 @@ void ClassLoadingService::reset_trace_class_unloading() { LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload)); } -GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; - -LoadedClassesEnumerator::LoadedClassesEnumerator() { - - int init_size = ClassLoadingService::loaded_class_count(); - _klass_array = new GrowableArray(init_size); - - // For consistency of the loaded classes, grab the SystemDictionary lock - MutexLocker sd_mutex(SystemDictionary_lock); - - // Set _loaded_classes and begin enumerating all classes. - // Only one thread will do the enumeration at a time. - // These static variables are needed and they are used by the static method - // add_loaded_class called from classes_do(). - _loaded_classes = _klass_array; - - SystemDictionary::classes_do(&add_loaded_class); - - // FIXME: Exclude array klasses for now - // Universe::basic_type_classes_do(&add_loaded_class); -} - #endif // INCLUDE_MANAGEMENT diff --git a/hotspot/src/share/vm/services/classLoadingService.hpp b/hotspot/src/share/vm/services/classLoadingService.hpp index 65d573b626a..5786e59ec01 100644 --- a/hotspot/src/share/vm/services/classLoadingService.hpp +++ b/hotspot/src/share/vm/services/classLoadingService.hpp @@ -117,28 +117,4 @@ public: } }; -// FIXME: make this piece of code to be shared by M&M and JVMTI -class LoadedClassesEnumerator : public StackObj { -private: - static GrowableArray* _loaded_classes; - GrowableArray* _klass_array; - -public: - LoadedClassesEnumerator(); - - int num_loaded_classes() { return _klass_array->length(); } - Klass* get_klass(int index) { return _klass_array->at(index); } - - static void add_loaded_class(Klass* k) { - // FIXME: For now - don't include array klasses - // The spec is unclear at this point to count array klasses or not - // and also indirect creation of array of super class and secondaries - // - // for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - // _loaded_classes->append(l); - // } - _loaded_classes->append(k); - } -}; - #endif // SHARE_VM_SERVICES_CLASSLOADINGSERVICE_HPP diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index 090c8e42771..44f862c1cf6 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -1291,25 +1291,6 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo return (jobjectArray) JNIHandles::make_local(env, result_h()); JVM_END -// Returns an array of Class objects. -JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env)) - ResourceMark rm(THREAD); - - LoadedClassesEnumerator lce; - - int num_classes = lce.num_loaded_classes(); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); - objArrayHandle classes_ah(THREAD, r); - - for (int i = 0; i < num_classes; i++) { - Klass* k = lce.get_klass(i); - oop mirror = k->java_mirror(); - classes_ah->obj_at_put(i, mirror); - } - - return (jobjectArray) JNIHandles::make_local(env, classes_ah()); -JVM_END - // Reset statistic. Return true if the requested statistic is reset. // Otherwise, return false. // From cee7beace22fb760c6d929ffb4d59a8bac8efb5f Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sun, 19 Mar 2017 16:40:09 -0400 Subject: [PATCH 63/86] 8175817: Clean up Solaris signal code: SIGUSR2, SIGasync, SIGJVM1/2 Reviewed-by: rehn, stuefe, dsamersoff --- hotspot/src/os/solaris/vm/jvm_solaris.h | 4 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 77 +++---------------- hotspot/src/os/solaris/vm/os_solaris.hpp | 6 +- .../solaris_sparc/vm/os_solaris_sparc.cpp | 6 +- .../os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 6 +- 5 files changed, 20 insertions(+), 79 deletions(-) diff --git a/hotspot/src/os/solaris/vm/jvm_solaris.h b/hotspot/src/os/solaris/vm/jvm_solaris.h index 7398e0bd899..92c551c6cb2 100644 --- a/hotspot/src/os/solaris/vm/jvm_solaris.h +++ b/hotspot/src/os/solaris/vm/jvm_solaris.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -85,7 +85,7 @@ /* Signal definitions */ #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ -#define ASYNC_SIGNAL SIGUSR2 /* Watcher & async err support. */ +#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */ #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ #define SHUTDOWN2_SIGNAL SIGINT #define SHUTDOWN3_SIGNAL SIGTERM diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index e93b0ed119a..e64dd520748 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1013,21 +1013,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, return true; } -// defined for >= Solaris 10. This allows builds on earlier versions -// of Solaris to take advantage of the newly reserved Solaris JVM signals. -// With SIGJVM1, SIGJVM2, ASYNC_SIGNAL is SIGJVM2. Previously INTERRUPT_SIGNAL -// was SIGJVM1. -// -#if !defined(SIGJVM1) - #define SIGJVM1 39 - #define SIGJVM2 40 -#endif - debug_only(static bool signal_sets_initialized = false); static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; -int os::Solaris::_SIGasync = ASYNC_SIGNAL; - bool os::Solaris::is_sig_ignored(int sig) { struct sigaction oact; sigaction(sig, (struct sigaction*)NULL, &oact); @@ -1040,12 +1028,6 @@ bool os::Solaris::is_sig_ignored(int sig) { } } -// Note: SIGRTMIN is a macro that calls sysconf() so it will -// dynamically detect SIGRTMIN value for the system at runtime, not buildtime -static bool isJVM1available() { - return SIGJVM1 < SIGRTMIN; -} - void os::Solaris::signal_sets_init() { // Should also have an assertion stating we are still single-threaded. assert(!signal_sets_initialized, "Already initialized"); @@ -1068,12 +1050,7 @@ void os::Solaris::signal_sets_init() { sigaddset(&unblocked_sigs, SIGSEGV); sigaddset(&unblocked_sigs, SIGBUS); sigaddset(&unblocked_sigs, SIGFPE); - - // Always true on Solaris 10+ - guarantee(isJVM1available(), "SIGJVM1/2 missing!"); - os::Solaris::set_SIGasync(SIGJVM2); - - sigaddset(&unblocked_sigs, os::Solaris::SIGasync()); + sigaddset(&unblocked_sigs, ASYNC_SIGNAL); if (!ReduceSignalUsage) { if (!os::Solaris::is_sig_ignored(SHUTDOWN1_SIGNAL)) { @@ -1918,7 +1895,6 @@ void os::print_memory_info(outputStream* st) { // Moved from whole group, because we need them here for diagnostic // prints. -#define OLDMAXSIGNUM 32 static int Maxsignum = 0; static int *ourSigFlags = NULL; @@ -2011,7 +1987,6 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SHUTDOWN1_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN3_SIGNAL, buf, buflen); - print_signal_handler(st, os::Solaris::SIGasync(), buf, buflen); } static char saved_jvm_path[MAXPATHLEN] = { 0 }; @@ -2179,14 +2154,12 @@ void os::signal_raise(int signal_number) { // a counter for each possible signal value static int Sigexit = 0; -static int Maxlibjsigsigs; static jint *pending_signals = NULL; static int *preinstalled_sigs = NULL; static struct sigaction *chainedsigactions = NULL; static sema_t sig_sem; typedef int (*version_getting_t)(); version_getting_t os::Solaris::get_libjsig_version = NULL; -static int libjsigversion = NULL; int os::sigexitnum_pd() { assert(Sigexit > 0, "signal memory not yet initialized"); @@ -2199,8 +2172,6 @@ void os::Solaris::init_signal_mem() { Sigexit = Maxsignum+1; assert(Maxsignum >0, "Unable to obtain max signal number"); - Maxlibjsigsigs = Maxsignum; - // pending_signals has one int per signal // The additional signal is for SIGEXIT - exit signal to signal_thread pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal); @@ -3564,7 +3535,7 @@ void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { // get current set of blocked signals and unblock resume signal pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); - sigdelset(&suspend_set, os::Solaris::SIGasync()); + sigdelset(&suspend_set, ASYNC_SIGNAL); sr_semaphore.signal(); // wait here until we are resumed @@ -3619,7 +3590,7 @@ bool os::message_box(const char* title, const char* message) { } static int sr_notify(OSThread* osthread) { - int status = thr_kill(osthread->thread_id(), os::Solaris::SIGasync()); + int status = thr_kill(osthread->thread_id(), ASYNC_SIGNAL); assert_status(status == 0, status, "thr_kill"); return status; } @@ -3764,7 +3735,7 @@ void os::os_exception_wrapper(java_call_t f, JavaValue* value, // // This routine may recognize any of the following kinds of signals: // SIGBUS, SIGSEGV, SIGILL, SIGFPE, BREAK_SIGNAL, SIGPIPE, SIGXFSZ, -// os::Solaris::SIGasync +// ASYNC_SIGNAL. // It should be consulted by handlers for any of those signals. // // The caller of this routine must pass in the three arguments supplied @@ -3799,7 +3770,7 @@ get_signal_t os::Solaris::get_signal_action = NULL; struct sigaction* os::Solaris::get_chained_signal_action(int sig) { struct sigaction *actp = NULL; - if ((libjsig_is_loaded) && (sig <= Maxlibjsigsigs)) { + if ((libjsig_is_loaded) && (sig <= Maxsignum)) { // Retrieve the old signal handler from libjsig actp = (*get_signal_action)(sig); } @@ -3964,6 +3935,7 @@ void os::run_periodic_checks() { DO_SIGNAL_CHECK(SIGBUS); DO_SIGNAL_CHECK(SIGPIPE); DO_SIGNAL_CHECK(SIGXFSZ); + DO_SIGNAL_CHECK(ASYNC_SIGNAL); // ReduceSignalUsage allows the user to override these handlers // see comments at the very top and jvm_solaris.h @@ -3973,10 +3945,6 @@ void os::run_periodic_checks() { DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL); DO_SIGNAL_CHECK(BREAK_SIGNAL); } - - // See comments above for using JVM1/JVM2 - DO_SIGNAL_CHECK(os::Solaris::SIGasync()); - } typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); @@ -4008,6 +3976,7 @@ void os::Solaris::check_signal_handler(int sig) { case SIGPIPE: case SIGXFSZ: case SIGILL: + case ASYNC_SIGNAL: jvmHandler = CAST_FROM_FN_PTR(address, signalHandler); break; @@ -4019,17 +3988,9 @@ void os::Solaris::check_signal_handler(int sig) { break; default: - int asynsig = os::Solaris::SIGasync(); - - if (sig == asynsig) { - jvmHandler = CAST_FROM_FN_PTR(address, signalHandler); - } else { return; - } - break; } - if (thisHandler != jvmHandler) { tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN)); tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN)); @@ -4061,7 +4022,6 @@ void os::Solaris::check_signal_handler(int sig) { } void os::Solaris::install_signal_handlers() { - bool libjsigdone = false; signal_handlers_are_installed = true; // signal-chaining @@ -4079,7 +4039,8 @@ void os::Solaris::install_signal_handlers() { dlsym(RTLD_DEFAULT, "JVM_get_libjsig_version")); libjsig_is_loaded = true; if (os::Solaris::get_libjsig_version != NULL) { - libjsigversion = (*os::Solaris::get_libjsig_version)(); + int libjsigversion = (*os::Solaris::get_libjsig_version)(); + assert(libjsigversion == JSIG_VERSION_1_4_1, "libjsig version mismatch"); } assert(UseSignalChaining, "should enable signal-chaining"); } @@ -4094,21 +4055,9 @@ void os::Solaris::install_signal_handlers() { set_signal_handler(SIGBUS, true, true); set_signal_handler(SIGILL, true, true); set_signal_handler(SIGFPE, true, true); + set_signal_handler(ASYNC_SIGNAL, true, true); - - if (os::Solaris::SIGasync() > OLDMAXSIGNUM) { - // Pre-1.4.1 Libjsig limited to signal chaining signals <= 32 so - // can not register overridable signals which might be > 32 - if (libjsig_is_loaded && libjsigversion <= JSIG_VERSION_1_4_1) { - // Tell libjsig jvm has finished setting signal handlers - (*end_signal_setting)(); - libjsigdone = true; - } - } - - set_signal_handler(os::Solaris::SIGasync(), true, true); - - if (libjsig_is_loaded && !libjsigdone) { + if (libjsig_is_loaded) { // Tell libjsig jvm finishes setting signal handlers (*end_signal_setting)(); } @@ -4408,10 +4357,6 @@ jint os::init_2(void) { Solaris::init_signal_mem(); Solaris::install_signal_handlers(); - if (libjsigversion < JSIG_VERSION_1_4_1) { - Maxlibjsigsigs = OLDMAXSIGNUM; - } - // initialize synchronization primitives to use either thread or // lwp synchronization (controlled by UseLWPSynchronization) Solaris::synchronization_init(); diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 7add07365ad..cb2b6ef6b19 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -109,9 +109,6 @@ class Solaris { static int (*get_libjsig_version)(); static void save_preinstalled_handler(int, struct sigaction&); static void check_signal_handler(int sig); - // For overridable signals - static int _SIGasync; // user-overridable ASYNC_SIGNAL - static void set_SIGasync(int newsig) { _SIGasync = newsig; } typedef int (*pthread_setname_np_func_t)(pthread_t, const char*); static pthread_setname_np_func_t _pthread_setname_np; @@ -120,7 +117,6 @@ class Solaris { // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); - static int SIGasync() { return _SIGasync; } static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo static bool valid_stack_address(Thread* thread, address sp); diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index c8c938edffe..e763b71f7d4 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -362,14 +362,14 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, } } - if (sig == os::Solaris::SIGasync()) { + if (sig == ASYNC_SIGNAL) { if (thread || vmthread) { OSThread::SR_handler(t, uc); return true; } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - // If os::Solaris::SIGasync not chained, and this is a non-vm and + // If ASYNC_SIGNAL not chained, and this is a non-vm and // non-java thread return true; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 5fcd2de83df..b841d21fddb 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -437,14 +437,14 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, } } - if (sig == os::Solaris::SIGasync()) { + if (sig == ASYNC_SIGNAL) { if(thread || vmthread){ OSThread::SR_handler(t, uc); return true; } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - // If os::Solaris::SIGasync not chained, and this is a non-vm and + // If ASYNC_SIGNAL not chained, and this is a non-vm and // non-java thread return true; } From 69fd40468abc957c4e01b16e33ef2f02a16d5f8d Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Fri, 17 Mar 2017 21:15:12 -0700 Subject: [PATCH 64/86] 8177070: Quarantine tests due to JDK-8177069 Reviewed-by: iveresov, iignatyev --- hotspot/test/ProblemList.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hotspot/test/ProblemList.txt b/hotspot/test/ProblemList.txt index b43932b86f9..234f2734ec8 100644 --- a/hotspot/test/ProblemList.txt +++ b/hotspot/test/ProblemList.txt @@ -106,6 +106,11 @@ compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java 8175791 windo compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java 8175791 windows-all compiler/aot/DeoptimizationTest.java 8175791 windows-all +# aot tests failing due to JDK-8177069 +compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java 8177069 windows-all +compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java 8177069 windows-all +compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java 8177069 windows-all +compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java 8177069 windows-all ############################################################################# From dd84bb9cffbc183a22483a43ebf897bfd1ec51c5 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 21 Mar 2017 11:21:11 +0100 Subject: [PATCH 65/86] 8176881: DerivedPointerTable Update log message in wrong order in regards to Redirty Cards Reviewed-by: sjohanss, jprovino --- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 317eec6a02f..e3104df54b5 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -380,6 +380,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms); debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms); + trace_phase(_gc_par_phases[RedirtyCards]); #if defined(COMPILER2) || INCLUDE_JVMCI debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms); #endif @@ -387,8 +388,6 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { debug_time("Clear Claimed Marks", _recorded_clear_claimed_marks_time_ms); } - trace_phase(_gc_par_phases[RedirtyCards]); - debug_time("Free Collection Set", _recorded_total_free_cset_time_ms); trace_time("Free Collection Set Serial", _recorded_serial_free_cset_time_ms); trace_phase(_gc_par_phases[YoungFreeCSet]); From 3af1da453318f3a701413b21aba6336dfe009877 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Tue, 21 Mar 2017 11:25:18 -0400 Subject: [PATCH 66/86] 8176705: Remove static functions in InstanceKlass Change static functions to instance functions and remove their 'this_k' parameters. Reviewed-by: dholmes, mgerdin, iklam --- hotspot/src/share/vm/oops/instanceKlass.cpp | 352 +++++++++----------- hotspot/src/share/vm/oops/instanceKlass.hpp | 44 +-- hotspot/src/share/vm/oops/method.hpp | 2 +- hotspot/src/share/vm/prims/jvm.cpp | 2 +- 4 files changed, 175 insertions(+), 225 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index bf53df7e68f..4150b4c7665 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -88,36 +88,36 @@ #define HOTSPOT_CLASS_INITIALIZATION_clinit HOTSPOT_CLASS_INITIALIZATION_CLINIT #define HOTSPOT_CLASS_INITIALIZATION_error HOTSPOT_CLASS_INITIALIZATION_ERROR #define HOTSPOT_CLASS_INITIALIZATION_end HOTSPOT_CLASS_INITIALIZATION_END -#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \ +#define DTRACE_CLASSINIT_PROBE(type, thread_type) \ { \ char* data = NULL; \ int len = 0; \ - Symbol* name = (clss)->name(); \ - if (name != NULL) { \ - data = (char*)name->bytes(); \ - len = name->utf8_length(); \ + Symbol* clss_name = name(); \ + if (clss_name != NULL) { \ + data = (char*)clss_name->bytes(); \ + len = clss_name->utf8_length(); \ } \ HOTSPOT_CLASS_INITIALIZATION_##type( \ - data, len, (clss)->class_loader(), thread_type); \ + data, len, class_loader(), thread_type); \ } -#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \ +#define DTRACE_CLASSINIT_PROBE_WAIT(type, thread_type, wait) \ { \ char* data = NULL; \ int len = 0; \ - Symbol* name = (clss)->name(); \ - if (name != NULL) { \ - data = (char*)name->bytes(); \ - len = name->utf8_length(); \ + Symbol* clss_name = name(); \ + if (clss_name != NULL) { \ + data = (char*)clss_name->bytes(); \ + len = clss_name->utf8_length(); \ } \ HOTSPOT_CLASS_INITIALIZATION_##type( \ - data, len, (clss)->class_loader(), thread_type, wait); \ + data, len, class_loader(), thread_type, wait); \ } #else // ndef DTRACE_ENABLED -#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) -#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) +#define DTRACE_CLASSINIT_PROBE(type, thread_type) +#define DTRACE_CLASSINIT_PROBE_WAIT(type, thread_type, wait) #endif // ndef DTRACE_ENABLED @@ -385,14 +385,14 @@ void InstanceKlass::eager_initialize(Thread *thread) { if (this->class_initializer() != NULL) return; // abort if it is java.lang.Object (initialization is handled in genesis) - Klass* super = this->super(); - if (super == NULL) return; + Klass* super_klass = super(); + if (super_klass == NULL) return; // abort if the super class should be initialized - if (!InstanceKlass::cast(super)->is_initialized()) return; + if (!InstanceKlass::cast(super_klass)->is_initialized()) return; // call body to expose the this pointer - eager_initialize_impl(this); + eager_initialize_impl(); } } @@ -431,17 +431,17 @@ void InstanceKlass::fence_and_clear_init_lock() { assert(!is_not_initialized(), "class must be initialized now"); } -void InstanceKlass::eager_initialize_impl(InstanceKlass* this_k) { +void InstanceKlass::eager_initialize_impl() { EXCEPTION_MARK; HandleMark hm(THREAD); - Handle init_lock(THREAD, this_k->init_lock()); - ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); + Handle h_init_lock(THREAD, init_lock()); + ObjectLocker ol(h_init_lock, THREAD, init_lock() != NULL); // abort if someone beat us to the initialization - if (!this_k->is_not_initialized()) return; // note: not equivalent to is_initialized() + if (!is_not_initialized()) return; // note: not equivalent to is_initialized() - ClassState old_state = this_k->init_state(); - link_class_impl(this_k, true, THREAD); + ClassState old_state = init_state(); + link_class_impl(true, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; // Abort if linking the class throws an exception. @@ -449,16 +449,16 @@ void InstanceKlass::eager_initialize_impl(InstanceKlass* this_k) { // Use a test to avoid redundantly resetting the state if there's // no change. Set_init_state() asserts that state changes make // progress, whereas here we might just be spinning in place. - if( old_state != this_k->_init_state ) - this_k->set_init_state (old_state); + if (old_state != _init_state) + set_init_state(old_state); } else { // linking successfull, mark class as initialized - this_k->set_init_state (fully_initialized); - this_k->fence_and_clear_init_lock(); + set_init_state(fully_initialized); + fence_and_clear_init_lock(); // trace if (log_is_enabled(Info, class, init)) { ResourceMark rm(THREAD); - log_info(class, init)("[Initialized %s without side effects]", this_k->external_name()); + log_info(class, init)("[Initialized %s without side effects]", external_name()); } } } @@ -469,7 +469,7 @@ void InstanceKlass::eager_initialize_impl(InstanceKlass* this_k) { // Note: implementation moved to static method to expose the this pointer. void InstanceKlass::initialize(TRAPS) { if (this->should_be_initialized()) { - initialize_impl(this, CHECK); + initialize_impl(CHECK); // Note: at this point the class may be initialized // OR it may be in the state of being initialized // in case of recursive initialization! @@ -479,12 +479,11 @@ void InstanceKlass::initialize(TRAPS) { } -bool InstanceKlass::verify_code( - InstanceKlass* this_k, bool throw_verifyerror, TRAPS) { +bool InstanceKlass::verify_code(bool throw_verifyerror, TRAPS) { // 1) Verify the bytecodes Verifier::Mode mode = throw_verifyerror ? Verifier::ThrowException : Verifier::NoException; - return Verifier::verify(this_k, mode, this_k->should_verify_class(), THREAD); + return Verifier::verify(this, mode, should_verify_class(), THREAD); } @@ -499,7 +498,7 @@ void InstanceKlass::unlink_class() { void InstanceKlass::link_class(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - link_class_impl(this, true, CHECK); + link_class_impl(true, CHECK); } } @@ -508,14 +507,13 @@ void InstanceKlass::link_class(TRAPS) { bool InstanceKlass::link_class_or_fail(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { - link_class_impl(this, false, CHECK_false); + link_class_impl(false, CHECK_false); } return is_linked(); } -bool InstanceKlass::link_class_impl( - InstanceKlass* this_k, bool throw_verifyerror, TRAPS) { - if (DumpSharedSpaces && this_k->is_in_error_state()) { +bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) { + if (DumpSharedSpaces && is_in_error_state()) { // This is for CDS dumping phase only -- we use the in_error_state to indicate that // the class has failed verification. Throwing the NoClassDefFoundError here is just // a convenient way to stop repeat attempts to verify the same (bad) class. @@ -524,11 +522,10 @@ bool InstanceKlass::link_class_impl( // if we are executing Java code. This is not a problem for CDS dumping phase since // it doesn't execute any Java code. ResourceMark rm(THREAD); - THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(), - this_k->external_name(), false); + THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(), external_name(), false); } // return if already verified - if (this_k->is_linked()) { + if (is_linked()) { return true; } @@ -538,34 +535,34 @@ bool InstanceKlass::link_class_impl( JavaThread* jt = (JavaThread*)THREAD; // link super class before linking this class - Klass* super = this_k->super(); - if (super != NULL) { - if (super->is_interface()) { // check if super class is an interface + Klass* super_klass = super(); + if (super_klass != NULL) { + if (super_klass->is_interface()) { // check if super class is an interface ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "class %s has interface %s as super class", - this_k->external_name(), - super->external_name() + external_name(), + super_klass->external_name() ); return false; } - InstanceKlass* ik_super = InstanceKlass::cast(super); - link_class_impl(ik_super, throw_verifyerror, CHECK_false); + InstanceKlass* ik_super = InstanceKlass::cast(super_klass); + ik_super->link_class_impl(throw_verifyerror, CHECK_false); } // link all interfaces implemented by this class before linking this class - Array* interfaces = this_k->local_interfaces(); + Array* interfaces = local_interfaces(); int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) { InstanceKlass* interk = InstanceKlass::cast(interfaces->at(index)); - link_class_impl(interk, throw_verifyerror, CHECK_false); + interk->link_class_impl(throw_verifyerror, CHECK_false); } // in case the class is linked in the process of linking its superclasses - if (this_k->is_linked()) { + if (is_linked()) { return true; } @@ -581,17 +578,17 @@ bool InstanceKlass::link_class_impl( // verification & rewriting { HandleMark hm(THREAD); - Handle init_lock(THREAD, this_k->init_lock()); - ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); + Handle h_init_lock(THREAD, init_lock()); + ObjectLocker ol(h_init_lock, THREAD, init_lock() != NULL); // rewritten will have been set if loader constraint error found // on an earlier link attempt // don't verify or rewrite if already rewritten // - if (!this_k->is_linked()) { - if (!this_k->is_rewritten()) { + if (!is_linked()) { + if (!is_rewritten()) { { - bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD); + bool verify_ok = verify_code(throw_verifyerror, THREAD); if (!verify_ok) { return false; } @@ -600,18 +597,18 @@ bool InstanceKlass::link_class_impl( // Just in case a side-effect of verify linked this class already // (which can sometimes happen since the verifier loads classes // using custom class loaders, which are free to initialize things) - if (this_k->is_linked()) { + if (is_linked()) { return true; } // also sets rewritten - this_k->rewrite_class(CHECK_false); - } else if (this_k->is_shared()) { - SystemDictionaryShared::check_verification_constraints(this_k, CHECK_false); + rewrite_class(CHECK_false); + } else if (is_shared()) { + SystemDictionaryShared::check_verification_constraints(this, CHECK_false); } // relocate jsrs and link methods after they are all rewritten - this_k->link_methods(CHECK_false); + link_methods(CHECK_false); // Initialize the vtable and interface table after // methods have been rewritten since rewrite may @@ -620,26 +617,26 @@ bool InstanceKlass::link_class_impl( // // initialize_vtable and initialize_itable need to be rerun for // a shared class if the class is not loaded by the NULL classloader. - ClassLoaderData * loader_data = this_k->class_loader_data(); - if (!(this_k->is_shared() && + ClassLoaderData * loader_data = class_loader_data(); + if (!(is_shared() && loader_data->is_the_null_class_loader_data())) { ResourceMark rm(THREAD); - this_k->vtable()->initialize_vtable(true, CHECK_false); - this_k->itable()->initialize_itable(true, CHECK_false); + vtable()->initialize_vtable(true, CHECK_false); + itable()->initialize_itable(true, CHECK_false); } #ifdef ASSERT else { ResourceMark rm(THREAD); - this_k->vtable()->verify(tty, true); + vtable()->verify(tty, true); // In case itable verification is ever added. - // this_k->itable()->verify(tty, true); + // itable()->verify(tty, true); } #endif - this_k->set_init_state(linked); + set_init_state(linked); if (JvmtiExport::should_post_class_prepare()) { Thread *thread = THREAD; assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_prepare((JavaThread *) thread, this_k); + JvmtiExport::post_class_prepare((JavaThread *) thread, this); } } } @@ -674,17 +671,17 @@ void InstanceKlass::link_methods(TRAPS) { } // Eagerly initialize superinterfaces that declare default methods (concrete instance: any access) -void InstanceKlass::initialize_super_interfaces(InstanceKlass* this_k, TRAPS) { - assert (this_k->has_nonstatic_concrete_methods(), "caller should have checked this"); - for (int i = 0; i < this_k->local_interfaces()->length(); ++i) { - Klass* iface = this_k->local_interfaces()->at(i); +void InstanceKlass::initialize_super_interfaces(TRAPS) { + assert (has_nonstatic_concrete_methods(), "caller should have checked this"); + for (int i = 0; i < local_interfaces()->length(); ++i) { + Klass* iface = local_interfaces()->at(i); InstanceKlass* ik = InstanceKlass::cast(iface); // Initialization is depth first search ie. we start with top of the inheritance tree // has_nonstatic_concrete_methods drives searching superinterfaces since it // means has_nonstatic_concrete_methods in its superinterface hierarchy if (ik->has_nonstatic_concrete_methods()) { - ik->initialize_super_interfaces(ik, CHECK); + ik->initialize_super_interfaces(CHECK); } // Only initialize() interfaces that "declare" concrete methods. @@ -694,22 +691,22 @@ void InstanceKlass::initialize_super_interfaces(InstanceKlass* this_k, TRAPS) { } } -void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { +void InstanceKlass::initialize_impl(TRAPS) { HandleMark hm(THREAD); // Make sure klass is linked (verified) before initialization // A class could already be verified, since it has been reflected upon. - this_k->link_class(CHECK); + link_class(CHECK); - DTRACE_CLASSINIT_PROBE(required, this_k, -1); + DTRACE_CLASSINIT_PROBE(required, -1); bool wait = false; // refer to the JVM book page 47 for description of steps // Step 1 { - Handle init_lock(THREAD, this_k->init_lock()); - ObjectLocker ol(init_lock, THREAD, init_lock() != NULL); + Handle h_init_lock(THREAD, init_lock()); + ObjectLocker ol(h_init_lock, THREAD, init_lock() != NULL); Thread *self = THREAD; // it's passed the current thread @@ -717,29 +714,29 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { // If we were to use wait() instead of waitInterruptibly() then // we might end up throwing IE from link/symbol resolution sites // that aren't expected to throw. This would wreak havoc. See 6320309. - while(this_k->is_being_initialized() && !this_k->is_reentrant_initialization(self)) { + while(is_being_initialized() && !is_reentrant_initialization(self)) { wait = true; ol.waitUninterruptibly(CHECK); } // Step 3 - if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) { - DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k, -1,wait); + if (is_being_initialized() && is_reentrant_initialization(self)) { + DTRACE_CLASSINIT_PROBE_WAIT(recursive, -1, wait); return; } // Step 4 - if (this_k->is_initialized()) { - DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k, -1,wait); + if (is_initialized()) { + DTRACE_CLASSINIT_PROBE_WAIT(concurrent, -1, wait); return; } // Step 5 - if (this_k->is_in_error_state()) { - DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k, -1,wait); + if (is_in_error_state()) { + DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait); ResourceMark rm(THREAD); const char* desc = "Could not initialize class "; - const char* className = this_k->external_name(); + const char* className = external_name(); size_t msglen = strlen(desc) + strlen(className) + 1; char* message = NEW_RESOURCE_ARRAY(char, msglen); if (NULL == message) { @@ -752,15 +749,15 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { } // Step 6 - this_k->set_init_state(being_initialized); - this_k->set_init_thread(self); + set_init_state(being_initialized); + set_init_thread(self); } // Step 7 // Next, if C is a class rather than an interface, initialize it's super class and super // interfaces. - if (!this_k->is_interface()) { - Klass* super_klass = this_k->super(); + if (!is_interface()) { + Klass* super_klass = super(); if (super_klass != NULL && super_klass->should_be_initialized()) { super_klass->initialize(THREAD); } @@ -768,8 +765,8 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { // the initialization of C triggers initialization of its super interfaces. // Only need to recurse if has_nonstatic_concrete_methods which includes declaring and // having a superinterface that declares, non-static, concrete methods - if (!HAS_PENDING_EXCEPTION && this_k->has_nonstatic_concrete_methods()) { - this_k->initialize_super_interfaces(this_k, THREAD); + if (!HAS_PENDING_EXCEPTION && has_nonstatic_concrete_methods()) { + initialize_super_interfaces(THREAD); } // If any exceptions, complete abruptly, throwing the same exception as above. @@ -779,23 +776,23 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { { EXCEPTION_MARK; // Locks object, set state, and notify all waiting threads - this_k->set_initialization_state_and_notify(initialization_error, THREAD); + set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; } - DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k, -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(super__failed, -1, wait); THROW_OOP(e()); } } // Look for aot compiled methods for this klass, including class initializer. - AOTLoader::load_for_klass(this_k, THREAD); + AOTLoader::load_for_klass(this, THREAD); // Step 8 { assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); JavaThread* jt = (JavaThread*)THREAD; - DTRACE_CLASSINIT_PROBE_WAIT(clinit, this_k, -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(clinit, -1, wait); // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer(). PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), @@ -804,14 +801,14 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { jt->get_thread_stat()->perf_recursion_counts_addr(), jt->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_CLINIT); - this_k->call_class_initializer(THREAD); + call_class_initializer(THREAD); } // Step 9 if (!HAS_PENDING_EXCEPTION) { - this_k->set_initialization_state_and_notify(fully_initialized, CHECK); + set_initialization_state_and_notify(fully_initialized, CHECK); { ResourceMark rm(THREAD); - debug_only(this_k->vtable()->verify(tty, true);) + debug_only(vtable()->verify(tty, true);) } } else { @@ -823,13 +820,13 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { JvmtiExport::clear_detected_exception((JavaThread*)THREAD); { EXCEPTION_MARK; - this_k->set_initialization_state_and_notify(initialization_error, THREAD); + set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below // JVMTI has already reported the pending exception // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError JvmtiExport::clear_detected_exception((JavaThread*)THREAD); } - DTRACE_CLASSINIT_PROBE_WAIT(error, this_k, -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(error, -1, wait); if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { @@ -839,25 +836,20 @@ void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) { &args); } } - DTRACE_CLASSINIT_PROBE_WAIT(end, this_k, -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(end, -1, wait); } -// Note: implementation moved to static method to expose the this pointer. void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) { - set_initialization_state_and_notify_impl(this, state, CHECK); -} - -void InstanceKlass::set_initialization_state_and_notify_impl(InstanceKlass* this_k, ClassState state, TRAPS) { - Handle init_lock(THREAD, this_k->init_lock()); + Handle h_init_lock(THREAD, init_lock()); if (init_lock() != NULL) { - ObjectLocker ol(init_lock, THREAD); - this_k->set_init_state(state); - this_k->fence_and_clear_init_lock(); + ObjectLocker ol(h_init_lock, THREAD); + set_init_state(state); + fence_and_clear_init_lock(); ol.notify_all(CHECK); } else { assert(init_lock() != NULL, "The initialization state should never be set twice"); - this_k->set_init_state(state); + set_init_state(state); } } @@ -1037,12 +1029,8 @@ void InstanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) { } Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) { - return array_klass_impl(this, or_null, n, THREAD); -} - -Klass* InstanceKlass::array_klass_impl(InstanceKlass* this_k, bool or_null, int n, TRAPS) { // Need load-acquire for lock-free read - if (this_k->array_klasses_acquire() == NULL) { + if (array_klasses_acquire() == NULL) { if (or_null) return NULL; ResourceMark rm; @@ -1053,15 +1041,15 @@ Klass* InstanceKlass::array_klass_impl(InstanceKlass* this_k, bool or_null, int MutexLocker ma(MultiArray_lock, THREAD); // Check if update has already taken place - if (this_k->array_klasses() == NULL) { - Klass* k = ObjArrayKlass::allocate_objArray_klass(this_k->class_loader_data(), 1, this_k, CHECK_NULL); + if (array_klasses() == NULL) { + Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL); // use 'release' to pair with lock-free load - this_k->release_set_array_klasses(k); + release_set_array_klasses(k); } } } // _this will always be set at this point - ObjArrayKlass* oak = (ObjArrayKlass*)this_k->array_klasses(); + ObjArrayKlass* oak = (ObjArrayKlass*)array_klasses(); if (or_null) { return oak->array_klass_or_null(n); } @@ -1072,11 +1060,7 @@ Klass* InstanceKlass::array_klass_impl(bool or_null, TRAPS) { return array_klass_impl(or_null, 1, THREAD); } -void InstanceKlass::call_class_initializer(TRAPS) { - call_class_initializer_impl(this, THREAD); -} - -static int call_class_initializer_impl_counter = 0; // for debugging +static int call_class_initializer_counter = 0; // for debugging Method* InstanceKlass::class_initializer() const { Method* clinit = find_method( @@ -1087,22 +1071,22 @@ Method* InstanceKlass::class_initializer() const { return NULL; } -void InstanceKlass::call_class_initializer_impl(InstanceKlass* this_k, TRAPS) { +void InstanceKlass::call_class_initializer(TRAPS) { if (ReplayCompiles && (ReplaySuppressInitializers == 1 || - ReplaySuppressInitializers >= 2 && this_k->class_loader() != NULL)) { + ReplaySuppressInitializers >= 2 && class_loader() != NULL)) { // Hide the existence of the initializer for the purpose of replaying the compile return; } - methodHandle h_method(THREAD, this_k->class_initializer()); - assert(!this_k->is_initialized(), "we cannot initialize twice"); + methodHandle h_method(THREAD, class_initializer()); + assert(!is_initialized(), "we cannot initialize twice"); if (log_is_enabled(Info, class, init)) { ResourceMark rm; outputStream* log = Log(class, init)::info_stream(); - log->print("%d Initializing ", call_class_initializer_impl_counter++); - this_k->name()->print_value_on(log); - log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this_k)); + log->print("%d Initializing ", call_class_initializer_counter++); + name()->print_value_on(log); + log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this)); } if (h_method() != NULL) { JavaCallArguments args; // No arguments @@ -1253,13 +1237,7 @@ void InstanceKlass::do_local_static_fields(FieldClosure* cl) { void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) { - do_local_static_fields_impl(this, f, mirror, CHECK); -} - - -void InstanceKlass::do_local_static_fields_impl(InstanceKlass* this_k, - void f(fieldDescriptor* fd, Handle, TRAPS), Handle mirror, TRAPS) { - for (JavaFieldStream fs(this_k); !fs.done(); fs.next()) { + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { fieldDescriptor& fd = fs.field_descriptor(); f(&fd, mirror, CHECK); @@ -1618,14 +1596,14 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, } /* jni_id_for_impl for jfieldIds only */ -JNIid* InstanceKlass::jni_id_for_impl(InstanceKlass* this_k, int offset) { +JNIid* InstanceKlass::jni_id_for_impl(int offset) { MutexLocker ml(JfieldIdCreation_lock); // Retry lookup after we got the lock - JNIid* probe = this_k->jni_ids() == NULL ? NULL : this_k->jni_ids()->find(offset); + JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset); if (probe == NULL) { // Slow case, allocate new static field identifier - probe = new JNIid(this_k, offset, this_k->jni_ids()); - this_k->set_jni_ids(probe); + probe = new JNIid(this, offset, jni_ids()); + set_jni_ids(probe); } return probe; } @@ -1635,7 +1613,7 @@ JNIid* InstanceKlass::jni_id_for_impl(InstanceKlass* this_k, int offset) { JNIid* InstanceKlass::jni_id_for(int offset) { JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset); if (probe == NULL) { - probe = jni_id_for_impl(this, offset); + probe = jni_id_for_impl(offset); } return probe; } @@ -1673,9 +1651,9 @@ void InstanceKlass::set_enclosing_method_indices(u2 class_index, // locking has to be done very carefully to avoid deadlocks // and/or other cache consistency problems. // -jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& method_h) { +jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { size_t idnum = (size_t)method_h->method_idnum(); - jmethodID* jmeths = ik->methods_jmethod_ids_acquire(); + jmethodID* jmeths = methods_jmethod_ids_acquire(); size_t length = 0; jmethodID id = NULL; @@ -1699,7 +1677,7 @@ jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& m if (jmeths != NULL) { // the cache already exists - if (!ik->idnum_can_increment()) { + if (!idnum_can_increment()) { // the cache can't grow so we can just get the current values get_jmethod_id_length_value(jmeths, idnum, &length, &id); } else { @@ -1733,7 +1711,7 @@ jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& m jmethodID* new_jmeths = NULL; if (length <= idnum) { // allocate a new cache that might be used - size_t size = MAX2(idnum+1, (size_t)ik->idnum_allocated_count()); + size_t size = MAX2(idnum+1, (size_t)idnum_allocated_count()); new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass); memset(new_jmeths, 0, (size+1)*sizeof(jmethodID)); // cache size is stored in element[0], other elements offset by one @@ -1744,23 +1722,23 @@ jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& m jmethodID new_id = NULL; if (method_h->is_old() && !method_h->is_obsolete()) { // The method passed in is old (but not obsolete), we need to use the current version - Method* current_method = ik->method_with_idnum((int)idnum); + Method* current_method = method_with_idnum((int)idnum); assert(current_method != NULL, "old and but not obsolete, so should exist"); - new_id = Method::make_jmethod_id(ik->class_loader_data(), current_method); + new_id = Method::make_jmethod_id(class_loader_data(), current_method); } else { // It is the current version of the method or an obsolete method, // use the version passed in - new_id = Method::make_jmethod_id(ik->class_loader_data(), method_h()); + new_id = Method::make_jmethod_id(class_loader_data(), method_h()); } if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) { // we're single threaded or at a safepoint - no locking needed - id = get_jmethod_id_fetch_or_update(ik, idnum, new_id, new_jmeths, + id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths, &to_dealloc_id, &to_dealloc_jmeths); } else { MutexLocker ml(JmethodIdCreation_lock); - id = get_jmethod_id_fetch_or_update(ik, idnum, new_id, new_jmeths, + id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths, &to_dealloc_id, &to_dealloc_jmeths); } @@ -1771,7 +1749,7 @@ jmethodID InstanceKlass::get_jmethod_id(InstanceKlass* ik, const methodHandle& m } // free up the new ID since it wasn't needed if (to_dealloc_id != NULL) { - Method::destroy_jmethod_id(ik->class_loader_data(), to_dealloc_id); + Method::destroy_jmethod_id(class_loader_data(), to_dealloc_id); } } return id; @@ -1803,7 +1781,7 @@ void InstanceKlass::ensure_space_for_methodids(int start_offset) { // the VMThread or have cache consistency issues. // jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( - InstanceKlass* ik, size_t idnum, jmethodID new_id, + size_t idnum, jmethodID new_id, jmethodID* new_jmeths, jmethodID* to_dealloc_id_p, jmethodID** to_dealloc_jmeths_p) { assert(new_id != NULL, "sanity check"); @@ -1814,7 +1792,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( JmethodIdCreation_lock->owned_by_self(), "sanity check"); // reacquire the cache - we are locked, single threaded or at a safepoint - jmethodID* jmeths = ik->methods_jmethod_ids_acquire(); + jmethodID* jmeths = methods_jmethod_ids_acquire(); jmethodID id = NULL; size_t length = 0; @@ -1827,7 +1805,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( } *to_dealloc_jmeths_p = jmeths; // save old cache for later delete } - ik->release_set_methods_jmethod_ids(jmeths = new_jmeths); + release_set_methods_jmethod_ids(jmeths = new_jmeths); } else { // fetch jmethodID (if any) from the existing cache id = jmeths[idnum+1]; @@ -2435,13 +2413,6 @@ bool InstanceKlass::is_override(const methodHandle& super_method, Handle targetc return(is_same_class_package(targetclassloader(), targetclassname)); } -/* defined for now in jvm.cpp, for historical reasons *-- -Klass* InstanceKlass::compute_enclosing_class_impl(InstanceKlass* self, - Symbol*& simple_name_result, TRAPS) { - ... -} -*/ - // Only boot and platform class loaders can define classes in "java/" packages. void InstanceKlass::check_prohibited_package(Symbol* class_name, Handle class_loader, @@ -2467,29 +2438,27 @@ void InstanceKlass::check_prohibited_package(Symbol* class_name, } // tell if two classes have the same enclosing class (at package level) -bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1, - const Klass* class2, - TRAPS) { - if (class2 == class1) return true; +bool InstanceKlass::is_same_package_member(const Klass* class2, TRAPS) const { + if (class2 == this) return true; if (!class2->is_instance_klass()) return false; // must be in same package before we try anything else - if (!class1->is_same_class_package(class2)) + if (!is_same_class_package(class2)) return false; - // As long as there is an outer1.getEnclosingClass, + // As long as there is an outer_this.getEnclosingClass, // shift the search outward. - const InstanceKlass* outer1 = class1; + const InstanceKlass* outer_this = this; for (;;) { - // As we walk along, look for equalities between outer1 and class2. - // Eventually, the walks will terminate as outer1 stops + // As we walk along, look for equalities between outer_this and class2. + // Eventually, the walks will terminate as outer_this stops // at the top-level class around the original class. bool ignore_inner_is_member; - const Klass* next = outer1->compute_enclosing_class(&ignore_inner_is_member, - CHECK_false); + const Klass* next = outer_this->compute_enclosing_class(&ignore_inner_is_member, + CHECK_false); if (next == NULL) break; if (next == class2) return true; - outer1 = InstanceKlass::cast(next); + outer_this = InstanceKlass::cast(next); } // Now do the same for class2. @@ -2500,8 +2469,8 @@ bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1, CHECK_false); if (next == NULL) break; // Might as well check the new outer against all available values. - if (next == class1) return true; - if (next == outer1) return true; + if (next == this) return true; + if (next == outer_this) return true; outer2 = InstanceKlass::cast(next); } @@ -2510,16 +2479,16 @@ bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1, return false; } -bool InstanceKlass::find_inner_classes_attr(const InstanceKlass* k, int* ooff, int* noff, TRAPS) { - constantPoolHandle i_cp(THREAD, k->constants()); - for (InnerClassesIterator iter(k); !iter.done(); iter.next()) { +bool InstanceKlass::find_inner_classes_attr(int* ooff, int* noff, TRAPS) const { + constantPoolHandle i_cp(THREAD, constants()); + for (InnerClassesIterator iter(this); !iter.done(); iter.next()) { int ioff = iter.inner_class_info_index(); if (ioff != 0) { // Check to see if the name matches the class we're looking for // before attempting to find the class. - if (i_cp->klass_name_at_matches(k, ioff)) { + if (i_cp->klass_name_at_matches(this, ioff)) { Klass* inner_klass = i_cp->klass_at(ioff, CHECK_false); - if (k == inner_klass) { + if (this == inner_klass) { *ooff = iter.outer_class_info_index(); *noff = iter.inner_name_index(); return true; @@ -2530,14 +2499,13 @@ bool InstanceKlass::find_inner_classes_attr(const InstanceKlass* k, int* ooff, i return false; } -InstanceKlass* InstanceKlass::compute_enclosing_class_impl(const InstanceKlass* k, - bool* inner_is_member, - TRAPS) { +InstanceKlass* InstanceKlass::compute_enclosing_class(bool* inner_is_member, TRAPS) const { InstanceKlass* outer_klass = NULL; *inner_is_member = false; int ooff = 0, noff = 0; - if (find_inner_classes_attr(k, &ooff, &noff, THREAD)) { - constantPoolHandle i_cp(THREAD, k->constants()); + bool has_inner_classes_attr = find_inner_classes_attr(&ooff, &noff, THREAD); + if (has_inner_classes_attr) { + constantPoolHandle i_cp(THREAD, constants()); if (ooff != 0) { Klass* ok = i_cp->klass_at(ooff, CHECK_NULL); outer_klass = InstanceKlass::cast(ok); @@ -2545,7 +2513,7 @@ InstanceKlass* InstanceKlass::compute_enclosing_class_impl(const InstanceKlass* } if (NULL == outer_klass) { // It may be anonymous; try for that. - int encl_method_class_idx = k->enclosing_method_class_index(); + int encl_method_class_idx = enclosing_method_class_index(); if (encl_method_class_idx != 0) { Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL); outer_klass = InstanceKlass::cast(ok); @@ -2560,7 +2528,7 @@ InstanceKlass* InstanceKlass::compute_enclosing_class_impl(const InstanceKlass* // Throws an exception if outer klass has not declared k as an inner klass // We need evidence that each klass knows about the other, or else // the system could allow a spoof of an inner class to gain access rights. - Reflection::check_for_inner_class(outer_klass, k, *inner_is_member, CHECK_NULL); + Reflection::check_for_inner_class(outer_klass, this, *inner_is_member, CHECK_NULL); return outer_klass; } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index cc31ad7d46b..b5d2e9ad1ea 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -464,16 +464,10 @@ class InstanceKlass: public Klass { const Symbol* class_name2); // find an enclosing class - InstanceKlass* compute_enclosing_class(bool* inner_is_member, TRAPS) const { - return compute_enclosing_class_impl(this, inner_is_member, THREAD); - } - static InstanceKlass* compute_enclosing_class_impl(const InstanceKlass* self, - bool* inner_is_member, - TRAPS); + InstanceKlass* compute_enclosing_class(bool* inner_is_member, TRAPS) const; - // Find InnerClasses attribute for k and return outer_class_info_index & inner_name_index. - static bool find_inner_classes_attr(const InstanceKlass* k, - int* ooff, int* noff, TRAPS); + // Find InnerClasses attribute and return outer_class_info_index & inner_name_index. + bool find_inner_classes_attr(int* ooff, int* noff, TRAPS) const; private: // Check prohibited package ("java/" only loadable by boot or platform loaders) @@ -482,12 +476,7 @@ class InstanceKlass: public Klass { TRAPS); public: // tell if two classes have the same enclosing class (at package level) - bool is_same_package_member(const Klass* class2, TRAPS) const { - return is_same_package_member_impl(this, class2, THREAD); - } - static bool is_same_package_member_impl(const InstanceKlass* self, - const Klass* class2, - TRAPS); + bool is_same_package_member(const Klass* class2, TRAPS) const; // initialization state bool is_loaded() const { return _init_state >= loaded; } @@ -883,10 +872,9 @@ public: u2 method_index); // jmethodID support - static jmethodID get_jmethod_id(InstanceKlass* ik, - const methodHandle& method_h); - static jmethodID get_jmethod_id_fetch_or_update(InstanceKlass* ik, - size_t idnum, jmethodID new_id, jmethodID* new_jmeths, + jmethodID get_jmethod_id(const methodHandle& method_h); + jmethodID get_jmethod_id_fetch_or_update(size_t idnum, + jmethodID new_id, jmethodID* new_jmeths, jmethodID* to_dealloc_id_p, jmethodID** to_dealloc_jmeths_p); static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum, @@ -1306,19 +1294,13 @@ public: private: void fence_and_clear_init_lock(); - // Static methods that are used to implement member methods where an exposed this pointer - // is needed due to possible GCs - static bool link_class_impl (InstanceKlass* this_k, bool throw_verifyerror, TRAPS); - static bool verify_code (InstanceKlass* this_k, bool throw_verifyerror, TRAPS); - static void initialize_impl (InstanceKlass* this_k, TRAPS); - static void initialize_super_interfaces (InstanceKlass* this_k, TRAPS); - static void eager_initialize_impl (InstanceKlass* this_k); - static void set_initialization_state_and_notify_impl (InstanceKlass* this_k, ClassState state, TRAPS); - static void call_class_initializer_impl (InstanceKlass* this_k, TRAPS); - static Klass* array_klass_impl (InstanceKlass* this_k, bool or_null, int n, TRAPS); - static void do_local_static_fields_impl (InstanceKlass* this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS); + bool link_class_impl (bool throw_verifyerror, TRAPS); + bool verify_code (bool throw_verifyerror, TRAPS); + void initialize_impl (TRAPS); + void initialize_super_interfaces (TRAPS); + void eager_initialize_impl (); /* jni_id_for_impl for jfieldID only */ - static JNIid* jni_id_for_impl (InstanceKlass* this_k, int offset); + JNIid* jni_id_for_impl (int offset); // Returns the array class for the n'th dimension Klass* array_klass_impl(bool or_null, int n, TRAPS); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 98fa587db4c..54c6211619d 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -811,7 +811,7 @@ class Method : public Metadata { static void print_jmethod_ids(ClassLoaderData* loader_data, outputStream* out) PRODUCT_RETURN; // Get this method's jmethodID -- allocate if it doesn't exist - jmethodID jmethod_id() { return InstanceKlass::get_jmethod_id(method_holder(), this); } + jmethodID jmethod_id() { return method_holder()->get_jmethod_id(this); } // Lookup the jmethodID for this method. Return NULL if not found. // NOTE that this function can be called from a signal handler diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index f41c4a55afa..73b3eadd322 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1532,7 +1532,7 @@ JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls)) } InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); int ooff = 0, noff = 0; - if (InstanceKlass::find_inner_classes_attr(k, &ooff, &noff, THREAD)) { + if (k->find_inner_classes_attr(&ooff, &noff, THREAD)) { if (noff != 0) { constantPoolHandle i_cp(thread, k->constants()); Symbol* name = i_cp->symbol_at(noff); From 98bf7d77276a33391eef14d6c7b08cb9833551d8 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Wed, 21 Dec 2016 12:47:29 +0300 Subject: [PATCH 67/86] 8171848: ObjectMonitor verify() and print() methods are empty Reviewed-by: dholmes --- hotspot/src/share/vm/runtime/objectMonitor.cpp | 6 ------ hotspot/src/share/vm/runtime/objectMonitor.hpp | 4 ---- hotspot/src/share/vm/runtime/synchronizer.cpp | 17 ----------------- hotspot/src/share/vm/runtime/synchronizer.hpp | 1 - 4 files changed, 28 deletions(-) diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index e765ee011eb..adc5845a634 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -2445,12 +2445,6 @@ void ObjectMonitor::sanity_checks() { } #ifndef PRODUCT -void ObjectMonitor::verify() { -} - -void ObjectMonitor::print() { -} - void ObjectMonitor_test() { ObjectMonitor::sanity_checks(); } diff --git a/hotspot/src/share/vm/runtime/objectMonitor.hpp b/hotspot/src/share/vm/runtime/objectMonitor.hpp index 253887f8ea6..4895874cbac 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.hpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp @@ -313,10 +313,6 @@ class ObjectMonitor { void clear(); static void sanity_checks(); // public for -XX:+ExecuteInternalVMTests // in PRODUCT for -XX:SyncKnobs=Verbose=1 -#ifndef PRODUCT - void verify(); - void print(); -#endif void enter(TRAPS); void exit(bool not_suspended, TRAPS); diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index a596a4e7b57..c3cd396e6f6 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -1879,23 +1879,6 @@ void ObjectSynchronizer::sanity_checks(const bool verbose, #ifndef PRODUCT -// Verify all monitors in the monitor cache, the verification is weak. -void ObjectSynchronizer::verify() { - PaddedEnd * block = - (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); - while (block != NULL) { - assert(block->object() == CHAINMARKER, "must be a block header"); - for (int i = 1; i < _BLOCKSIZE; i++) { - ObjectMonitor* mid = (ObjectMonitor *)(block + i); - oop object = (oop)mid->object(); - if (object != NULL) { - mid->verify(); - } - } - block = (PaddedEnd *)block->FreeNext; - } -} - // Check if monitor belongs to the monitor cache // The list is grow-only so it's *relatively* safe to traverse // the list of extant blocks without taking a lock. diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index af242e8557a..16ba567815a 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -141,7 +141,6 @@ class ObjectSynchronizer : AllStatic { static void sanity_checks(const bool verbose, const unsigned int cache_line_size, int *error_cnt_ptr, int *warning_cnt_ptr); - static void verify() PRODUCT_RETURN; static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0; private: From 2fd9f38a31d5217f59c06ee58e30437034ff4488 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 12 Dec 2016 16:16:27 +0300 Subject: [PATCH 68/86] 8171090: Convert VMStruct_test to GTest Reviewed-by: iignatyev --- hotspot/src/share/vm/runtime/vmStructs.cpp | 58 +++++------------ hotspot/src/share/vm/runtime/vmStructs.hpp | 10 ++- .../share/vm/utilities/internalVMTests.cpp | 3 - .../test/native/runtime/test_vmStructs.cpp | 64 +++++++++++++++++++ 4 files changed, 89 insertions(+), 46 deletions(-) create mode 100644 hotspot/test/native/runtime/test_vmStructs.cpp diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 55411ccfdd8..4fbbeb8c8a7 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -3042,6 +3042,10 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { GENERATE_VM_STRUCT_LAST_ENTRY() }; +size_t VMStructs::localHotSpotVMStructsLength() { + return sizeof(localHotSpotVMStructs) / sizeof(VMStructEntry); +} + VMTypeEntry VMStructs::localHotSpotVMTypes[] = { VM_TYPES(GENERATE_VM_TYPE_ENTRY, @@ -3104,6 +3108,10 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_VM_TYPE_LAST_ENTRY() }; +size_t VMStructs::localHotSpotVMTypesLength() { + return sizeof(localHotSpotVMTypes) / sizeof(VMTypeEntry); +} + VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { VM_INT_CONSTANTS(GENERATE_VM_INT_CONSTANT_ENTRY, @@ -3146,6 +3154,10 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { GENERATE_VM_INT_CONSTANT_LAST_ENTRY() }; +size_t VMStructs::localHotSpotVMIntConstantsLength() { + return sizeof(localHotSpotVMIntConstants) / sizeof(VMIntConstantEntry); +} + VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { VM_LONG_CONSTANTS(GENERATE_VM_LONG_CONSTANT_ENTRY, @@ -3175,6 +3187,10 @@ VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() }; +size_t VMStructs::localHotSpotVMLongConstantsLength() { + return sizeof(localHotSpotVMLongConstants) / sizeof(VMLongConstantEntry); +} + // This is used both to check the types of referenced fields and, in // debug builds, to ensure that all of the field types are present. void @@ -3466,45 +3482,3 @@ VMStructs::findType(const char* typeName) { void vmStructs_init() { debug_only(VMStructs::init()); } - -#ifndef PRODUCT -void VMStructs::test() { - // Make sure last entry in the each array is indeed the correct end marker. - // The reason why these are static is to make sure they are zero initialized. - // Putting them on the stack will leave some garbage in the padding of some fields. - static VMStructEntry struct_last_entry = GENERATE_VM_STRUCT_LAST_ENTRY(); - assert(memcmp(&localHotSpotVMStructs[(sizeof(localHotSpotVMStructs) / sizeof(VMStructEntry)) - 1], - &struct_last_entry, - sizeof(VMStructEntry)) == 0, "Incorrect last entry in localHotSpotVMStructs"); - - static VMTypeEntry type_last_entry = GENERATE_VM_TYPE_LAST_ENTRY(); - assert(memcmp(&localHotSpotVMTypes[sizeof(localHotSpotVMTypes) / sizeof(VMTypeEntry) - 1], - &type_last_entry, - sizeof(VMTypeEntry)) == 0, "Incorrect last entry in localHotSpotVMTypes"); - - static VMIntConstantEntry int_last_entry = GENERATE_VM_INT_CONSTANT_LAST_ENTRY(); - assert(memcmp(&localHotSpotVMIntConstants[sizeof(localHotSpotVMIntConstants) / sizeof(VMIntConstantEntry) - 1], - &int_last_entry, - sizeof(VMIntConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMIntConstants"); - - static VMLongConstantEntry long_last_entry = GENERATE_VM_LONG_CONSTANT_LAST_ENTRY(); - assert(memcmp(&localHotSpotVMLongConstants[sizeof(localHotSpotVMLongConstants) / sizeof(VMLongConstantEntry) - 1], - &long_last_entry, - sizeof(VMLongConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMLongConstants"); - - - // Check for duplicate entries in type array - for (int i = 0; localHotSpotVMTypes[i].typeName != NULL; i++) { - for (int j = i + 1; localHotSpotVMTypes[j].typeName != NULL; j++) { - if (strcmp(localHotSpotVMTypes[i].typeName, localHotSpotVMTypes[j].typeName) == 0) { - tty->print_cr("Duplicate entries for '%s'", localHotSpotVMTypes[i].typeName); - assert(false, "Duplicate types in localHotSpotVMTypes array"); - } - } - } -} - -void VMStructs_test() { - VMStructs::test(); -} -#endif diff --git a/hotspot/src/share/vm/runtime/vmStructs.hpp b/hotspot/src/share/vm/runtime/vmStructs.hpp index 4f9f31dcd3e..18ea1500c3a 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.hpp +++ b/hotspot/src/share/vm/runtime/vmStructs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -107,20 +107,28 @@ public: // The last entry is identified over in the serviceability agent by // the fact that it has a NULL fieldName static VMStructEntry localHotSpotVMStructs[]; + // The function to get localHotSpotVMStructs length + static size_t localHotSpotVMStructsLength(); // The last entry is identified over in the serviceability agent by // the fact that it has a NULL typeName static VMTypeEntry localHotSpotVMTypes[]; + // The function to get localHotSpotVMTypes length + static size_t localHotSpotVMTypesLength(); // Table of integer constants required by the serviceability agent. // The last entry is identified over in the serviceability agent by // the fact that it has a NULL typeName static VMIntConstantEntry localHotSpotVMIntConstants[]; + // The function to get localHotSpotVMIntConstants length + static size_t localHotSpotVMIntConstantsLength(); // Table of long constants required by the serviceability agent. // The last entry is identified over in the serviceability agent by // the fact that it has a NULL typeName static VMLongConstantEntry localHotSpotVMLongConstants[]; + // The function to get localHotSpotVMIntConstants length + static size_t localHotSpotVMLongConstantsLength(); /** * Table of addresses. diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index eae11ff1528..a757c1bc859 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -49,9 +49,6 @@ void InternalVMTests::run() { run_unit_test(GCTimer_test); run_unit_test(ObjectMonitor_test); run_unit_test(DirectivesParser_test); -#if INCLUDE_VM_STRUCTS - run_unit_test(VMStructs_test); -#endif tty->print_cr("All internal VM tests passed"); } diff --git a/hotspot/test/native/runtime/test_vmStructs.cpp b/hotspot/test/native/runtime/test_vmStructs.cpp new file mode 100644 index 00000000000..ed3f82ac66a --- /dev/null +++ b/hotspot/test/native/runtime/test_vmStructs.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "runtime/vmStructs.hpp" +#include "utilities/macros.hpp" +#include "unittest.hpp" + +#if INCLUDE_VM_STRUCTS +TEST(VMStructs, last_entries) { + // Make sure last entry in the each array is indeed the correct end marker. + // The reason why these are static is to make sure they are zero initialized. + // Putting them on the stack will leave some garbage in the padding of some fields. + static VMStructEntry struct_last_entry = GENERATE_VM_STRUCT_LAST_ENTRY(); + EXPECT_EQ(0, memcmp(&VMStructs::localHotSpotVMStructs[VMStructs::localHotSpotVMStructsLength() - 1], + &struct_last_entry, + sizeof(VMStructEntry))) << "Incorrect last entry in localHotSpotVMStructs"; + + static VMTypeEntry type_last_entry = GENERATE_VM_TYPE_LAST_ENTRY(); + EXPECT_EQ(0, memcmp(&VMStructs::localHotSpotVMTypes[VMStructs::localHotSpotVMTypesLength() - 1], + &type_last_entry, + sizeof(VMTypeEntry))) << "Incorrect last entry in localHotSpotVMTypes"; + + static VMIntConstantEntry int_last_entry = GENERATE_VM_INT_CONSTANT_LAST_ENTRY(); + EXPECT_EQ(0, memcmp(&VMStructs::localHotSpotVMIntConstants[VMStructs::localHotSpotVMIntConstantsLength() - 1], + &int_last_entry, + sizeof(VMIntConstantEntry))) << "Incorrect last entry in localHotSpotVMIntConstants"; + + static VMLongConstantEntry long_last_entry = GENERATE_VM_LONG_CONSTANT_LAST_ENTRY(); + EXPECT_EQ(0, memcmp(&VMStructs::localHotSpotVMLongConstants[VMStructs::localHotSpotVMLongConstantsLength() - 1], + &long_last_entry, + sizeof(VMLongConstantEntry))) << "Incorrect last entry in localHotSpotVMLongConstants"; +} + +TEST(VMStructs, VMTypes_duplicates) { + // Check for duplicate entries in type array + for (int i = 0; VMStructs::localHotSpotVMTypes[i].typeName != NULL; i++) { + for (int j = i + 1; VMStructs::localHotSpotVMTypes[j].typeName != NULL; j++) { + EXPECT_STRNE(VMStructs::localHotSpotVMTypes[i].typeName, VMStructs::localHotSpotVMTypes[j].typeName) + << "Duplicate entries on indexes " << i << " and " << j; + } + } +} +#endif From f509f32e037ee4bf91d1d2373b4b697b5cd47afd Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Mon, 20 Mar 2017 16:01:33 +0300 Subject: [PATCH 69/86] 8167196: WhiteBox methods should throw an exception if used with inappropriate collector Reviewed-by: shade, dfazunen --- hotspot/src/share/vm/prims/whitebox.cpp | 95 ++++++++++++++++--------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 0f7bc97a186..3a8080c2f13 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -359,52 +359,76 @@ WB_END #if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - oop result = JNIHandles::resolve(obj); - const HeapRegion* hr = g1->heap_region_containing(result); - return hr->is_humongous(); + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + oop result = JNIHandles::resolve(obj); + const HeapRegion* hr = g1->heap_region_containing(result); + return hr->is_humongous(); + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1IsHumongous: G1 GC is not enabled"); WB_END WB_ENTRY(jboolean, WB_G1BelongsToHumongousRegion(JNIEnv* env, jobject o, jlong addr)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - const HeapRegion* hr = g1->heap_region_containing((void*) addr); - return hr->is_humongous(); + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + const HeapRegion* hr = g1->heap_region_containing((void*) addr); + return hr->is_humongous(); + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToHumongousRegion: G1 GC is not enabled"); WB_END WB_ENTRY(jboolean, WB_G1BelongsToFreeRegion(JNIEnv* env, jobject o, jlong addr)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - const HeapRegion* hr = g1->heap_region_containing((void*) addr); - return hr->is_free(); + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + const HeapRegion* hr = g1->heap_region_containing((void*) addr); + return hr->is_free(); + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToFreeRegion: G1 GC is not enabled"); WB_END WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - size_t nr = g1->max_regions(); - return (jlong)nr; + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + size_t nr = g1->max_regions(); + return (jlong)nr; + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumMaxRegions: G1 GC is not enabled"); WB_END WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - size_t nr = g1->num_free_regions(); - return (jlong)nr; + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + size_t nr = g1->num_free_regions(); + return (jlong)nr; + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumFreeRegions: G1 GC is not enabled"); WB_END WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o)) - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - return g1h->concurrent_mark()->cmThread()->during_cycle(); + if (UseG1GC) { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + return g1h->concurrent_mark()->cmThread()->during_cycle(); + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1InConcurrentMark: G1 GC is not enabled"); WB_END WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o)) - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (!g1h->concurrent_mark()->cmThread()->during_cycle()) { - g1h->collect(GCCause::_wb_conc_mark); - return true; + if (UseG1GC) { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + if (!g1h->concurrent_mark()->cmThread()->during_cycle()) { + g1h->collect(GCCause::_wb_conc_mark); + return true; + } + return false; } - return false; + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1StartMarkCycle: G1 GC is not enabled"); WB_END WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) - return (jint)HeapRegion::GrainBytes; + if (UseG1GC) { + return (jint)HeapRegion::GrainBytes; + } + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1RegionSize: G1 GC is not enabled"); WB_END WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o)) @@ -413,7 +437,7 @@ WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o)) return ParallelScavengeHeap::heap()->gens()->virtual_spaces()->alignment(); } #endif // INCLUDE_ALL_GCS - THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled"); + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled"); WB_END WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o)) @@ -422,15 +446,20 @@ WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o)) return ParallelScavengeHeap::heap()->generation_alignment(); } #endif // INCLUDE_ALL_GCS - THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled"); + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled"); WB_END WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env)) - ResourceMark rm(THREAD); - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - MemoryUsage usage = g1h->get_auxiliary_data_memory_usage(); - Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); - return JNIHandles::make_local(env, h()); +#if INCLUDE_ALL_GCS + if (UseG1GC) { + ResourceMark rm(THREAD); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + MemoryUsage usage = g1h->get_auxiliary_data_memory_usage(); + Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); + return JNIHandles::make_local(env, h()); + } +#endif // INCLUDE_ALL_GCS + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled"); WB_END class OldRegionsLivenessClosure: public HeapRegionClosure { @@ -475,7 +504,7 @@ class OldRegionsLivenessClosure: public HeapRegionClosure { WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness)) if (!UseG1GC) { - THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "WB_G1GetMixedGCInfo: G1 is not enabled"); + THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1GetMixedGCInfo: G1 GC is not enabled"); } if (liveness < 0) { THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative"); @@ -492,8 +521,6 @@ WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness)) return (jlongArray) JNIHandles::make_local(env, result); WB_END - - #endif // INCLUDE_ALL_GCS #if INCLUDE_NMT From d405f1648b790dfe45c85d48f81fdbc3efb62b88 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 22 Mar 2017 13:42:45 -0700 Subject: [PATCH 70/86] 8177046: Update Graal Update Graal, make appropriate changes to AOT, and the build system. Reviewed-by: kvn --- hotspot/make/CompileTools.gmk | 7 +- .../Gensrc-jdk.internal.vm.compiler.gmk | 1 - .../jaotc/binformat/BinaryContainer.java | 23 +- .../src/jdk/tools/jaotc/AOTBackend.java | 28 +- .../jdk/tools/jaotc/AOTCompilationTask.java | 12 +- .../src/jdk/tools/jaotc/AOTCompiler.java | 10 +- .../src/jdk/tools/jaotc/DataBuilder.java | 4 +- .../src/jdk/tools/jaotc/Main.java | 72 +- .../.mx.graal/suite.py | 84 +- .../share/classes/module-info.java | 1 + .../api/collections/CollectionsProvider.java | 57 - .../test/AllocationInstrumentationTest.java | 146 --- .../test/DeoptimizeDirectiveTest.java | 2 +- .../test/IsMethodInlineDirectiveTest.java | 125 -- .../test/LockInstrumentationTest.java | 133 --- .../test/RootNameDirectiveTest.java | 175 --- .../api/directives/test/TinyInstrumentor.java | 242 ---- .../api/directives/GraalDirectives.java | 65 -- .../compiler/api/replacements/Snippet.java | 9 + .../test/AArch64MacroAssemblerTest.java | 2 +- .../aarch64/test/TestProtectedAssembler.java | 8 +- .../compiler/asm/aarch64/AArch64Address.java | 32 +- .../asm/aarch64/AArch64Assembler.java | 37 +- .../asm/aarch64/AArch64MacroAssembler.java | 203 +++- .../compiler/asm/amd64/AMD64Address.java | 12 + .../compiler/asm/amd64/AMD64Assembler.java | 45 +- .../asm/amd64/AMD64MacroAssembler.java | 442 ++++++- .../compiler/asm/sparc/SPARCAssembler.java | 4 +- .../compiler/asm/test/AssemblerTest.java | 18 +- .../src/org/graalvm/compiler/asm/Buffer.java | 2 + .../compiler/code/CompilationResult.java | 8 +- .../SourceStackTraceBailoutException.java | 2 +- .../core/aarch64/AArch64AddressNode.java | 7 + .../AArch64ArithmeticLIRGenerator.java | 81 +- .../core/aarch64/AArch64LIRGenerator.java | 60 +- .../core/aarch64/AArch64MoveFactory.java | 32 +- .../core/aarch64/AArch64NodeMatchRules.java | 19 + .../core/amd64/test/AMD64AllocatorTest.java | 4 +- .../core/amd64/test/MatchRuleTest.java | 19 +- .../core/amd64/AMD64AddressLowering.java | 2 +- .../compiler/core/amd64/AMD64AddressNode.java | 7 + .../amd64/AMD64ArithmeticLIRGenerator.java | 4 +- .../core/amd64/AMD64LIRGenerator.java | 63 +- .../compiler/core/amd64/AMD64MoveFactory.java | 22 +- .../core/amd64/AMD64MoveFactoryBase.java | 9 +- .../core/amd64/AMD64NodeMatchRules.java | 180 ++- .../core/amd64/AMD64SuitesProvider.java | 7 +- .../common/CancellationBailoutException.java | 41 + .../core/common/CollectionsFactory.java | 132 --- .../core/common}/CompressEncoding.java | 35 +- .../compiler/core/common/GraalOptions.java | 176 ++- .../core/common/LinkedIdentityHashMap.java | 285 ----- .../core/common/LocationIdentity.java | 37 +- .../compiler/core/common}/NumUtil.java | 43 +- .../common/PermanentBailoutException.java | 2 +- .../common/RetryableBailoutException.java | 2 +- .../alloc/RegisterAllocationConfig.java | 28 +- .../core/common/cfg/AbstractBlockBase.java | 33 +- .../common/cfg/AbstractControlFlowGraph.java | 2 + .../compiler/core/common/cfg/CFGVerifier.java | 15 +- .../compiler/core/common/cfg/Loop.java | 5 + .../common/spi/ConstantFieldProvider.java | 4 + .../common/spi/JavaConstantFieldProvider.java | 8 +- .../common/type/AbstractPointerStamp.java | 40 +- .../core/common/type/ArithmeticOpTable.java | 38 +- .../core/common/type/ArithmeticStamp.java | 8 +- .../compiler/core/common/type/FloatStamp.java | 4 - .../core/common/type/IntegerStamp.java | 331 ++++-- .../core/common/type/StampFactory.java | 61 +- .../compiler/core/common/util/ArrayMap.java | 118 -- .../core/common/util/CompilationAlarm.java | 89 +- .../compiler/core/common/util/IntList.java | 12 +- .../compiler/core/common/util/ModuleAPI.java | 56 + .../core/common/util/ReversedList.java} | 41 +- .../compiler/core/common/util/Util.java | 79 +- .../core/match/processor/MatchProcessor.java | 31 +- .../core/sparc/test/SPARCAllocatorTest.java | 15 +- .../sparc/SPARCArithmeticLIRGenerator.java | 119 +- .../core/sparc/SPARCImmediateAddressNode.java | 15 + .../core/sparc/SPARCIndexedAddressNode.java | 7 + .../core/sparc/SPARCLIRGenerator.java | 34 +- .../compiler/core/sparc/SPARCMoveFactory.java | 32 +- .../core/sparc/SPARCNodeMatchRules.java | 49 + .../core/sparc/SPARCSuitesProvider.java | 5 +- .../core/test/BoxingEliminationTest.java | 4 +- .../core/test/CheckGraalInvariants.java | 263 ++++- .../core/test/CommonedConstantsTest.java | 4 +- .../core/test/CompareCanonicalizerTest2.java | 77 ++ .../compiler/core/test/ConditionTest.java | 2 + ...lEliminationLoadFieldConstantFoldTest.java | 289 ----- .../test/ConditionalEliminationMulTest.java | 7 +- .../test/ConditionalEliminationTest10.java | 42 +- .../test/ConditionalEliminationTest11.java | 74 +- .../test/ConditionalEliminationTest12.java | 84 ++ .../test/ConditionalEliminationTest13.java | 323 ++++++ .../test/ConditionalEliminationTest2.java | 4 +- .../test/ConditionalEliminationTest3.java | 2 + .../test/ConditionalEliminationTest5.java | 56 +- .../test/ConditionalEliminationTest7.java | 2 + .../test/ConditionalEliminationTestBase.java | 40 +- .../core/test/CooperativePhaseTest.java | 49 +- .../core/test/DontReuseArgumentSpaceTest.java | 9 +- .../compiler/core/test/EnumSwitchTest.java | 5 +- .../core/test/FinalizableSubclassTest.java | 5 +- .../compiler/core/test/GraalCompilerTest.java | 363 ++++-- .../compiler/core/test/GraphEncoderTest.java | 2 +- .../test/GuardEliminationCornerCasesTest.java | 117 -- .../core/test/GuardedIntrinsicTest.java | 14 +- .../compiler/core/test/HashCodeTest.java | 6 +- .../core/test/IfCanonicalizerTest.java | 4 +- .../core/test/InfopointReasonTest.java | 17 +- .../test/InstalledCodeInvalidationTest.java | 7 +- .../core/test/InterfaceMethodHandleTest.java | 110 +- .../core/test/LockEliminationTest.java | 2 - .../compiler/core/test/LongNodeChainTest.java | 5 +- .../core/test/MemoryArithmeticTest.java | 5 +- .../core/test/MemoryScheduleTest.java | 102 +- .../test/MethodHandleEagerResolution.java | 2 + .../core/test/NodePropertiesTest.java | 4 +- .../core/test/OptionsVerifierTest.java | 26 +- .../core/test/PushNodesThroughPiTest.java | 4 +- .../core/test/ReadAfterCheckCastTest.java | 2 - .../core/test/ReentrantBlockIteratorTest.java | 2 +- .../compiler/core/test/SimpleCFGTest.java | 12 +- .../core/test/StaticInterfaceFieldTest.java | 18 +- .../compiler/core/test/TypeSystemTest.java | 6 +- .../compiler/core/test/TypeWriterTest.java | 2 +- .../core/test/UnbalancedMonitorsTest.java | 328 +++--- .../core/test/UnsafeReadEliminationTest.java | 24 +- .../core/test/UnsafeVirtualizationTest.java | 94 ++ .../core/test/VerifyBailoutUsageTest.java | 9 +- .../core/test/VerifyDebugUsageTest.java | 5 +- .../core/test/VerifyVirtualizableTest.java | 5 +- .../core/test/backend/BackendTest.java | 4 +- .../core/test/debug/MethodMetricsTest.java | 48 +- .../MethodMetricsTestInterception01.java | 23 +- .../MethodMetricsTestInterception02.java | 23 +- .../test/debug/VerifyMethodMetricsTest.java | 8 +- .../test/deopt/SafepointRethrowDeoptTest.java | 2 +- .../compiler/core/test/ea/EATestBase.java | 2 +- .../core/test/ea/EscapeAnalysisTest.java | 129 ++- .../core/test/ea/PEAReadEliminationTest.java | 14 +- .../NestedLoopEffectsPhaseComplexityTest.java | 154 +++ .../test/inlining/RecursiveInliningTest.java | 206 ---- .../core/test/tutorial/InvokeGraal.java | 10 +- .../core/test/tutorial/StaticAnalysis.java | 5 +- .../graalvm/compiler/core/GraalCompiler.java | 75 +- .../compiler/core/GraalCompilerOptions.java | 18 +- .../GraalDebugInitializationParticipant.java | 29 +- .../compiler/core/gen/DebugInfoBuilder.java | 24 +- .../compiler/core/gen/NodeLIRBuilder.java | 44 +- .../compiler/core/gen/NodeMatchRules.java | 4 + .../compiler/core/match/MatchContext.java | 12 +- .../compiler/core/match/MatchPattern.java | 28 +- .../core/match/MatchRuleRegistry.java | 37 +- .../compiler/core/match/MatchStatement.java | 4 +- .../phases/CoreCompilerConfiguration.java | 26 +- .../phases/EconomyCompilerConfiguration.java | 19 +- .../compiler/core/phases/EconomyHighTier.java | 5 +- .../compiler/core/phases/EconomyLowTier.java | 5 +- .../compiler/core/phases/EconomyMidTier.java | 5 +- .../phases/GraphChangeMonitoringPhase.java | 26 +- .../compiler/core/phases/HighTier.java | 46 +- .../graalvm/compiler/core/phases/LowTier.java | 39 +- .../graalvm/compiler/core/phases/MidTier.java | 56 +- .../graalvm/compiler/core/target/Backend.java | 13 +- .../compiler/debug/test/DebugTimerTest.java | 76 +- .../graalvm/compiler/debug/Assertions.java | 40 + .../src/org/graalvm/compiler/debug/Debug.java | 35 +- .../graalvm/compiler/debug/DebugConfig.java | 7 + .../compiler/debug/DebugConfigCustomizer.java | 11 +- .../compiler/debug/DebugDumpHandler.java | 8 + .../compiler/debug/DebugEnvironment.java | 73 +- .../compiler/debug/DelegatingDebugConfig.java | 6 + .../graalvm/compiler/debug/Fingerprint.java | 16 +- .../compiler/debug/GraalDebugConfig.java | 186 +-- .../src/org/graalvm/compiler/debug/TTY.java | 17 +- .../compiler/debug/internal/DebugScope.java | 34 +- .../debug/internal/DebugValuesPrinter.java | 61 +- .../internal/method/MethodMetricsImpl.java | 4 +- .../method/MethodMetricsInlineeScopeInfo.java | 9 +- .../internal/method/MethodMetricsPrinter.java | 16 +- .../method/MethodMetricsRootScopeInfo.java | 15 +- .../compiler/graph/test/GraphTest.java} | 14 +- .../compiler/graph/test/NodeMapTest.java | 16 +- .../compiler/graph/test/NodeUsagesTests.java | 26 +- .../graph/test/NodeValidationChecksTest.java | 6 +- .../graph/test/TypedNodeIteratorTest.java | 22 +- .../graph/test/TypedNodeIteratorTest2.java | 6 +- .../graalvm/compiler/graph/CachedGraph.java | 5 +- .../graph/DefaultNodeCollectionsProvider.java | 57 - .../src/org/graalvm/compiler/graph/Edges.java | 4 +- .../src/org/graalvm/compiler/graph/Graph.java | 250 ++-- .../src/org/graalvm/compiler/graph/Node.java | 162 +-- .../org/graalvm/compiler/graph/NodeClass.java | 154 ++- .../graph/NodeCollectionsProvider.java | 60 - .../org/graalvm/compiler/graph/NodeMap.java | 164 ++- .../graalvm/compiler/graph/NodeNodeMap.java | 111 -- .../org/graalvm/compiler/graph/NodeStack.java | 10 +- .../compiler/graph/NodeUsageIterable.java | 21 + .../graalvm/compiler/graph/NodeWorkList.java | 23 +- .../graph/TypedGraphNodeIterator.java | 6 +- .../compiler/graph/spi/CanonicalizerTool.java | 3 + .../aarch64/AArch64HotSpotBackend.java | 92 +- .../aarch64/AArch64HotSpotBackendFactory.java | 9 +- .../AArch64HotSpotForeignCallsProvider.java | 23 +- ...tSpotJumpToExceptionHandlerInCallerOp.java | 21 +- .../aarch64/AArch64HotSpotLIRGenerator.java | 40 +- .../AArch64HotSpotLoweringProvider.java | 9 +- .../hotspot/aarch64/AArch64HotSpotMove.java | 49 +- .../aarch64/AArch64HotSpotMoveFactory.java | 6 +- .../aarch64/AArch64HotSpotNodeLIRBuilder.java | 17 - .../AArch64HotSpotPatchReturnAddressOp.java | 7 +- ...Arch64HotSpotRegisterAllocationConfig.java | 4 +- .../aarch64/AArch64HotSpotSafepointOp.java | 8 +- .../aarch64/AArch64RawNativeCallNode.java | 117 ++ .../amd64/test/CompressedNullCheckTest.java | 47 +- .../hotspot/amd64/test/StubAVXTest.java | 25 +- .../amd64/AMD64DeoptimizationStub.java | 60 - .../amd64/AMD64HotSpotAddressLowering.java | 64 +- .../AMD64HotSpotArithmeticLIRGenerator.java | 10 +- .../hotspot/amd64/AMD64HotSpotBackend.java | 23 +- .../amd64/AMD64HotSpotBackendFactory.java | 24 +- ...4HotSpotEnterUnpackFramesStackFrameOp.java | 124 -- .../AMD64HotSpotForeignCallsProvider.java | 42 +- .../amd64/AMD64HotSpotLIRGenerator.java | 114 +- ...4HotSpotLeaveUnpackFramesStackFrameOp.java | 87 -- .../amd64/AMD64HotSpotLoadConfigValueOp.java | 2 +- .../amd64/AMD64HotSpotLoweringProvider.java | 16 +- .../hotspot/amd64/AMD64HotSpotMove.java | 34 +- .../amd64/AMD64HotSpotMoveFactory.java | 4 +- .../amd64/AMD64HotSpotNodeLIRBuilder.java | 15 - .../AMD64HotSpotRegisterAllocationConfig.java | 4 +- .../amd64/AMD64HotSpotSafepointOp.java | 8 +- .../amd64/AMD64HotSpotSuitesProvider.java | 7 +- .../compiler/hotspot/amd64/AMD64MathStub.java | 5 +- .../hotspot/amd64/AMD64UncommonTrapStub.java | 61 - .../sparc/SPARCDeoptimizationStub.java | 60 - .../hotspot/sparc/SPARCHotSpotBackend.java | 42 +- .../sparc/SPARCHotSpotBackendFactory.java | 2 +- ...CHotSpotEnterUnpackFramesStackFrameOp.java | 125 -- .../SPARCHotSpotForeignCallsProvider.java | 30 +- .../sparc/SPARCHotSpotLIRGenerator.java | 174 +-- ...CHotSpotLeaveUnpackFramesStackFrameOp.java | 80 -- .../hotspot/sparc/SPARCHotSpotMove.java | 16 +- .../sparc/SPARCHotSpotMoveFactory.java | 6 +- .../sparc/SPARCHotSpotNodeLIRBuilder.java | 14 - .../SPARCHotSpotRegisterAllocationConfig.java | 4 +- .../sparc/SPARCHotSpotStrategySwitchOp.java | 9 +- .../hotspot/sparc/SPARCUncommonTrapStub.java | 60 - .../test/AheadOfTimeCompilationTest.java | 67 +- .../test/ArrayCopyIntrinsificationTest.java | 12 +- .../hotspot/test/CheckGraalIntrinsics.java | 5 +- .../hotspot/test/CompileTheWorldTest.java | 16 +- .../test/ConstantPoolSubstitutionsTests.java | 263 +++-- .../compiler/hotspot/test/DataPatchTest.java | 3 +- .../hotspot/test/ExplicitExceptionTest.java | 6 +- .../hotspot/test/GraalOSRLockTest.java | 649 ++++++++++- .../compiler/hotspot/test/GraalOSRTest.java | 60 +- .../hotspot/test/GraalOSRTestBase.java | 58 +- .../test/HotSpotGraalCompilerTest.java | 4 +- .../test/HotSpotNodeSubstitutionsTest.java | 4 +- .../test/HotSpotResolvedJavaFieldTest.java | 29 +- .../test/InstalledCodeExecuteHelperTest.java | 10 +- .../test/LoadJavaMirrorWithKlassTest.java | 9 +- .../hotspot/test/MemoryUsageBenchmark.java | 14 +- .../hotspot/test/TestIntrinsicCompiles.java | 14 +- .../test/WriteBarrierVerificationTest.java | 9 +- .../hotspot/AOTGraalHotSpotVMConfig.java | 12 +- .../compiler/hotspot/BootstrapWatchDog.java | 30 +- .../compiler/hotspot/CompilationCounters.java | 19 +- .../hotspot/CompilationStatistics.java | 20 +- .../compiler/hotspot/CompilationTask.java | 60 +- .../compiler/hotspot/CompilationWatchDog.java | 73 +- .../compiler/hotspot/CompileTheWorld.java | 143 +-- .../hotspot/CompileTheWorldOptions.java | 35 +- .../hotspot/CompilerConfigurationFactory.java | 23 +- .../hotspot/GraalHotSpotVMConfig.java | 27 +- .../compiler/hotspot/HotSpotBackend.java | 61 +- .../compiler/hotspot/HotSpotCounterOp.java | 7 +- .../hotspot/HotSpotForeignCallLinkage.java | 5 + .../HotSpotForeignCallLinkageImpl.java | 18 +- .../hotspot/HotSpotGraalCompiler.java | 85 +- .../hotspot/HotSpotGraalCompilerFactory.java | 201 +--- .../HotSpotGraalJVMCIServiceLocator.java | 32 +- .../hotspot/HotSpotGraalOptionValues.java | 159 +++ .../compiler/hotspot/HotSpotGraalRuntime.java | 103 +- .../hotspot/HotSpotGraalRuntimeProvider.java | 9 +- .../hotspot/HotSpotGraalVMEventListener.java | 2 +- .../compiler/hotspot/HotSpotHostBackend.java | 17 +- .../hotspot/HotSpotInstructionProfiling.java | 4 +- .../hotspot/HotSpotLIRGenerationResult.java | 9 +- .../compiler/hotspot/HotSpotLIRGenerator.java | 92 +- .../hotspot/HotSpotNodeLIRBuilder.java | 4 - .../hotspot/HotSpotReferenceMapBuilder.java | 2 +- .../hotspot/HotSpotReplacementsImpl.java | 5 +- .../hotspot/HotSpotTTYStreamProvider.java | 8 +- .../compiler/hotspot/JVMCIVersionCheck.java | 14 +- ...mOption.java => PrintStreamOptionKey.java} | 84 +- .../hotspot/debug/BenchmarkCounters.java | 75 +- .../meta/DefaultHotSpotLoweringProvider.java | 134 ++- .../meta/HotSpotAOTProfilingPlugin.java | 35 +- .../meta/HotSpotConstantFieldProvider.java | 7 +- .../meta/HotSpotForeignCallsProvider.java | 8 + .../meta/HotSpotForeignCallsProviderImpl.java | 31 +- .../HotSpotGraalConstantFieldProvider.java | 175 +-- .../meta/HotSpotGraphBuilderPlugins.java | 47 +- .../meta/HotSpotHostForeignCallsProvider.java | 110 +- .../meta/HotSpotInvocationPlugins.java | 2 +- .../hotspot/meta/HotSpotLoweringProvider.java | 3 +- .../hotspot/meta/HotSpotNodePlugin.java | 19 +- .../hotspot/meta/HotSpotProfilingPlugin.java | 32 +- .../hotspot/meta/HotSpotSuitesProvider.java | 40 +- .../meta/HotSpotWordOperationPlugin.java | 6 - .../hotspot/nodes/BeginLockScopeNode.java | 6 + .../hotspot/nodes/CompressionNode.java | 11 +- ...DeoptimizationFetchUnrollInfoCallNode.java | 90 -- .../hotspot/nodes/DimensionsNode.java | 2 +- .../nodes/DirectCompareAndSwapNode.java | 103 -- .../EnterUnpackFramesStackFrameNode.java | 77 -- .../nodes/GraalHotSpotVMConfigNode.java | 16 +- .../nodes/LeaveCurrentStackFrameNode.java | 64 - .../nodes/LeaveDeoptimizedStackFrameNode.java | 67 -- .../LeaveUnpackFramesStackFrameNode.java | 65 -- .../nodes/PushInterpreterFrameNode.java | 72 -- .../hotspot/nodes/SaveAllRegistersNode.java | 76 -- .../nodes/SnippetLocationProxyNode.java | 57 - .../hotspot/nodes/UncommonTrapCallNode.java | 94 -- .../aot/LoadConstantIndirectlyFixedNode.java | 6 +- .../nodes/aot/LoadConstantIndirectlyNode.java | 6 +- .../aot/LoadMethodCountersIndirectlyNode.java | 2 +- .../nodes/aot/ResolveConstantStubCall.java | 2 +- .../hotspot/nodes/profiling/ProfileNode.java | 8 +- .../hotspot/nodes/type/KlassPointerStamp.java | 2 +- .../nodes/type/MetaspacePointerStamp.java | 5 + .../hotspot/nodes/type/NarrowOopStamp.java | 2 +- .../phases/LoadJavaMirrorWithKlassPhase.java | 2 +- .../phases/OnStackReplacementPhase.java | 141 ++- .../phases/WriteBarrierAdditionPhase.java | 10 +- .../phases/WriteBarrierVerificationPhase.java | 32 +- .../hotspot/phases/aot/AOTInliningPolicy.java | 20 +- ...EliminateRedundantInitializationPhase.java | 4 +- .../profiling/FinalizeProfileNodesPhase.java | 20 +- .../replacements/AESCryptSubstitutions.java | 6 +- .../replacements/AssertionSnippets.java | 15 +- .../replacements/CRC32Substitutions.java | 15 +- .../CipherBlockChainingSubstitutions.java | 20 +- .../hotspot/replacements/ClassGetHubNode.java | 25 +- .../replacements/EncodedSymbolConstant.java | 2 +- .../replacements/HashCodeSnippets.java | 5 +- .../HotSpotClassSubstitutions.java | 23 +- .../replacements/HotSpotReplacementsUtil.java | 60 +- .../replacements/HotspotSnippetsOptions.java | 25 +- .../hotspot/replacements/HubGetClassNode.java | 17 +- .../replacements/IdentityHashCodeNode.java | 2 +- .../replacements/InstanceOfSnippets.java | 135 ++- .../replacements/KlassLayoutHelperNode.java | 13 +- .../LoadExceptionObjectSnippets.java | 20 +- .../hotspot/replacements/MonitorSnippets.java | 654 +++++++---- .../replacements/NewObjectSnippets.java | 266 +++-- .../hotspot/replacements/ObjectCloneNode.java | 4 +- .../replacements/SHA2Substitutions.java | 4 +- .../replacements/SHA5Substitutions.java | 4 +- .../replacements/SHASubstitutions.java | 4 +- .../replacements/StringToBytesSnippets.java | 5 +- .../replacements/ThreadSubstitutions.java | 5 +- .../replacements/TypeCheckSnippetUtils.java | 73 +- .../replacements/UnsafeLoadSnippets.java | 9 +- .../replacements/WriteBarrierSnippets.java | 99 +- .../aot/ResolveConstantSnippets.java | 5 +- .../arraycopy/ArrayCopySnippets.java | 267 +++-- .../arraycopy/UnsafeArrayCopySnippets.java | 21 +- .../ProbabilisticProfileSnippets.java | 5 +- .../profiling/ProfileSnippets.java | 5 +- .../stubs/ArrayStoreExceptionStub.java | 7 +- .../hotspot/stubs/ClassCastExceptionStub.java | 7 +- .../hotspot/stubs/CreateExceptionStub.java | 5 +- .../hotspot/stubs/DeoptimizationStub.java | 302 ----- .../hotspot/stubs/ExceptionHandlerStub.java | 34 +- .../hotspot/stubs/ForeignCallStub.java | 12 +- .../compiler/hotspot/stubs/NewArrayStub.java | 28 +- .../hotspot/stubs/NewInstanceStub.java | 35 +- .../stubs/NullPointerExceptionStub.java | 5 +- .../stubs/OutOfBoundsExceptionStub.java | 5 +- .../compiler/hotspot/stubs/SnippetStub.java | 59 +- .../graalvm/compiler/hotspot/stubs/Stub.java | 47 +- .../compiler/hotspot/stubs/StubOptions.java | 12 +- .../compiler/hotspot/stubs/StubUtil.java | 2 +- .../hotspot/stubs/UncommonTrapStub.java | 225 ---- .../stubs/UnwindExceptionToCallerStub.java | 39 +- .../compiler/hotspot/stubs/VerifyOopStub.java | 5 +- .../hotspot/word/MetaspacePointer.java | 11 - .../compiler/java/BciBlockMapping.java | 34 +- .../graalvm/compiler/java/BytecodeParser.java | 458 ++++---- .../compiler/java/BytecodeParserOptions.java | 21 +- .../java/ComputeLoopFrequenciesClosure.java | 18 +- .../compiler/java/DefaultSuitesProvider.java | 9 +- .../compiler/java/FrameStateBuilder.java | 10 +- .../compiler/java/JsrNotSupportedBailout.java | 2 +- .../compiler/java/SuitesProviderBase.java | 48 +- .../src/org/graalvm/compiler/jtt/JTTTest.java | 39 +- .../compiler/jtt/backend/ConstantPhiTest.java | 18 +- .../jtt/backend/LargeConstantSectionTest.java | 176 +-- .../compiler/jtt/bytecode/BC_instanceof.java | 16 + .../jtt/bytecode/BC_instanceof01.java | 9 +- .../compiler/jtt/except/BC_getfield1.java | 2 +- .../jtt/except/UntrustedInterfaces.java | 14 +- .../compiler/jtt/hotspot/Test6186134.java | 17 +- .../compiler/jtt/hotspot/Test6959129.java | 4 +- .../compiler/jtt/jdk/UnsafeAccess01.java | 27 +- .../jtt/jdk/Unsafe_compareAndSwap.java | 14 +- .../jdk/Unsafe_compareAndSwapNullCheck.java | 15 +- .../compiler/jtt/lang/LambdaEagerTest.java | 22 +- .../compiler/jtt/optimize/GuardMovement.java | 72 ++ .../compiler/jtt/optimize/NestedLoop_EA.java | 7 +- .../compiler/jtt/optimize/UnsafeDeopt.java | 32 +- .../compiler/jtt/optimize/VN_Double03.java} | 36 +- .../jtt/threads/Monitor_contended01.java | 4 +- .../jtt/threads/Monitor_notowner01.java | 4 +- .../compiler/jtt/threads/Monitorenter01.java | 4 +- .../compiler/jtt/threads/Monitorenter02.java | 4 +- .../compiler/jtt/threads/Object_wait01.java | 7 +- .../compiler/jtt/threads/Object_wait02.java | 6 +- .../compiler/jtt/threads/Object_wait03.java | 6 +- .../compiler/jtt/threads/Object_wait04.java | 9 +- .../jtt/threads/SynchronizedLoopExit01.java | 4 +- .../jtt/threads/Thread_isInterrupted02.java | 5 +- .../jtt/threads/Thread_isInterrupted03.java | 4 +- .../jtt/threads/Thread_isInterrupted05.java | 4 +- .../compiler/jtt/threads/Thread_join01.java | 4 +- .../compiler/jtt/threads/Thread_join02.java | 4 +- .../compiler/jtt/threads/Thread_join03.java | 4 +- .../compiler/jtt/threads/Thread_sleep01.java | 6 +- .../compiler/jtt/threads/Thread_yield01.java | 4 +- .../lir/aarch64/AArch64ArithmeticOp.java | 12 + .../lir/aarch64/AArch64ArrayEqualsOp.java | 235 ++++ .../lir/aarch64/AArch64BitManipulationOp.java | 10 +- .../lir/aarch64/AArch64BlockEndOp.java | 5 +- .../lir/aarch64/AArch64ByteSwapOp.java | 61 + .../compiler/lir/aarch64/AArch64CCall.java | 67 ++ .../compiler/lir/aarch64/AArch64Compare.java | 2 +- .../lir/aarch64/AArch64ControlFlow.java | 69 +- .../compiler/lir/aarch64/AArch64Move.java | 58 +- .../lir/aarch64/AArch64SignExtendOp.java | 2 +- .../compiler/lir/aarch64/AArch64Unary.java | 95 ++ .../compiler/lir/amd64/AMD64AddressValue.java | 12 + .../compiler/lir/amd64/AMD64Binary.java | 2 +- .../lir/amd64/AMD64BinaryConsumer.java | 2 +- .../compiler/lir/amd64/AMD64BlockEndOp.java | 5 +- .../compiler/lir/amd64/AMD64ControlFlow.java | 2 +- .../compiler/lir/amd64/AMD64FrameMap.java | 2 +- .../graalvm/compiler/lir/amd64/AMD64Move.java | 2 +- .../lir/amd64/AMD64SaveRegistersOp.java | 13 +- .../lir/amd64/AMD64StringIndexOfOp.java | 102 ++ .../lir/amd64/AMD64ZapRegistersOp.java | 5 +- .../phases/StackMoveOptimizationPhase.java | 6 +- .../lir/jtt/SPARCBranchBailoutTest.java | 2 +- .../compiler/lir/sparc/SPARCArithmetic.java | 34 +- .../lir/sparc/SPARCArrayEqualsOp.java | 30 +- .../lir/sparc/SPARCBitManipulationOp.java | 7 +- .../compiler/lir/sparc/SPARCBlockEndOp.java | 5 +- .../compiler/lir/sparc/SPARCByteSwapOp.java | 17 +- .../compiler/lir/sparc/SPARCControlFlow.java | 25 +- .../lir/sparc/SPARCFloatCompareOp.java | 12 +- .../lir/sparc/SPARCLIRInstruction.java | 2 +- .../compiler/lir/sparc/SPARCOP3Op.java | 19 +- .../compiler/lir/sparc/SPARCOPFOp.java | 18 +- .../lir/sparc/SPARCSaveRegistersOp.java | 13 +- .../TraceGlobalMoveResolutionMappingTest.java | 61 +- .../BailoutAndRestartBackendException.java | 26 +- .../compiler/lir/ControlFlowOptimizer.java | 6 +- .../compiler/lir/EdgeMoveOptimizer.java | 6 +- .../src/org/graalvm/compiler/lir/LIR.java | 10 +- .../graalvm/compiler/lir/LIRFrameState.java | 2 + .../graalvm/compiler/lir/LIRInstruction.java | 5 + .../compiler/lir/LIRIntrospection.java | 17 +- .../compiler/lir/NullCheckOptimizer.java | 4 +- .../lir/RedundantMoveElimination.java | 18 +- .../org/graalvm/compiler/lir/StandardOp.java | 142 +-- .../lir/alloc/OutOfRegistersException.java | 21 - .../lir/alloc/SaveCalleeSaveRegisters.java | 6 +- .../compiler/lir/alloc/lsra/Interval.java | 78 +- .../lir/alloc/lsra/IntervalWalker.java | 18 +- .../compiler/lir/alloc/lsra/LinearScan.java | 77 +- .../lsra/LinearScanAssignLocationsPhase.java | 9 +- .../LinearScanEliminateSpillMovePhase.java | 28 +- .../alloc/lsra/LinearScanIntervalDumper.java | 2 +- .../lsra/LinearScanLifetimeAnalysisPhase.java | 72 +- .../LinearScanOptimizeSpillPositionPhase.java | 2 +- .../lir/alloc/lsra/LinearScanPhase.java | 2 +- .../LinearScanRegisterAllocationPhase.java | 11 +- .../lsra/LinearScanResolveDataFlowPhase.java | 10 +- .../lir/alloc/lsra/LinearScanWalker.java | 52 +- .../compiler/lir/alloc/lsra/MoveResolver.java | 20 +- .../lsra/OptimizingLinearScanWalker.java | 16 +- .../compiler/lir/alloc/lsra/Range.java | 17 +- .../lir/alloc/lsra/RegisterVerifier.java | 17 +- .../SSALinearScanResolveDataFlowPhase.java | 6 +- .../DefaultTraceRegisterAllocationPolicy.java | 31 +- .../trace/GlobalLivenessAnalysisPhase.java | 330 ++++++ .../lir/alloc/trace/GlobalLivenessInfo.java | 199 ++++ .../lir/alloc/trace/TraceAllocationPhase.java | 16 +- .../lir/alloc/trace/TraceBuilderPhase.java | 22 +- .../trace/TraceGlobalMoveResolutionPhase.java | 71 +- .../alloc/trace/TraceGlobalMoveResolver.java | 26 +- .../trace/TraceRegisterAllocationPhase.java | 47 +- .../trace/TraceRegisterAllocationPolicy.java | 8 +- .../compiler/lir/alloc/trace/TraceUtil.java | 28 +- .../alloc/trace/TrivialTraceAllocator.java | 81 +- .../lir/alloc/trace/bu/BottomUpAllocator.java | 249 ++-- .../alloc/trace/lsra/RegisterVerifier.java | 17 +- .../lir/alloc/trace/lsra/TraceInterval.java | 66 +- .../lsra/TraceLinearScanAllocationPhase.java | 2 +- .../TraceLinearScanAssignLocationsPhase.java | 139 ++- ...raceLinearScanEliminateSpillMovePhase.java | 10 +- .../TraceLinearScanLifetimeAnalysisPhase.java | 149 ++- .../trace/lsra/TraceLinearScanPhase.java | 60 +- .../TraceLinearScanResolveDataFlowPhase.java | 103 +- .../trace/lsra/TraceLinearScanWalker.java | 127 +- .../trace/lsra/TraceLocalMoveResolver.java | 12 +- .../lir/asm/CompilationResultBuilder.java | 40 +- .../asm/CompilationResultBuilderFactory.java | 7 +- .../constopt/ConstantLoadOptimization.java | 12 +- .../compiler/lir/constopt/ConstantTree.java | 12 +- .../lir/constopt/ConstantTreeAnalyzer.java | 15 +- .../compiler/lir/dfa/LocationMarker.java | 4 +- .../compiler/lir/framemap/FrameMap.java | 4 +- .../lir/gen/ArithmeticLIRGenerator.java | 4 + .../compiler/lir/gen/LIRGenerator.java | 41 +- .../compiler/lir/gen/LIRGeneratorTool.java | 11 +- .../graalvm/compiler/lir/gen/PhiResolver.java | 8 +- .../lir/gen/VerifyingMoveFactory.java | 3 +- .../compiler/lir/phases/AllocationStage.java | 13 +- .../graalvm/compiler/lir/phases/LIRPhase.java | 12 +- .../PostAllocationOptimizationStage.java | 31 +- .../PreAllocationOptimizationStage.java | 5 +- .../lir/profiling/MethodProfilingPhase.java | 4 +- .../compiler/lir/profiling/MoveProfiler.java | 4 +- .../lir/profiling/MoveProfilingPhase.java | 8 +- .../org/graalvm/compiler/lir/ssa/SSAUtil.java | 17 +- .../graalvm/compiler/lir/ssa/SSAVerifier.java | 4 +- .../compiler/lir/ssi/FastSSIBuilder.java | 212 ---- .../graalvm/compiler/lir/ssi/SSIBuilder.java | 334 ------ .../compiler/lir/ssi/SSIBuilderBase.java | 116 -- .../lir/ssi/SSIConstructionPhase.java | 82 -- .../org/graalvm/compiler/lir/ssi/SSIUtil.java | 196 ---- .../graalvm/compiler/lir/ssi/SSIVerifier.java | 179 --- .../FixPointIntervalBuilder.java | 18 +- .../stackslotalloc/LSStackSlotAllocator.java | 16 +- .../compiler/lir/util/GenericValueMap.java | 11 +- .../compiler/lir/util/IndexedValueMap.java | 12 +- .../phases/LoopSafepointEliminationPhase.java | 2 +- .../loop/phases/LoopTransformations.java | 4 +- .../compiler/loop/test/LoopsDataTest.java | 125 ++ .../compiler/loop/DefaultLoopPolicies.java | 35 +- .../loop/DerivedScaledInductionVariable.java | 4 +- .../src/org/graalvm/compiler/loop/LoopEx.java | 35 +- .../graalvm/compiler/loop/LoopFragment.java | 28 +- .../compiler/loop/LoopFragmentInside.java | 14 +- .../org/graalvm/compiler/loop/LoopsData.java | 64 +- .../micro/benchmarks/ArrayListBenchmark.java | 71 ++ .../micro/benchmarks/BoxingBenchmark.java} | 47 +- .../ConcurrentSkipListBenchmark.java} | 38 +- .../src/micro/benchmarks/HashBenchmark.java | 52 + .../ConditionalEliminationBenchmark.java | 53 +- .../microbenchmarks/graal/GraalBenchmark.java | 6 +- .../graal/util/GraalState.java | 3 + .../microbenchmarks/graal/util/GraalUtil.java | 15 +- .../graal/util/GraphState.java | 17 +- .../lir/GraalCompilerState.java | 38 +- .../lir/RegisterAllocationTimeBenchmark.java | 11 +- .../trace/TraceLSRAIntervalBuildingBench.java | 22 +- .../test/IfNodeCanonicalizationTest.java | 1 + .../compiler/nodes/test/IntegerStampTest.java | 156 ++- .../test/NegateNodeCanonicalizationTest.java | 14 +- .../nodes/test/ShortCircuitOrNodeTest.java | 309 ++++- .../compiler/nodes/AbstractEndNode.java | 3 +- .../compiler/nodes/AbstractMergeNode.java | 11 +- .../compiler/nodes/BinaryOpLogicNode.java | 6 +- .../graalvm/compiler/nodes/Cancellable.java | 35 + .../compiler/nodes/ControlSplitNode.java | 11 + .../compiler/nodes/DeoptimizeNode.java | 7 +- .../compiler/nodes/DeoptimizingGuard.java | 4 +- .../graalvm/compiler/nodes/EncodedGraph.java | 8 +- .../compiler/nodes/EntryProxyNode.java | 6 + .../compiler/nodes/FixedGuardNode.java | 4 +- .../graalvm/compiler/nodes/FrameState.java | 2 +- .../graalvm/compiler/nodes/GraphDecoder.java | 172 +-- .../graalvm/compiler/nodes/GraphEncoder.java | 48 +- .../org/graalvm/compiler/nodes/GuardNode.java | 3 +- .../graalvm/compiler/nodes/GuardPhiNode.java | 5 - .../compiler/nodes/GuardedValueNode.java | 20 +- .../org/graalvm/compiler/nodes/IfNode.java | 82 +- .../nodes/IndirectCallTargetNode.java | 3 + .../org/graalvm/compiler/nodes/Invoke.java | 3 +- .../graalvm/compiler/nodes/InvokeNode.java | 14 - .../nodes/InvokeWithExceptionNode.java | 25 +- .../compiler/nodes/KillingBeginNode.java | 8 +- .../graalvm/compiler/nodes/LoopBeginNode.java | 4 +- .../compiler/nodes/NamedLocationIdentity.java | 9 +- .../org/graalvm/compiler/nodes/PhiNode.java | 79 +- .../graalvm/compiler/nodes/PiArrayNode.java | 34 +- .../org/graalvm/compiler/nodes/PiNode.java | 98 +- .../org/graalvm/compiler/nodes/ProxyNode.java | 3 +- .../compiler/nodes/ShortCircuitOrNode.java | 81 ++ .../nodes/SimplifyingGraphDecoder.java | 14 +- .../compiler}/nodes/SnippetAnchorNode.java | 4 +- .../compiler/nodes/StructuredGraph.java | 234 ++-- .../org/graalvm/compiler/nodes/ValueNode.java | 23 + .../graalvm/compiler/nodes/ValuePhiNode.java | 7 +- .../compiler/nodes/ValueProxyNode.java | 6 + .../graalvm/compiler/nodes/calc/AddNode.java | 2 +- .../nodes/calc/BinaryArithmeticNode.java | 30 +- .../compiler/nodes/calc/CompareNode.java | 15 +- .../compiler/nodes/calc/ConvertNode.java | 8 + .../compiler/nodes/calc/FloatConvertNode.java | 5 + .../compiler/nodes/calc/FloatEqualsNode.java | 8 +- .../nodes/calc/FloatLessThanNode.java | 4 +- .../compiler/nodes/calc/IntegerBelowNode.java | 196 +--- .../nodes/calc/IntegerConvertNode.java | 14 +- .../nodes/calc/IntegerDivRemNode.java | 9 +- .../nodes/calc/IntegerEqualsNode.java | 124 +- .../nodes/calc/IntegerLessThanNode.java | 221 ++-- .../nodes/calc/IntegerLowerThanNode.java | 318 +++++ .../compiler/nodes/calc/IntegerTestNode.java | 12 +- .../compiler/nodes/calc/IsNullNode.java | 44 +- .../graalvm/compiler/nodes/calc/MulNode.java | 20 +- .../compiler/nodes/calc/NarrowNode.java | 25 +- .../compiler/nodes/calc/NegateNode.java | 9 +- .../graalvm/compiler/nodes/calc/NotNode.java | 9 +- .../nodes/calc/PointerEqualsNode.java | 12 +- .../compiler/nodes/calc/ReinterpretNode.java | 14 +- .../compiler/nodes/calc/SignExtendNode.java | 11 +- .../graalvm/compiler/nodes/calc/SubNode.java | 2 +- .../compiler/nodes/calc/UnsignedDivNode.java | 6 - .../compiler/nodes/calc/UnsignedRemNode.java | 6 - .../compiler/nodes/calc/ZeroExtendNode.java | 26 +- .../org/graalvm/compiler/nodes/cfg/Block.java | 42 +- .../compiler/nodes/cfg/ControlFlowGraph.java | 255 +++- .../InstrumentationBeginNode.java | 74 -- .../instrumentation/InstrumentationNode.java | 172 --- .../instrumentation/IsMethodInlinedNode.java | 92 -- .../instrumentation/MonitorProxyNode.java | 77 -- .../debug/instrumentation/RootNameNode.java | 87 -- .../compiler/nodes/extended/BoxNode.java | 6 +- .../nodes/extended/BranchProbabilityNode.java | 2 +- .../nodes/extended/FixedValueAnchorNode.java | 21 +- .../nodes/extended/GuardedUnsafeLoadNode.java | 2 +- .../nodes/extended/IntegerSwitchNode.java | 38 +- .../nodes/extended/JavaWriteNode.java | 4 +- .../compiler/nodes/extended/LoadHubNode.java | 6 +- .../compiler/nodes/extended/OSRLockNode.java | 39 + .../OSRMonitorEnterNode.java} | 42 +- .../{UnsafeLoadNode.java => RawLoadNode.java} | 37 +- ...UnsafeStoreNode.java => RawStoreNode.java} | 32 +- .../compiler/nodes/extended/SwitchNode.java | 41 + .../nodes/extended/UnsafeAccessNode.java | 37 +- .../nodes/extended/UnsafeCopyNode.java | 4 +- .../nodes/extended/ValueAnchorNode.java | 7 - .../GeneratedInvocationPlugin.java | 2 +- .../GraphBuilderConfiguration.java | 43 +- .../graphbuilderconf/GraphBuilderContext.java | 34 +- .../graphbuilderconf/GraphBuilderTool.java | 5 + .../graphbuilderconf/InvocationPlugin.java | 22 + .../graphbuilderconf/InvocationPlugins.java | 77 +- ...e.java => AbstractCompareAndSwapNode.java} | 41 +- .../compiler/nodes/java/AccessFieldNode.java | 2 +- .../nodes/java/AccessMonitorNode.java | 5 + .../nodes/java/ClassIsAssignableFromNode.java | 8 +- .../nodes/java/DynamicNewInstanceNode.java | 2 + .../nodes/java/ExceptionObjectNode.java | 2 +- .../nodes/java/FinalFieldBarrierNode.java | 4 +- .../nodes/java/InstanceOfDynamicNode.java | 4 +- .../compiler/nodes/java/LoadFieldNode.java | 23 +- .../nodes/java/LogicCompareAndSwapNode.java | 72 ++ .../java/LoweredAtomicReadAndWriteNode.java | 10 +- .../compiler/nodes/java/NewArrayNode.java | 35 +- .../compiler/nodes/java/StoreFieldNode.java | 13 +- .../compiler/nodes/java/TypeSwitchNode.java | 20 + ...ode.java => UnsafeCompareAndSwapNode.java} | 9 +- .../nodes/java/ValueCompareAndSwapNode.java | 59 + .../nodes/memory/AbstractWriteNode.java | 23 - .../nodes/memory/FixedAccessNode.java | 3 +- .../nodes/memory/FloatingReadNode.java | 37 +- .../nodes/memory/LIRLowerableAccess.java} | 11 +- .../compiler/nodes/memory/MemoryMap.java | 4 +- .../compiler/nodes/memory/MemoryMapNode.java | 26 +- .../compiler/nodes/memory/ReadNode.java | 52 +- .../compiler/nodes/memory/WriteNode.java | 60 +- .../nodes/memory/address/AddressNode.java | 14 + .../memory/address/OffsetAddressNode.java | 64 +- .../nodes/memory/address/RawAddressNode.java | 17 +- .../nodes/spi/NodeLIRBuilderTool.java | 5 + .../compiler/nodes/spi/Replacements.java | 3 + .../{PiPushable.java => StampInverter.java} | 21 +- .../compiler/nodes/spi/ValueProxy.java | 4 +- .../compiler/nodes/spi/VirtualizerTool.java | 3 + .../compiler/nodes/util/ConstantFoldUtil.java | 8 +- .../compiler/nodes/util/GraphUtil.java | 269 +++-- .../nodes/virtual/CommitAllocationNode.java | 21 - .../options/processor/OptionProcessor.java | 45 +- .../test/NestedBooleanOptionKeyTest.java | 123 ++ .../test/NestedBooleanOptionValueTest.java | 143 --- .../compiler/options/test/TestOptionKey.java | 68 ++ .../options/test/TestOptionValue.java | 140 --- .../compiler/options/DerivedOptionValue.java | 60 - ...numOptionValue.java => EnumOptionKey.java} | 21 +- ...Value.java => NestedBooleanOptionKey.java} | 19 +- .../org/graalvm/compiler/options/Option.java | 2 +- .../compiler/options/OptionDescriptor.java | 17 +- .../compiler/options/OptionDescriptors.java | 2 +- .../graalvm/compiler/options/OptionKey.java | 164 +++ .../graalvm/compiler/options/OptionValue.java | 517 --------- .../compiler/options/OptionValues.java | 241 ++++ .../compiler/options/OptionValuesAccess.java} | 20 +- .../compiler/options/OptionsParser.java | 219 ++-- .../compiler/options/StableOptionValue.java | 75 -- .../compiler/options/UniquePathUtilities.java | 60 +- .../phases/common/CanonicalizerPhase.java | 35 +- .../common/ConvertDeoptimizeToGuardPhase.java | 35 +- .../common/DeadCodeEliminationPhase.java | 18 +- .../DominatorConditionalEliminationPhase.java | 243 ++-- .../phases/common/ExpandLogicPhase.java | 7 + .../compiler/phases/common/FixReadsPhase.java | 515 ++++++++ .../phases/common/FloatingReadPhase.java | 101 +- .../common/FrameStateAssignmentPhase.java | 4 +- .../phases/common/GuardLoweringPhase.java | 151 +-- .../IterativeConditionalEliminationPhase.java | 7 +- .../phases/common/LockEliminationPhase.java | 6 +- .../common/LoopSafepointInsertionPhase.java | 13 +- .../compiler/phases/common/LoweringPhase.java | 45 +- .../NewConditionalEliminationPhase.java | 1031 +++++++++++++++++ .../common/OptimizeGuardAnchorsPhase.java | 150 --- .../common/ProfileCompiledMethodsPhase.java | 2 +- .../PropagateDeoptimizeProbabilityPhase.java | 106 ++ .../phases/common/PushThroughPiPhase.java | 50 - .../phases/common/RemoveValueProxyPhase.java | 6 +- .../common/UseTrappingNullChecksPhase.java | 68 +- .../common/ValueAnchorCleanupPhase.java | 102 -- .../phases/common/inlining/InliningPhase.java | 16 +- .../phases/common/inlining/InliningUtil.java | 206 ++-- .../inlining/info/AbstractInlineInfo.java | 31 +- .../inlining/info/AssumptionInlineInfo.java | 5 +- .../common/inlining/info/ExactInlineInfo.java | 5 +- .../common/inlining/info/InlineInfo.java | 8 +- .../info/MultiTypeGuardInlineInfo.java | 28 +- .../inlining/info/TypeGuardInlineInfo.java | 5 +- .../inlining/info/elem/InlineableGraph.java | 8 +- .../policy/AbstractInliningPolicy.java | 2 +- .../inlining/policy/GreedyInliningPolicy.java | 14 +- .../policy/InlineEverythingPolicy.java | 4 +- .../walker/CallsiteHolderExplorable.java | 20 +- .../walker/ComputeInliningRelevance.java | 26 +- .../common/inlining/walker/InliningData.java | 50 +- .../inlining/walker/MethodInvocation.java | 2 +- .../ExtractInstrumentationPhase.java | 219 ---- ...HighTierReconcileInstrumentationPhase.java | 182 --- .../InlineInstrumentationPhase.java | 227 ---- .../MidTierReconcileInstrumentationPhase.java | 64 - .../common/util/HashSetNodeEventListener.java | 10 +- .../graalvm/compiler/phases/BasePhase.java | 23 +- .../phases/OptimisticOptimizations.java | 55 +- .../graalvm/compiler/phases/PhaseSuite.java | 25 + .../graph/FixedNodeProbabilityCache.java | 5 +- .../phases/graph/PostOrderNodeIterator.java | 9 +- .../phases/graph/ReentrantBlockIterator.java | 37 +- .../phases/graph/ReentrantNodeIterator.java | 29 +- .../phases/graph/SinglePassNodeIterator.java | 9 +- .../schedule/MemoryScheduleVerification.java | 28 +- .../phases/schedule/SchedulePhase.java | 720 +++++++----- .../phases/tiers/CompilerConfiguration.java | 13 +- .../graalvm/compiler/phases/tiers/Suites.java | 9 +- .../compiler/phases/tiers/SuitesCreator.java | 9 +- .../compiler/phases/tiers/SuitesProvider.java | 11 +- .../compiler/phases/util/GraphOrder.java | 7 +- .../phases/verify/VerifyBailoutUsage.java | 4 +- .../phases/verify/VerifyDebugUsage.java | 1 - .../phases/verify/VerifyUsageWithEquals.java | 13 + .../compiler/printer/BinaryGraphPrinter.java | 29 +- .../graalvm/compiler/printer/CFGPrinter.java | 58 +- .../compiler/printer/CFGPrinterObserver.java | 15 +- .../printer/CanonicalStringGraphPrinter.java | 16 +- .../printer/GraalDebugConfigCustomizer.java | 77 +- .../compiler/printer/GraphPrinter.java | 11 +- .../printer/GraphPrinterDumpHandler.java | 72 +- .../compiler/printer/IdealGraphPrinter.java | 25 +- .../printer/NoDeadCodeVerifyHandler.java | 15 +- .../AArch64CountTrailingZerosNode.java | 90 ++ .../AArch64FloatArithmeticSnippets.java | 5 +- .../aarch64/AArch64GraphBuilderPlugins.java | 56 +- .../AArch64IntegerArithmeticSnippets.java | 5 +- .../amd64/AMD64ConvertSnippets.java | 5 +- .../amd64/AMD64GraphBuilderPlugins.java | 11 + .../amd64/AMD64StringIndexOfNode.java | 104 ++ .../amd64/AMD64StringSubstitutions.java | 73 ++ .../test/ArraysSubstitutionsTest.java | 4 +- .../test/CompiledExceptionHandlerTest.java | 18 +- .../CompiledNullPointerExceptionTest.java | 18 +- .../test/DeoptimizeOnExceptionTest.java | 10 +- .../replacements/test/DerivedOopTest.java | 7 +- .../compiler/replacements/test/EdgesTest.java | 3 +- .../compiler/replacements/test/FoldTest.java | 5 +- .../replacements/test/InstanceOfTest.java | 2 +- .../test/IntegerExactFoldTest.java | 298 +++++ .../test/IntegerMulExactFoldTest.java | 211 ---- .../replacements/test/InvokeTest.java | 2 +- .../replacements/test/MonitorTest.java | 4 +- .../replacements/test/NewMultiArrayTest.java | 7 +- .../replacements/test/ObjectAccessTest.java | 22 +- .../replacements/test/PEGraphDecoderTest.java | 6 +- .../replacements/test/PointerTest.java | 19 +- .../test/PointerTrackingTest.java | 7 +- .../test/ReplacementsParseTest.java | 7 +- .../replacements/test/ReplacementsTest.java} | 29 +- .../replacements/test/SnippetsTest.java | 50 + .../test/StringIndexOfConstantTest.java | 91 ++ .../replacements/test/StringIndexOfTest.java} | 48 +- .../test/StringIndexOfTestBase.java | 117 ++ .../replacements/test/SubstitutionsTest.java | 9 +- .../replacements/test/TypeCheckTest.java | 9 +- .../compiler/replacements/test/WordTest.java | 17 +- .../test/classfile/RedefineIntrinsicTest.java | 16 +- .../replacements/verifier/FoldVerifier.java | 7 +- .../verifier/GeneratedFoldPlugin.java | 1 + .../verifier/GeneratedPlugin.java | 3 +- .../compiler/replacements/BoxingSnippets.java | 87 +- .../replacements/CachingPEGraphDecoder.java | 16 +- .../ConstantBindingParameterPlugin.java | 11 +- .../ConstantStringIndexOfSnippets.java | 150 +++ .../DefaultJavaLoweringProvider.java | 216 ++-- .../compiler/replacements/GraphKit.java | 7 +- .../InlineDuringParsingPlugin.java | 9 +- .../InstanceOfSnippetsTemplates.java | 5 +- .../replacements/IntrinsicGraphBuilder.java | 19 +- .../replacements/MethodHandlePlugin.java | 9 +- .../compiler/replacements/PEGraphDecoder.java | 68 +- .../replacements/ReplacementsImpl.java | 59 +- .../replacements/ReplacementsUtil.java | 10 +- .../compiler/replacements/SnippetCounter.java | 49 +- .../replacements/SnippetCounterNode.java | 30 +- .../SnippetLowerableMemoryNode.java | 87 ++ .../replacements/SnippetTemplate.java | 276 +++-- .../StandardGraphBuilderPlugins.java | 105 +- ...ivesPlugin.java => StringIndexOfNode.java} | 40 +- .../compiler/replacements/UnsafeAccess.java | 51 + .../replacements/WordOperationPlugin.java | 36 +- .../replacements/classfile/Classfile.java | 5 +- .../classfile/ClassfileBytecodeProvider.java | 202 +++- .../classfile/ClassfileConstant.java | 24 +- .../replacements/nodes/AssertionNode.java | 32 +- .../nodes/DirectObjectStoreNode.java | 118 -- .../replacements/nodes/DirectStoreNode.java | 4 +- .../replacements/nodes/MacroNode.java | 16 +- .../replacements/nodes/MethodHandleNode.java | 185 ++- .../nodes/arithmetic/IntegerAddExactNode.java | 18 +- .../arithmetic/IntegerAddExactSplitNode.java | 14 + .../IntegerExactArithmeticNode.java | 2 +- .../IntegerExactArithmeticSplitNode.java | 14 +- .../nodes/arithmetic/IntegerMulExactNode.java | 56 +- .../arithmetic/IntegerMulExactSplitNode.java | 14 + .../arithmetic/IntegerSubExactSplitNode.java | 14 + .../compiler/salver/SalverOptions.java | 47 - .../salver/dumper/AbstractGraalDumper.java | 87 -- .../dumper/AbstractMethodScopeDumper.java | 155 --- .../dumper/AbstractSerializerDumper.java | 64 - .../compiler/salver/dumper/GraphDumper.java | 365 ------ .../salver/handler/AbstractDumpHandler.java | 109 -- .../handler/AbstractGraalDumpHandler.java | 172 --- .../graalvm/compiler/salver/package-info.java | 69 -- .../salver/serialize/JSONSerializer.java | 170 --- .../compiler/salver/util/MethodContext.java | 118 -- .../salver/writer/ChannelDumpWriter.java | 192 --- .../compiler/salver/writer/DumpWriter.java | 51 - .../graalvm/compiler/test/AddExports.java} | 35 +- .../org/graalvm/compiler/test/GraalTest.java | 1 + .../virtual/nodes/VirtualObjectState.java | 6 +- .../phases/ea/EarlyReadEliminationPhase.java | 7 +- .../virtual/phases/ea/EffectList.java | 2 +- .../virtual/phases/ea/EffectsBlockState.java | 38 +- .../virtual/phases/ea/EffectsClosure.java | 137 ++- .../virtual/phases/ea/EffectsPhase.java | 59 +- .../virtual/phases/ea/GraphEffectList.java | 73 +- .../virtual/phases/ea/ObjectState.java | 26 +- .../ea/PEReadEliminationBlockState.java | 29 +- .../phases/ea/PEReadEliminationClosure.java | 122 +- .../phases/ea/PartialEscapeBlockState.java | 105 +- .../phases/ea/PartialEscapeClosure.java | 198 ++-- .../virtual/phases/ea/PartialEscapePhase.java | 24 +- .../phases/ea/ReadEliminationBlockState.java | 33 +- .../phases/ea/ReadEliminationClosure.java | 117 +- .../virtual/phases/ea/VirtualUtil.java | 34 +- .../phases/ea/VirtualizerToolImpl.java | 26 +- .../org/graalvm/compiler/word/Pointer.java | 41 + .../src/org/graalvm/compiler/word/Word.java | 92 ++ .../compiler/word/nodes/WordCastNode.java | 8 +- .../org/graalvm/util/test/CollectionTest.java | 536 +++++++++ .../src/org/graalvm/util/CollectionsUtil.java | 196 ++++ .../src/org/graalvm/util/EconomicMap.java | 206 ++++ .../src/org/graalvm/util/EconomicSet.java | 126 ++ .../src/org/graalvm/util/Equivalence.java | 93 ++ .../src/org/graalvm/util/MapCursor.java} | 19 +- .../org/graalvm/util/ObjectSizeEstimate.java | 240 ++++ .../src/org/graalvm/util/Pair.java | 102 ++ .../util/UnmodifiableEconomicMap.java} | 32 +- .../graalvm/util/UnmodifiableEconomicSet.java | 48 + .../graalvm/util/UnmodifiableMapCursor.java} | 27 +- .../graalvm/util/impl/EconomicMapImpl.java | 852 ++++++++++++++ 907 files changed, 25594 insertions(+), 20934 deletions(-) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot => org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common}/CompressEncoding.java (75%) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.asm/src/org/graalvm/compiler/asm => org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common}/NumUtil.java (83%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.common/src/org/graalvm/compiler => org.graalvm.compiler.core.common/src/org/graalvm/compiler/core}/common/PermanentBailoutException.java (97%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.common/src/org/graalvm/compiler => org.graalvm.compiler.core.common/src/org/graalvm/compiler/core}/common/RetryableBailoutException.java (97%) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java => org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java} (52%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/DumpHandler.java => org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java} (74%) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/{PrintStreamOption.java => PrintStreamOptionKey.java} (58%) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java => org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java} (62%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/FastSSIBuilder.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIBuilder.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIBuilderBase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIConstructionPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIUtil.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIVerifier.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopsDataTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java => org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/BoxingBenchmark.java} (55%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/util/ECIDUtil.java => org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java} (54%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/HashBenchmark.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Cancellable.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot => org.graalvm.compiler.nodes/src/org/graalvm/compiler}/nodes/SnippetAnchorNode.java (94%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationBeginNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/IsMethodInlinedNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/MonitorProxyNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/RootNameNode.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/OSRLockNode.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/{debug/instrumentation/InstrumentationEndNode.java => extended/OSRMonitorEnterNode.java} (51%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/{UnsafeLoadNode.java => RawLoadNode.java} (66%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/{UnsafeStoreNode.java => RawStoreNode.java} (76%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/{LoweredCompareAndSwapNode.java => AbstractCompareAndSwapNode.java} (58%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/{CompareAndSwapNode.java => UnsafeCompareAndSwapNode.java} (84%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/Dumper.java => org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/LIRLowerableAccess.java} (76%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/{PiPushable.java => StampInverter.java} (72%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionKeyTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionValueTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionKey.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionValue.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/DerivedOptionValue.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/{EnumOptionValue.java => EnumOptionKey.java} (71%) rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/{NestedBooleanOptionValue.java => NestedBooleanOptionKey.java} (72%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValue.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataDict.java => org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValuesAccess.java} (64%) delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/StableOptionValue.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NewConditionalEliminationPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/OptimizeGuardAnchorsPhase.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PushThroughPiPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ValueAnchorCleanupPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/ExtractInstrumentationPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/HighTierReconcileInstrumentationPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/InlineInstrumentationPhase.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/MidTierReconcileInstrumentationPhase.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountTrailingZerosNode.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerMulExactFoldTest.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/Salver.java => org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsTest.java} (53%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfConstantTest.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/AbstractSerializer.java => org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfTest.java} (57%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfTestBase.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetLowerableMemoryNode.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/{InlineGraalDirectivesPlugin.java => StringIndexOfNode.java} (50%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/UnsafeAccess.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/DirectObjectStoreNode.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/SalverOptions.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractGraalDumper.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractMethodScopeDumper.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractSerializerDumper.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/GraphDumper.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/AbstractDumpHandler.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/AbstractGraalDumpHandler.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/package-info.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/JSONSerializer.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/util/MethodContext.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/ChannelDumpWriter.java delete mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/SalverDebugConfigCustomizer.java => org.graalvm.compiler.test/src/org/graalvm/compiler/test/AddExports.java} (57%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataList.java => org.graalvm.util/src/org/graalvm/util/MapCursor.java} (67%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/Serializer.java => org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java} (63%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java rename hotspot/src/jdk.internal.vm.compiler/share/classes/{org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationInliningCallback.java => org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java} (65%) create mode 100644 hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java diff --git a/hotspot/make/CompileTools.gmk b/hotspot/make/CompileTools.gmk index c80632226cf..9d9a83239f2 100644 --- a/hotspot/make/CompileTools.gmk +++ b/hotspot/make/CompileTools.gmk @@ -47,11 +47,9 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ $(SRC_DIR)/org.graalvm.compiler.core/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.asm/src \ $(SRC_DIR)/org.graalvm.compiler.bytecode/src \ @@ -68,6 +66,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.phases.common/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.virtual/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ @@ -102,6 +101,7 @@ ifeq ($(INCLUDE_GRAAL), true) SRC := \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \ + $(SRC_DIR)/org.graalvm.util/src \ , \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \ @@ -114,9 +114,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.code/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ @@ -125,6 +123,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ diff --git a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk index 268a6b237a1..3687362b5be 100644 --- a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk +++ b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk @@ -37,7 +37,6 @@ SRC_DIR := $(HOTSPOT_TOPDIR)/src/$(MODULE)/share/classes PROC_SRC_SUBDIRS := \ org.graalvm.compiler.code \ - org.graalvm.compiler.common \ org.graalvm.compiler.core \ org.graalvm.compiler.core.aarch64 \ org.graalvm.compiler.core.amd64 \ diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java index 226cf0bf219..63625cce2a9 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java @@ -40,14 +40,15 @@ import jdk.tools.jaotc.binformat.macho.JMachORelocObject; import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; /** * A format-agnostic container class that holds various components of a binary. * *

* This class holds information necessary to create platform-specific binary containers such as - * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac - * OS or PEContainer for MS Windows operating systems. + * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac OS or PEContainer + * for MS Windows operating systems. * *

* Method APIs provided by this class are used to construct and populate platform-independent @@ -58,6 +59,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; * Methods to record and access code section contents, symbols and relocations are provided. */ public class BinaryContainer implements SymbolTable { + private final OptionValues graalOptions; private final int codeSegmentSize; @@ -259,8 +261,12 @@ public class BinaryContainer implements SymbolTable { * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the * prefix {@code prefix}. It also initializes internal code container, symbol table and * relocation tables. + * + * @param graalOptions */ - public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + this.graalOptions = graalOptions; + this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize; this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment; @@ -305,17 +311,17 @@ public class BinaryContainer implements SymbolTable { graalHotSpotVMConfig.useCMSGC, graalHotSpotVMConfig.useTLAB, graalHotSpotVMConfig.useBiasedLocking, - TieredAOT.getValue(), + TieredAOT.getValue(graalOptions), graalHotSpotVMConfig.enableContended, graalHotSpotVMConfig.restrictContended, graphBuilderConfig.omitAssertions() }; - int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift, - graalHotSpotVMConfig.getKlassEncoding().shift, + int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(), + graalHotSpotVMConfig.getKlassEncoding().getShift(), graalHotSpotVMConfig.contendedPaddingWidth, graalHotSpotVMConfig.fieldsAllocationStyle, - 1 << graalHotSpotVMConfig.getOopEncoding().alignment, + 1 << graalHotSpotVMConfig.logMinObjAlignment(), graalHotSpotVMConfig.codeSegmentSize, }; // @formatter:on @@ -511,8 +517,7 @@ public class BinaryContainer implements SymbolTable { JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion); pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values()); break; - } - else + } else throw new InternalError("Unsupported platform: " + osName); } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java index 3ba1067b959..7b11338d335 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java @@ -23,17 +23,12 @@ package jdk.tools.jaotc; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import java.util.ListIterator; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -43,8 +38,7 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -62,6 +56,7 @@ import jdk.vm.ci.meta.TriState; public class AOTBackend { private final Main main; + private final OptionValues graalOptions; private final HotSpotBackend backend; @@ -71,8 +66,9 @@ public class AOTBackend { private final HighTierContext highTierContext; private final GraalFilters filters; - public AOTBackend(Main main, HotSpotBackend backend, GraalFilters filters) { + public AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, GraalFilters filters) { this.main = main; + this.graalOptions = graalOptions; this.backend = backend; this.filters = filters; providers = backend.getProviders(); @@ -87,23 +83,21 @@ public class AOTBackend { private Suites getSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultSuites(); + return backend.getSuites().getDefaultSuites(graalOptions); } private LIRSuites getLirSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultLIRSuites(); + return backend.getSuites().getDefaultLIRSuites(graalOptions); } @SuppressWarnings("try") public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) { - try (OverrideScope s = OptionValue.override(ImmutableCode, true, GeneratePIC, true)) { - StructuredGraph graph = buildStructuredGraph(resolvedMethod); - if (graph != null) { - return compileGraph(resolvedMethod, graph); - } - return null; + StructuredGraph graph = buildStructuredGraph(resolvedMethod); + if (graph != null) { + return compileGraph(resolvedMethod, graph); } + return null; } /** @@ -115,7 +109,7 @@ public class AOTBackend { @SuppressWarnings("try") private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) { try (Scope s = Debug.scope("AOTParseMethod")) { - StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.NO, false, CompilationIdentifier.INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(graalOptions).method(javaMethod).useProfilingInfo(false).build(); graphBuilderSuite.apply(graph, highTierContext); return graph; } catch (Throwable e) { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java index f92ead4ba25..eb018b24724 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -54,6 +55,8 @@ public class AOTCompilationTask implements Runnable, Comparable { private final Main main; + private OptionValues graalOptions; + /** * The compilation id of this task. */ @@ -73,8 +76,9 @@ public class AOTCompilationTask implements Runnable, Comparable { */ private CompiledMethodInfo result; - public AOTCompilationTask(Main main, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { + public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { this.main = main; + this.graalOptions = graalOptions; this.id = ids.getAndIncrement(); this.holder = holder; this.method = method; @@ -91,14 +95,14 @@ public class AOTCompilationTask implements Runnable, Comparable { // Ensure a debug configuration for this thread is initialized if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out); + DebugEnvironment.ensureInitialized(graalOptions); } AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); final long threadId = Thread.currentThread().getId(); - final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); + final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed(); if (printCompilation) { TTY.println(getMethodDescription() + "..."); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java index 12a72c42dfa..7b708cb1d9c 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java @@ -31,12 +31,16 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.ResolvedJavaMethod; public class AOTCompiler { private final Main main; + private final OptionValues graalOptions; + private CompileQueue compileQueue; private final AOTBackend backend; @@ -102,11 +106,13 @@ public class AOTCompiler { /** * @param main + * @param graalOptions * @param aotBackend * @param threads number of compilation threads */ - public AOTCompiler(Main main, AOTBackend aotBackend, final int threads) { + public AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) { this.main = main; + this.graalOptions = graalOptions; this.compileQueue = new CompileQueue(threads); this.backend = aotBackend; } @@ -146,7 +152,7 @@ public class AOTCompiler { * @param method method to be enqueued */ private void enqueueMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method) { - AOTCompilationTask task = new AOTCompilationTask(main, aotClass, method, backend); + AOTCompilationTask task = new AOTCompilationTask(main, graalOptions, aotClass, method, backend); try { compileQueue.execute(task); } catch (RejectedExecutionException e) { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java index 159955c6bda..097670b7974 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.hotspot.HotSpotHostBackend; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -180,7 +181,8 @@ class DataBuilder { @SuppressWarnings("try") private AOTCompiledClass retrieveStubCode() { ArrayList stubs = new ArrayList<>(); - for (Stub stub : Stub.getStubs()) { + HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls(); + for (Stub stub : foreignCallsProvider.getStubs()) { try (Scope scope = Debug.scope("CompileStubs")) { CompilationResult result = stub.getCompilationResult(backend); CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend)); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index ab71c0e78bb..d00d6bbb3e1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -60,11 +60,15 @@ import jdk.tools.jaotc.collect.module.ModuleSourceProvider; import jdk.tools.jaotc.utils.Timer; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.hotspot.CompilerConfigurationFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory; +import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -76,11 +80,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.runtime.JVMCI; public class Main implements LogPrinter { - static { - GeneratePIC.setValue(true); - ImmutableCode.setValue(true); - } - static class BadArgs extends Exception { private static final long serialVersionUID = 1L; final String key; @@ -132,7 +131,7 @@ public class Main implements LogPrinter { abstract void process(Main task, String opt, String arg) throws BadArgs; } - static Option[] recognizedOptions = { new Option(" --output Output file name", true, "--output") { + static Option[] recognizedOptions = {new Option(" --output Output file name", true, "--output") { @Override void process(Main task, String opt, String arg) { String name = arg; @@ -172,7 +171,7 @@ public class Main implements LogPrinter { }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { @Override void process(Main task, String opt, String arg) { - TieredAOT.setValue(true); + task.options.tiered = true; } }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { @Override @@ -265,6 +264,7 @@ public class Main implements LogPrinter { public boolean help; public boolean version; public boolean compileWithAssertions; + public boolean tiered; } /* package */final Options options = new Options(); @@ -307,7 +307,7 @@ public class Main implements LogPrinter { printlnInfo("Compiling " + options.outputName + "..."); final long start = System.currentTimeMillis(); if (!run()) { - return EXIT_ABNORMAL; + return EXIT_ABNORMAL; } final long end = System.currentTimeMillis(); printlnInfo("Total time: " + (end - start) + " ms"); @@ -351,8 +351,7 @@ public class Main implements LogPrinter { } /** - * Visual Studio supported versions - * Search Order is: VS2013, VS2015, VS2012 + * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012 */ public enum VSVERSIONS { VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), @@ -367,20 +366,23 @@ public class Main implements LogPrinter { this.wkp = wellknownpath; } - String EnvVariable() { return envvariable; } - String WellKnownPath() { return wkp; } + String EnvVariable() { + return envvariable; + } + + String WellKnownPath() { + return wkp; + } } /** - * Search for Visual Studio link.exe - * Search Order is: VS2013, VS2015, VS2012 + * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012 */ private static String getWindowsLinkPath() { String link = "\\VC\\bin\\amd64\\link.exe"; /** - * First try searching the paths pointed to by - * the VS environment variables. + * First try searching the paths pointed to by the VS environment variables. */ for (VSVERSIONS vs : VSVERSIONS.values()) { String vspath = System.getenv(vs.EnvVariable()); @@ -388,13 +390,13 @@ public class Main implements LogPrinter { File commonTools = new File(vspath); File vsRoot = commonTools.getParentFile().getParentFile(); File linkPath = new File(vsRoot, link); - if (linkPath.exists()) return linkPath.getPath(); + if (linkPath.exists()) + return linkPath.getPath(); } } /** - * If we didn't find via the VS environment variables, - * try the well known paths + * If we didn't find via the VS environment variables, try the well known paths */ for (VSVERSIONS vs : VSVERSIONS.values()) { String wkp = vs.WellKnownPath(); @@ -438,7 +440,13 @@ public class Main implements LogPrinter { printInfo(classesToCompile.size() + " classes found"); } - GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler(); + OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + // Setting -Dgraal.TieredAOT overrides --compile-for-tiered + if (!TieredAOT.hasBeenSet(graalOptions)) { + graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered); + } + graalOptions = new OptionValues(HotSpotGraalOptionValues.HOTSPOT_OPTIONS, GeneratePIC, true, ImmutableCode, true); + GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions)); HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime(); HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend(); MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); @@ -458,8 +466,8 @@ public class Main implements LogPrinter { System.gc(); } - AOTBackend aotBackend = new AOTBackend(this, backend, filters); - AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads); + AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters); + AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); classes = compiler.compileClasses(classes); GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig(); @@ -475,7 +483,7 @@ public class Main implements LogPrinter { System.gc(); } - BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); + BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); dataBuilder.prepareData(); @@ -524,11 +532,9 @@ public class Main implements LogPrinter { if (name.endsWith(".so")) { objectFileName = name.substring(0, name.length() - ".so".length()); - } - else if (name.endsWith(".dylib")) { + } else if (name.endsWith(".dylib")) { objectFileName = name.substring(0, name.length() - ".dylib".length()); - } - else if (name.endsWith(".dll")) { + } else if (name.endsWith(".dll")) { objectFileName = name.substring(0, name.length() - ".dll".length()); } @@ -536,34 +542,32 @@ public class Main implements LogPrinter { case "Linux": // libraryFileName = options.outputName + ".so"; objectFileName = objectFileName + ".o"; - linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; break; case "SunOS": // libraryFileName = options.outputName + ".so"; objectFileName = objectFileName + ".o"; - linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName; break; case "Mac OS X": // libraryFileName = options.outputName + ".dylib"; objectFileName = objectFileName + ".o"; - linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName; break; default: if (osName.startsWith("Windows")) { // libraryFileName = options.outputName + ".dll"; objectFileName = objectFileName + ".obj"; - linkerPath = (options.linkerpath != null) ? - options.linkerpath : getWindowsLinkPath(); + linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath(); if (linkerPath == null) { throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe"); } linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; break; - } - else + } else throw new InternalError("Unsupported platform: " + osName); } diff --git a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py index dda989acedf..380c31931af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py +++ b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py @@ -17,18 +17,22 @@ suite = { "sha1" : "476d9a44cd19d6b55f81571077dfa972a4f8a083", "bootClassPathAgent" : "true", }, + + "ASM5" : { + "sha1" : "0da08b8cce7bbf903602a25a3a163ae252435795", + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-5.0.4.jar"], + }, + + "ASM_TREE5" : { + "sha1" : "396ce0c07ba2b481f25a70195c7c94922f0d1b0b", + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-tree-5.0.4.jar"], + "dependencies" : ["ASM5"], + }, }, "projects" : { # ------------- Graal ------------- - "org.graalvm.compiler.common" : { - "subDir" : "share/classes", - "sourceDirs" : ["src"], - "checkstyle" : "org.graalvm.compiler.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,Graal", - }, "org.graalvm.compiler.serviceprovider" : { "subDir" : "share/classes", @@ -50,7 +54,9 @@ suite = { "org.graalvm.compiler.options" : { "subDir" : "share/classes", "sourceDirs" : ["src"], + "dependencies" : ["org.graalvm.util"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "javaCompliance" : "1.8", "workingSets" : "Graal", }, @@ -82,6 +88,11 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : [ + "org.graalvm.compiler.debug.DebugConfigCustomizer", + "org.graalvm.compiler.debug.DebugInitializationParticipant", + "org.graalvm.compiler.debug.TTYStreamProvider", + ], "dependencies" : [ "org.graalvm.compiler.serviceprovider", "org.graalvm.compiler.options" @@ -108,7 +119,6 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.graph", - "org.graalvm.compiler.common", ], "annotationProcessors" : ["GRAAL_SERVICEPROVIDER_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -116,7 +126,7 @@ suite = { "workingSets" : "Graal", }, - "org.graalvm.compiler.api.collections" : { + "org.graalvm.util" : { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", @@ -124,6 +134,18 @@ suite = { "workingSets" : "API,Graal", }, + "org.graalvm.util.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JUNIT", + "org.graalvm.util", + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + "org.graalvm.compiler.api.directives" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -179,6 +201,11 @@ suite = { "org.graalvm.compiler.replacements", "org.graalvm.compiler.runtime", ], + "imports" : [ + # All other internal packages are exported dynamically - + # see org.graalvm.compiler.hotspot.HotSpotGraalJVMCIServiceLocator + "jdk.internal.module", + ], "checkstyle" : "org.graalvm.compiler.graph", "annotationProcessors" : [ "GRAAL_NODEINFO_PROCESSOR", @@ -320,7 +347,6 @@ suite = { "dependencies" : [ "org.graalvm.compiler.nodeinfo", "org.graalvm.compiler.core.common", - "org.graalvm.compiler.api.collections", ], "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -347,6 +373,9 @@ suite = { "org.graalvm.compiler.asm" : { "subDir" : "share/classes", "sourceDirs" : ["src"], + "dependencies" : [ + "org.graalvm.compiler.core.common" + ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Assembler", @@ -356,7 +385,6 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -379,9 +407,7 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", - "org.graalvm.compiler.common" ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -711,6 +737,18 @@ suite = { "workingSets" : "Graal", }, + "org.graalvm.compiler.loop.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "org.graalvm.compiler.loop", + "org.graalvm.compiler.core.test" + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "Graal,Test", + }, + "org.graalvm.compiler.loop.phases" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -731,6 +769,7 @@ suite = { "org.graalvm.compiler.virtual", "org.graalvm.compiler.loop.phases", ], + "uses" : ["org.graalvm.compiler.core.match.MatchStatementSet"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -908,7 +947,9 @@ suite = { "org.graalvm.compiler.graph.test", "org.graalvm.compiler.printer", "JAVA_ALLOCATION_INSTRUMENTER", + "ASM_TREE5", ], + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -929,21 +970,6 @@ suite = { "findbugs" : "false", }, - # ------------- Salver ------------- - - "org.graalvm.compiler.salver" : { - "subDir" : "share/classes", - "sourceDirs" : ["src"], - "dependencies" : ["org.graalvm.compiler.phases"], - "annotationProcessors" : [ - "GRAAL_OPTIONS_PROCESSOR", - "GRAAL_SERVICEPROVIDER_PROCESSOR", - ], - "checkstyle" : "org.graalvm.compiler.graph", - "javaCompliance" : "1.8", - "workingSets" : "Graal", - }, - # ------------- AOT ------------- "jdk.tools.jaotc" : { @@ -1073,7 +1099,6 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", ], "distDependencies" : [ "GRAAL_API", @@ -1197,7 +1222,6 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", "org.graalvm.compiler.hotspot.aarch64", "org.graalvm.compiler.hotspot.amd64", "org.graalvm.compiler.hotspot.sparc", diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java index 783eef09fa5..8f53b16ed0b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java @@ -39,6 +39,7 @@ module jdk.internal.vm.compiler { uses org.graalvm.compiler.debug.TTYStreamProvider; uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory; uses org.graalvm.compiler.hotspot.HotSpotBackendFactory; + uses org.graalvm.compiler.options.OptionValuesAccess; uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; exports org.graalvm.compiler.api.directives to jdk.aot; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java deleted file mode 100644 index f8c00882bb7..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.collections; - -import java.util.Map; -import java.util.Set; - -/** - * A factory for creating collections. - */ -public interface CollectionsProvider { - - /** - * Creates a set that uses reference-equality in place of object-equality when comparing - * entries. - */ - Set newIdentitySet(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - */ - Map newIdentityMap(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param expectedMaxSize the expected maximum size of the map - */ - Map newIdentityMap(int expectedMaxSize); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java deleted file mode 100644 index 03bd8a7804d..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class AllocationInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public AllocationInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(AllocationInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - } - - public static boolean allocationWasExecuted; - - private static void resetFlag() { - allocationWasExecuted = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - allocationWasExecuted = true; - GraalDirectives.instrumentationEnd(); - } - - public static void notEscapeSnippet() { - @SuppressWarnings("unused") - ClassA a = new ClassA(); // a does not escape - } - - @Test - public void testNotEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "notEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "notEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet does not escape and will be optimized away. We expect - // the instrumentation is removed. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void mustEscapeSnippet() { - ClassA a = new ClassA(); - a.notInlinedMethod(); // a escapses - } - - @Test - public void testMustEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "mustEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "mustEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes. We expect the instrumentation is preserved. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void partialEscapeSnippet(boolean condition) { - ClassA a = new ClassA(); - - if (condition) { - a.notInlinedMethod(); // a escapes in the then-clause - } - } - - @Test - public void testPartialEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "partialEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "partialEscapeSnippet"); - executeExpected(method, null, true); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes in the then-clause, and will be relocated to - // this branch. We expect the instrumentation follows and will only be effective when - // the then-clause is taken. - InstalledCode code = getCode(method); - code.executeVarargs(false); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - code.executeVarargs(true); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java index 91a14d1630d..d85e18ddf66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java @@ -70,7 +70,7 @@ public class DeoptimizeDirectiveTest extends GraalCompilerTest { Result actual; try { actual = new Result(code.executeVarargs(), null); - } catch (Throwable e) { + } catch (Exception e) { actual = new Result(null, e); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java deleted file mode 100644 index 48a1f107320..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class IsMethodInlineDirectiveTest extends GraalCompilerTest { - - public IsMethodInlineDirectiveTest() { - HotSpotResolvedJavaMethod calleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeSnippet"); - calleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod calleeWithInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeWithInstrumentationSnippet"); - calleeWithInstrumentationSnippet.shouldBeInlined(); - } - - public static boolean rootMethodSnippet() { - return GraalDirectives.isMethodInlined(); - } - - @SuppressWarnings("try") - @Test - public void testRootMethod() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootMethodSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target method is not inlined. We expect the result to be false. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(false, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static boolean calleeSnippet() { - return GraalDirectives.isMethodInlined(); - } - - public static boolean callerSnippet() { - return calleeSnippet(); - } - - @Test - public void testInlinedCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // calleeSnippet will be inlined. We expect the result to be true. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(true, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static boolean isCalleeInlined; - static boolean isCallerInlined; - - public static void calleeWithInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - isCalleeInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - calleeWithInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - isCallerInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - @Test - public void testInlinedCalleeWithInstrumentation() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - isCalleeInlined = false; - isCallerInlined = false; - // calleeWithInstrumentationSnippet will be inlined. We expect the flag1 set in - // calleeWithInstrumentationSnippet to be true, and the flag2 set in callerSnippet1 to - // be false. - InstalledCode code = getCode(method); - code.executeVarargs(); - assertTrue("calleWithInstrumentationSnippet should be inlined", isCalleeInlined); - assertFalse("callerSnippet1 should not be inlined", isCallerInlined); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java deleted file mode 100644 index 244e2d620cc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class LockInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public LockInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(LockInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - - } - - public static final Object lock = new Object(); - public static boolean lockAfterCheckPoint; - public static boolean checkpoint; - - private static void resetFlags() { - lockAfterCheckPoint = false; - checkpoint = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - lockAfterCheckPoint = checkpoint; - GraalDirectives.instrumentationEnd(); - } - - public static void lockSnippet() { - synchronized (lock) { - checkpoint = true; - ClassA a = new ClassA(); - a.notInlinedMethod(); - } - } - - @Test - public void testLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "lockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "lockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The monitorenter anchors. We expect the instrumentation set the flag before passing - // the checkpoint. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("expected lock was performed before checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void postponeLockSnippet() { - ClassA a = new ClassA(); - - synchronized (a) { - checkpoint = true; - a.notInlinedMethod(); - } - - } - - @Test - public void testNonEscapeLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "postponeLockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "postponeLockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The lock in the snippet will be relocated before the invocation to - // notInlinedMethod(), i.e., after the checkpoint. We expect the instrumentation follows - // and flag will be set to true. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("expected lock was performed after checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java deleted file mode 100644 index a22ac2edb03..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Method; -import java.util.Formatter; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -import com.google.monitoring.runtime.instrumentation.common.com.google.common.base.Objects; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.printer.IdealGraphPrinter; - -import jdk.vm.ci.code.CodeCacheProvider; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class RootNameDirectiveTest extends GraalCompilerTest { - - public RootNameDirectiveTest() { - HotSpotResolvedJavaMethod rootNameAtCalleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameAtCalleeSnippet"); - rootNameAtCalleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod rootNameWithinInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameWithinInstrumentationSnippet"); - rootNameWithinInstrumentationSnippet.shouldBeInlined(); - } - - private static String toString(ResolvedJavaMethod method) { - return method.getDeclaringClass().toJavaName() + "." + method.getName() + method.getSignature().toMethodDescriptor(); - } - - public static String rootNameSnippet() { - return GraalDirectives.rootName(); - } - - @Test - public void testRootName() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootNameSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is already the root method. We expect the name of the target snippet - // is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static String rootNameAtCalleeSnippet() { - return GraalDirectives.rootName(); - } - - public static String callerSnippet() { - return rootNameAtCalleeSnippet(); - } - - @Test - public void testRootNameAtCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is the compilation root of rootNameAtCalleeSnippet() because the later - // will be inlined. We expect the name of the target snippet is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static String rootNameInCallee; - static String rootNameInCaller; - - @BytecodeParserForceInline - public static void rootNameWithinInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - rootNameInCallee = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - rootNameWithinInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - rootNameInCaller = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - private void assertEquals(StructuredGraph graph, InstalledCode code, Object expected, Object actual) { - if (!Objects.equal(expected, actual)) { - Formatter buf = new Formatter(); - - try (Scope s = Debug.sandbox("PrintingGraph", null)) { - Map properties = new HashMap<>(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - IdealGraphPrinter printer = new IdealGraphPrinter(baos, true, getSnippetReflection()); - printer.beginGroup("RootNameDirectiveTest", "RootNameDirectiveTest", graph.method(), -1, null); - properties.put("graph", graph.toString()); - properties.put("scope", Debug.currentScope()); - printer.print(graph, graph.method().format("%H.%n(%p)"), properties); - printer.endGroup(); - printer.close(); - buf.format("-- Graph -- %n%s", baos.toString()); - } catch (Throwable e) { - buf.format("%nError printing graph: %s", e); - } - try { - CodeCacheProvider codeCache = getCodeCache(); - Method disassemble = codeCache.getClass().getMethod("disassemble", InstalledCode.class); - buf.format("%n-- Code -- %n%s", disassemble.invoke(codeCache, code)); - } catch (NoSuchMethodException e) { - // Not a HotSpotCodeCacheProvider - } catch (Exception e) { - buf.format("%nError disassembling code: %s", e); - } - Assert.assertEquals(buf.toString(), expected, actual); - } - } - - @SuppressWarnings("try") - @Test - public void testRootNameWithinInstrumentationAtCallee() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - rootNameInCallee = null; - rootNameInCaller = null; - // We expect both rootName1 and rootName2 are set to the name of the target snippet. - StructuredGraph graph = parseForCompile(method); - InstalledCode code = getCode(method, graph); - code.executeVarargs(); - assertEquals(graph, code, toString(method), rootNameInCallee); - assertEquals(graph, code, rootNameInCallee, rootNameInCaller); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java deleted file mode 100644 index d8cf15a17fb..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; -import jdk.internal.org.objectweb.asm.tree.ClassNode; -import jdk.internal.org.objectweb.asm.tree.IincInsnNode; -import jdk.internal.org.objectweb.asm.tree.InsnList; -import jdk.internal.org.objectweb.asm.tree.JumpInsnNode; -import jdk.internal.org.objectweb.asm.tree.LabelNode; -import jdk.internal.org.objectweb.asm.tree.LineNumberNode; -import jdk.internal.org.objectweb.asm.tree.MethodNode; -import jdk.internal.org.objectweb.asm.tree.VarInsnNode; - -/** - * The {@code TinyInstrumentor} is a bytecode instrumentor using ASM bytecode manipulation - * framework. It injects given code snippet into a target method and creates a temporary class as - * the container. Because the target method is cloned into the temporary class, it is required that - * the target method is public static. Any referred method/field in the target method or the - * instrumentation snippet should be made public as well. - */ -public class TinyInstrumentor implements Opcodes { - - private InsnList instrumentationInstructions; - private int instrumentationMaxLocal; - - /** - * Create a instrumentor with a instrumentation snippet. The snippet is specified with the given - * class {@code instrumentationClass} and the given method name {@code methodName}. - */ - public TinyInstrumentor(Class instrumentationClass, String methodName) throws IOException { - MethodNode instrumentationMethod = getMethodNode(instrumentationClass, methodName); - assert instrumentationMethod != null; - assert (instrumentationMethod.access | ACC_STATIC) != 0; - assert "()V".equals(instrumentationMethod.desc); - instrumentationInstructions = cloneInstructions(instrumentationMethod.instructions); - instrumentationMaxLocal = instrumentationMethod.maxLocals; - // replace return instructions with a goto unless there is a single return at the end. In - // that case, simply remove the return. - List returnInstructions = new ArrayList<>(); - for (AbstractInsnNode instruction : selectAll(instrumentationInstructions)) { - if (instruction instanceof LineNumberNode) { - instrumentationInstructions.remove(instruction); - } else if (instruction.getOpcode() == RETURN) { - returnInstructions.add(instruction); - } - } - LabelNode exit = new LabelNode(); - if (returnInstructions.size() == 1) { - AbstractInsnNode returnInstruction = returnInstructions.get(0); - if (instrumentationInstructions.getLast() != returnInstruction) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - } - instrumentationInstructions.remove(returnInstruction); - } else { - for (AbstractInsnNode returnInstruction : returnInstructions) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - instrumentationInstructions.remove(returnInstruction); - } - } - instrumentationInstructions.add(exit); - } - - /** - * @return a {@link MethodNode} called {@code methodName} in the given class. - */ - private static MethodNode getMethodNode(Class clazz, String methodName) throws IOException { - ClassReader classReader = new ClassReader(clazz.getName()); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, ClassReader.SKIP_FRAMES); - - for (MethodNode methodNode : classNode.methods) { - if (methodNode.name.equals(methodName)) { - return methodNode; - } - } - return null; - } - - /** - * Create a {@link ClassNode} with empty constructor. - */ - private static ClassNode emptyClass(String name) { - ClassNode classNode = new ClassNode(); - classNode.visit(52, ACC_SUPER | ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", new String[]{}); - - MethodVisitor mv = classNode.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - return classNode; - } - - /** - * Helper method for iterating the given {@link InsnList}. - */ - private static Iterable selectAll(InsnList instructions) { - return new Iterable() { - @Override - public Iterator iterator() { - return instructions.iterator(); - } - }; - } - - /** - * Make a clone of the given {@link InsnList}. - */ - private static InsnList cloneInstructions(InsnList instructions) { - Map labelMap = new HashMap<>(); - for (AbstractInsnNode instruction : selectAll(instructions)) { - if (instruction instanceof LabelNode) { - LabelNode clone = new LabelNode(new Label()); - LabelNode original = (LabelNode) instruction; - labelMap.put(original, clone); - } - } - InsnList clone = new InsnList(); - for (AbstractInsnNode insn : selectAll(instructions)) { - clone.add(insn.clone(labelMap)); - } - return clone; - } - - /** - * Shifts all local variable slot references by a specified amount. - */ - private static void shiftLocalSlots(InsnList instructions, int offset) { - for (AbstractInsnNode insn : selectAll(instructions)) { - if (insn instanceof VarInsnNode) { - VarInsnNode varInsn = (VarInsnNode) insn; - varInsn.var += offset; - - } else if (insn instanceof IincInsnNode) { - IincInsnNode iincInsn = (IincInsnNode) insn; - iincInsn.var += offset; - } - } - } - - /** - * Instrument the target method specified by the class {@code targetClass} and the method name - * {@code methodName}. For each occurrence of the {@code opcode}, the instrumentor injects a - * copy of the instrumentation snippet. - */ - public Class instrument(Class targetClass, String methodName, int opcode) throws IOException, ClassNotFoundException { - return instrument(targetClass, methodName, opcode, true); - } - - public Class instrument(Class targetClass, String methodName, int opcode, boolean insertAfter) throws IOException, ClassNotFoundException { - // create a container class - String className = targetClass.getName() + "$$" + methodName; - ClassNode classNode = emptyClass(className); - // duplicate the target method and add to the container class - MethodNode methodNode = getMethodNode(targetClass, methodName); - MethodNode newMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, methodNode.exceptions.toArray(new String[methodNode.exceptions.size()])); - methodNode.accept(newMethodNode); - classNode.methods.add(newMethodNode); - // perform bytecode instrumentation - for (AbstractInsnNode instruction : selectAll(newMethodNode.instructions)) { - if (instruction.getOpcode() == opcode) { - InsnList instrumentation = cloneInstructions(instrumentationInstructions); - shiftLocalSlots(instrumentation, newMethodNode.maxLocals); - newMethodNode.maxLocals += instrumentationMaxLocal; - if (insertAfter) { - newMethodNode.instructions.insert(instruction, instrumentation); - } else { - newMethodNode.instructions.insertBefore(instruction, instrumentation); - } - } - } - // dump a byte array and load the class with a dedicated loader to separate the namespace - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - classNode.accept(classWriter); - byte[] bytes = classWriter.toByteArray(); - return new Loader(className, bytes).findClass(className); - } - - private static class Loader extends ExportingClassLoader { - - private String className; - private byte[] bytes; - - Loader(String className, byte[] bytes) { - super(TinyInstrumentor.class.getClassLoader()); - this.className = className; - this.bytes = bytes; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if (name.equals(className)) { - return defineClass(name, bytes, 0, bytes.length); - } else { - return super.findClass(name); - } - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java index 35bb6686845..aa23c861a4a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.api.directives; -import java.nio.charset.Charset; - // JaCoCo Exclude /** @@ -367,67 +365,4 @@ public final class GraalDirectives { */ public static void ensureVirtualizedHere(@SuppressWarnings("unused") Object object) { } - - /** - * Marks the beginning of an instrumentation boundary. The instrumentation code will be folded - * during compilation and will not affect inlining heuristics regarding graph size except one on - * compiled low-level graph size (e.g., {@code GraalOptions.SmallCompiledLowLevelGraphSize}). - */ - public static void instrumentationBegin() { - } - - /** - * Marks the beginning of an instrumentation boundary and associates the instrumentation with - * the preceding bytecode. If the instrumented instruction is {@code new}, then instrumentation - * will adapt to optimizations concerning allocation, and only be executed if allocation really - * happens. - * - * Example (the instrumentation is associated with {@code new}): - * - *
- * - *
-     *  0  new java.lang.Object
-     *  3  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationBeginForPredecessor() : void
-     *  6  invokestatic AllocationProfiler.countActualAllocation() : void
-     *  9  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationEnd() : void
-     * 12  invokespecial java.lang.Object()
-     * 
- * - *
- * - * @see #instrumentationBegin() - */ - public static void instrumentationBeginForPredecessor() { - } - - /** - * Marks the end of the instrumentation boundary. - * - * @see #instrumentationBegin() - */ - public static void instrumentationEnd() { - } - - /** - * @return true if the enclosing method is inlined. - */ - public static boolean isMethodInlined() { - return false; - } - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - /** - * @return the name of the root method for the current compilation task. If the enclosing method - * is inlined, it returns the name of the method into which it is inlined. - */ - public static String rootName() { - return new String(rawRootName(), UTF8); - } - - public static byte[] rawRootName() { - return new byte[0]; - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java index 8b904f36561..08cbae1ce6c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java @@ -54,4 +54,13 @@ public @interface Snippet { @Target(ElementType.PARAMETER) public @interface ConstantParameter { } + + /** + * Denotes a snippet parameter that will bound to a non-null value during snippet template + * instantiation. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public @interface NonNullParameter { + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java index 8bc7e55ecec..be74fd7c167 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java @@ -31,7 +31,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java index 9934218b662..9c579967920 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java @@ -226,12 +226,12 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.adds(size, dst, src1, src2, shiftType, imm); } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.subs(size, dst, src1, src2, shiftType, imm); } @@ -261,7 +261,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { super.subs(size, dst, src1, src2, extendType, shiftAmt); } @@ -336,7 +336,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { super.rbit(size, dst, src); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java index 31d07c5b9c0..8a48c423846 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.asm.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -274,7 +274,7 @@ public final class AArch64Address extends AbstractAddress { /** * @return immediate in correct representation for the given addressing mode. For example in * case of addressingMode ==IMMEDIATE_UNSCALED the value will be returned - * as the 9bit signed representation. + * as the 9-bit signed representation. */ public int getImmediate() { switch (addressingMode) { @@ -282,12 +282,15 @@ public final class AArch64Address extends AbstractAddress { case IMMEDIATE_POST_INDEXED: case IMMEDIATE_PRE_INDEXED: // 9-bit signed value + assert NumUtil.isSignedNbit(9, immediate); return immediate & NumUtil.getNbitNumberInt(9); case IMMEDIATE_SCALED: // Unsigned value can be returned as-is. + assert NumUtil.isUnsignedNbit(9, immediate); return immediate; case PC_LITERAL: // 21-bit signed value, but lower 2 bits are always 0 and are shifted out. + assert NumUtil.isSignedNbit(19, immediate >> 2); return (immediate >> 2) & NumUtil.getNbitNumberInt(19); default: throw GraalError.shouldNotReachHere("Should only be called for addressing modes that use immediate values."); @@ -356,4 +359,29 @@ public final class AArch64Address extends AbstractAddress { } } + /** + * Loads an address into Register r. + * + * @param masm the macro assembler. + * @param r general purpose register. May not be null. + */ + public void lea(AArch64MacroAssembler masm, Register r) { + switch (addressingMode) { + case IMMEDIATE_UNSCALED: + if (immediate == 0 && base.equals(r)) { // it's a nop + break; + } + masm.add(64, r, base, immediate); + break; + case REGISTER_OFFSET: + masm.add(64, r, base, offset); + break; + case PC_LITERAL: { + masm.mov(r, getImmediate()); + break; + } + default: + throw GraalError.shouldNotReachHere(); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index 02a7eb2d686..9a1f294fe7b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -111,7 +111,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import java.util.Arrays; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.debug.GraalError; @@ -347,6 +347,11 @@ public abstract class AArch64Assembler extends Assembler { return reg.encoding << RnOffset; } + private static int maskField(int sizeInBits, int n) { + assert NumUtil.isSignedNbit(sizeInBits, n); + return n & NumUtil.getNbitNumberInt(sizeInBits); + } + /** * Enumeration of all different instruction kinds: General32/64 are the general instructions * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for @@ -448,7 +453,7 @@ public abstract class AArch64Assembler extends Assembler { private static final int LoadStoreFpFlagOffset = 26; private static final int LoadLiteralImmeOffset = 5; - private static final int LoadStorePairOp = 0b101_0_010 << 23; + private static final int LoadStorePairOp = 0b101_0 << 26; @SuppressWarnings("unused") private static final int LoadStorePairPostIndexOp = 0b101_0_001 << 23; @SuppressWarnings("unused") private static final int LoadStorePairPreIndexOp = 0b101_0_011 << 23; private static final int LoadStorePairImm7Offset = 15; @@ -978,7 +983,9 @@ public abstract class AArch64Assembler extends Assembler { } /** - * + * Load Pair of Registers calculates an address from a base register value and an immediate + * offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from + * two registers. */ public void ldp(int size, Register rt, Register rt2, AArch64Address address) { assert size == 32 || size == 64; @@ -996,10 +1003,18 @@ public abstract class AArch64Assembler extends Assembler { } private void loadStorePairInstruction(Instruction instr, Register rt, Register rt2, AArch64Address address, InstructionType type) { - int memop = type.encoding | instr.encoding | address.getImmediate() << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); + int scaledOffset = maskField(7, address.getImmediateRaw()); // LDP/STP use a 7-bit scaled + // offset + int memop = type.encoding | instr.encoding | scaledOffset << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); switch (address.getAddressingMode()) { - case IMMEDIATE_UNSCALED: - emitInt(memop | LoadStorePairOp); + case IMMEDIATE_SCALED: + emitInt(memop | LoadStorePairOp | (0b010 << 23)); + break; + case IMMEDIATE_POST_INDEXED: + emitInt(memop | LoadStorePairOp | (0b001 << 23)); + break; + case IMMEDIATE_PRE_INDEXED: + emitInt(memop | LoadStorePairOp | (0b011 << 23)); break; default: throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode()); @@ -1471,7 +1486,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(ADDS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1499,7 +1514,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(SUBS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1571,7 +1586,7 @@ public abstract class AArch64Assembler extends Assembler { * @param extendType defines how src2 is extended to the same size as src1. * @param shiftAmt must be in range 0 to 4. */ - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { assert !dst.equals(sp); assert !src1.equals(zr); assert !src2.equals(sp); @@ -1786,7 +1801,7 @@ public abstract class AArch64Assembler extends Assembler { * @param dst general purpose register. May not be null, zero-register or the stackpointer. * @param src source register. May not be null, zero-register or the stackpointer. */ - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { dataProcessing1SourceOp(RBIT, dst, src, generalFromSize(size)); } @@ -1934,7 +1949,7 @@ public abstract class AArch64Assembler extends Assembler { * @param src2 general purpose register. May not be null or the stackpointer. * @param src3 general purpose register. May not be null or the stackpointer. */ - protected void smaddl(Register dst, Register src1, Register src2, Register src3) { + public void smaddl(Register dst, Register src1, Register src2, Register src3) { assert !dst.equals(sp); assert !src1.equals(sp); assert !src2.equals(sp); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 7c0d184e02c..d948f868771 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -39,7 +39,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -196,6 +196,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_INDEX: newIndex = allowOverwrite ? index : additionalReg; + assert !newIndex.equals(sp) && !newIndex.equals(zr); if (plan.needsScratch) { mov(additionalReg, scaledDisplacement); add(signExtendIndex ? 32 : 64, newIndex, index, additionalReg); @@ -206,6 +207,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_BASE: newBase = allowOverwrite ? base : additionalReg; + assert !newBase.equals(sp) && !newBase.equals(zr); if (plan.needsScratch) { mov(additionalReg, displacement); add(64, newBase, base, additionalReg); @@ -411,6 +413,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { assert !firstMove; } + /** + * Generates a 32-bit immediate move code sequence. The immediate may later be updated by + * HotSpot. + * + * @param dst general purpose register. May not be null, stackpointer or zero-register. + * @param imm + */ + public void movNarrowAddress(Register dst, long imm) { + assert (imm & 0xFFFF_FFFF_0000_0000L) == 0; + movz(64, dst, (int) (imm >>> 16), 16); + movk(64, dst, (int) (imm & 0xffff), 0); + } + /** * @return Number of instructions necessary to load immediate into register. */ @@ -455,6 +470,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { } } + /** + * Loads a srcSize value from address into rt zero-extending it if necessary. + * + * @param srcSize size of memory read in bits. Must be 8, 16 or 32 and smaller or equal to + * targetSize. + * @param rt general purpose register. May not be null or stackpointer. + * @param address all addressing modes allowed. May not be null. + */ + @Override + public void ldr(int srcSize, Register rt, AArch64Address address) { + super.ldr(srcSize, rt, address); + } + /** * Conditional move. dst = src1 if condition else src2. * @@ -482,52 +510,47 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 + src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void add(int size, Register dst, Register src1, Register src2) { - super.add(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.add(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.add(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 + src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void adds(int size, Register dst, Register src1, Register src2) { - super.adds(size, dst, src1, src2, getNopExtendType(size), 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.adds(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.adds(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 - src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void subs(int size, Register dst, Register src1, Register src2) { - super.subs(size, dst, src1, src2, getNopExtendType(size), 0); - } - - /** - * Returns the ExtendType for the given size that corresponds to a no-op. - * - * I.e. when doing add X0, X1, X2, the actual instruction has the form add X0, X1, X2 UXTX. - * - * @param size - */ - private static ExtendType getNopExtendType(int size) { - if (size == 64) { - return ExtendType.UXTX; - } else if (size == 32) { - return ExtendType.UXTW; + if (dst.equals(sp) || src1.equals(sp)) { + super.subs(size, dst, src1, src2, ExtendType.UXTX, 0); } else { - throw GraalError.shouldNotReachHere("No-op "); + super.subs(size, dst, src1, src2, ShiftType.LSL, 0); } } @@ -535,12 +558,16 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 - src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void sub(int size, Register dst, Register src1, Register src2) { - super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.sub(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** @@ -590,16 +617,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src + immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void add(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { sub(size, dst, src, -immediate); - } else if (!(dst.equals(src) && immediate == 0)) { - super.add(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.add(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.add(size, dst, src, immediate & -(1 << 12)); + super.add(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + add(size, src, dst, dst); } } @@ -613,6 +650,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void adds(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { subs(size, dst, src, -immediate); } else if (!(dst.equals(src) && immediate == 0)) { @@ -624,16 +662,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src - immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void sub(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { add(size, dst, src, -immediate); - } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.sub(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.sub(size, dst, src, immediate & -(1 << 12)); + super.sub(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + sub(size, src, dst, dst); } } @@ -647,10 +695,11 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void subs(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { adds(size, dst, src, -immediate); } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + super.subs(size, dst, src, immediate); } } @@ -675,6 +724,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void umulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.umulh(dst, src1, src2); @@ -695,6 +745,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void smulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.smulh(dst, src1, src2); @@ -715,6 +766,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param d denominator. General purpose register. Divisor May not be null or the stackpointer. */ public void rem(int size, Register dst, Register n, Register d) { + assert (!dst.equals(sp) && !n.equals(sp) && !d.equals(sp)); // There is no irem or similar instruction. Instead we use the relation: // n % d = n - Floor(n / d) * d if nd >= 0 // n % d = n - Ceil(n / d) * d else @@ -940,16 +992,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { /** * Sign-extend value from src into dst. * - * @param destSize destination register size. Has to be 32 or 64. - * @param srcSize source register size. May be 8, 16 or 32 and smaller than destSize. + * @param destSize destination register size. Must be 32 or 64. + * @param srcSize source register size. Must be smaller than destSize. * @param dst general purpose register. May not be null, stackpointer or zero-register. * @param src general purpose register. May not be null, stackpointer or zero-register. */ public void sxt(int destSize, int srcSize, Register dst, Register src) { - assert (destSize == 32 || destSize == 64) && srcSize < destSize; - assert srcSize == 8 || srcSize == 16 || srcSize == 32; - int[] srcSizeValues = {7, 15, 31}; - super.sbfm(destSize, dst, src, 0, srcSizeValues[NumUtil.log2Ceil(srcSize / 8)]); + assert (srcSize < destSize && srcSize > 0); + super.sbfm(destSize, dst, src, 0, srcSize - 1); } /** @@ -1078,6 +1128,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y general purpose register. May not be null or stackpointer. */ public void cmp(int size, Register x, Register y) { + assert size == 32 || size == 64; super.subs(size, zr, x, y, ShiftType.LSL, 0); } @@ -1089,6 +1140,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y comparison immediate, {@link #isComparisonImmediate(long)} has to be true for it. */ public void cmp(int size, Register x, int y) { + assert size == 32 || size == 64; if (y < 0) { super.adds(size, zr, x, -y); } else { @@ -1108,6 +1160,54 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.ands(size, dst, x, y, ShiftType.LSL, 0); } + /** + * Sets overflow flag according to result of x * y. + * + * @param size register size. Has to be 32 or 64. + * @param dst general purpose register. May not be null or stack-pointer. + * @param x general purpose register. May not be null or stackpointer. + * @param y general purpose register. May not be null or stackpointer. + */ + public void mulvs(int size, Register dst, Register x, Register y) { + try (ScratchRegister sc1 = getScratchRegister(); + ScratchRegister sc2 = getScratchRegister()) { + switch (size) { + case 64: { + // Be careful with registers: it's possible that x, y, and dst are the same + // register. + Register rscratch1 = sc1.getRegister(); + Register rscratch2 = sc2.getRegister(); + mul(64, rscratch1, x, y); // Result bits 0..63 + smulh(64, rscratch2, x, y); // Result bits 64..127 + // Top is pure sign ext + subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63); + // Copy all 64 bits of the result into dst + mov(64, dst, rscratch1); + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + case 32: { + Register rscratch1 = sc1.getRegister(); + smaddl(rscratch1, x, y, zr); + // Copy the low 32 bits of the result into dst + mov(32, dst, rscratch1); + subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0); + // NE => overflow + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + } + } + } + /** * When patching up Labels we have to know what kind of code to generate. */ @@ -1353,7 +1453,8 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.b(branchOffset, branch); break; case JUMP_ADDRESS: - emitInt(jumpTarget, branch); + int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET; + emitInt(jumpTarget - offset, branch); break; case BRANCH_NONZERO: case BRANCH_ZERO: { @@ -1404,4 +1505,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { public AbstractAddress getPlaceholder(int instructionStartPosition) { return AArch64Address.PLACEHOLDER; } + + /** + * Loads an address into Register d. + * + * @param d general purpose register. May not be null. + * @param a AArch64Address the address of an operand. + */ + public void lea(Register d, AArch64Address a) { + a.lea(this, d); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java index 1ff59f79536..7b5bec18025 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java @@ -65,6 +65,18 @@ public final class AMD64Address extends AbstractAddress { this(base, Register.None, Scale.Times1, displacement); } + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and 0 + * displacement. + * + * @param base the base register + * @param index the index register + * @param scale the scaling factor + */ + public AMD64Address(Register base, Register index, Scale scale) { + this(base, index, scale, 0, -1); + } + /** * Creates an {@link AMD64Address} with given base and index registers, scaling and * displacement. This is the most general constructor. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index a69eb78cd50..2c09ced0b80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.asm.amd64; -import static org.graalvm.compiler.asm.NumUtil.isByte; -import static org.graalvm.compiler.asm.NumUtil.isInt; -import static org.graalvm.compiler.asm.NumUtil.isShiftCount; -import static org.graalvm.compiler.asm.NumUtil.isUByte; +import static org.graalvm.compiler.core.common.NumUtil.isByte; +import static org.graalvm.compiler.core.common.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isShiftCount; +import static org.graalvm.compiler.core.common.NumUtil.isUByte; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; @@ -58,7 +58,7 @@ import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; @@ -2494,6 +2494,24 @@ public class AMD64Assembler extends Assembler { emitByte(0xC0 | encode); } + void pcmpestri(Register dst, AMD64Address src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitOperandHelper(dst, src, 0); + emitByte(imm8); + } + + void pcmpestri(Register dst, Register src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void push(Register src) { int encode = prefixAndEncode(src.encoding); emitByte(0x50 | encode); @@ -2633,6 +2651,16 @@ public class AMD64Assembler extends Assembler { emitByte(imm8); } + public final void psrldq(Register dst, int imm8) { + assert isUByte(imm8) : "invalid value"; + assert dst.getRegisterCategory().equals(AMD64.XMM); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(AMD64.xmm3, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x73); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void pshufd(Register dst, Register src, int imm8) { assert isUByte(imm8) : "invalid value"; assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); @@ -3322,6 +3350,13 @@ public class AMD64Assembler extends Assembler { } } + public final void movdl(Register dst, AMD64Address src) { + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x6E); + emitOperandHelper(dst, src, 0); + } + public final void movddup(Register dst, Register src) { assert supports(CPUFeature.SSE3); assert dst.getRegisterCategory().equals(AMD64.XMM); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java index fc4f7e74edc..36995bf6853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java @@ -22,11 +22,17 @@ */ package org.graalvm.compiler.asm.amd64; +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.amd64.AMD64.rsp; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -138,6 +144,10 @@ public class AMD64MacroAssembler extends AMD64Assembler { cmpq(src1, src2); } + public final void decrementl(Register reg) { + decrementl(reg, 1); + } + public final void decrementl(Register reg, int value) { if (value == Integer.MIN_VALUE) { subl(reg, value); @@ -321,4 +331,434 @@ public class AMD64MacroAssembler extends AMD64Assembler { movdbl(dest, tmp); addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); } + + // IndexOf for constant substrings with size >= 8 chars + // which don't need to be loaded through stack. + public void stringIndexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp) { + // assert(UseSSE42Intrinsics, "SSE4.2 is required"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label exit = new Label(); + Label foundSubstr = new Label(); + Label matchSubstrHead = new Label(); + Label reloadStr = new Label(); + Label foundCandidate = new Label(); + + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars"; + + // Load substring. + movdqu(vec, new AMD64Address(str2, 0)); + movl(cnt2, intCnt2); + movq(result, str1); // string addr + + if (intCnt2 > 8) { + jmpb(scanToSubstr); + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + negq(cnt2); // Jumped here with negative cnt2, convert to positive + + bind(reloadStr); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + + // cnt2 is number of substring reminding elements and + // cnt1 is number of string reminding elements when cmp failed. + // Restored cnt1 = cnt1 - cnt2 + int_cnt2 + subl(cnt1, cnt2); + addl(cnt1, intCnt2); + movl(cnt2, intCnt2); // Now restore cnt2 + + decrementl(cnt1, 1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + + } // (int_cnt2 > 8) + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // Matched whole vector if first element matched (tmp(rcx) == 0). + if (intCnt2 == 8) { + jccb(ConditionFlag.Overflow, retFound); // OF == 1 + } else { // int_cnt2 > 8 + jccb(ConditionFlag.Overflow, foundSubstr); + } + // After pcmpestri tmp(rcx) contains matched element index + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0)); + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + if (intCnt2 == 8) { + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + } else { // int_cnt2 > 8 + jccb(ConditionFlag.GreaterEqual, matchSubstrHead); + } + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(exit); + + if (intCnt2 > 8) { + // This code is optimized for the case when whole substring + // is matched if its head is matched. + bind(matchSubstrHead); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + // Reload only string if does not match + jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0 + + Label contScanSubstr = new Label(); + // Compare the rest of substring (> 8 chars). + bind(foundSubstr); + // First 8 chars are already matched. + negq(cnt2); + addq(cnt2, 8); + + bind(scanSubstr); + subl(cnt1, 8); + cmpl(cnt2, -8); // Do not read beyond substring + jccb(ConditionFlag.LessEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring: + // cnt1 = cnt1 - cnt2 + 8 + addl(cnt1, cnt2); // cnt2 is negative + addl(cnt1, 8); + movl(cnt2, 8); + negq(cnt2); + bind(contScanSubstr); + if (intCnt2 < 1024 * 1024 * 1024) { + movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2)); + pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d); + } else { + // calculate index in register to avoid integer overflow (int_cnt2*2) + movl(tmp, intCnt2); + addq(tmp, cnt2); + movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0)); + pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d); + } + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + addq(cnt2, 8); + jcc(ConditionFlag.Negative, scanSubstr); + // Fall through if found full substring + + } // (int_cnt2 > 8) + + bind(retFound); + // Found result if we matched full small substring. + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + bind(exit); + + } // string_indexofC8 + + // Small strings are loaded through stack if they cross page boundary. + public void stringIndexOf(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp, int vmPageSize) { + // + // int_cnt2 is length of small (< 8 chars) constant substring + // or (-1) for non constant substring in which case its length + // is in cnt2 register. + // + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + // + assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0"; + + // This method uses pcmpestri instruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label adjustStr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label cleanup = new Label(); + Label foundSubstr = new Label(); + Label foundCandidate = new Label(); + + int wordSize = 8; + // We don't know where these strings are located + // and we can't read beyond them. Load them through stack. + Label bigStrings = new Label(); + Label checkStr = new Label(); + Label copySubstr = new Label(); + Label copyStr = new Label(); + + movq(tmp, rsp); // save old SP + + if (intCnt2 > 0) { // small (< 8 chars) constant substring + if (intCnt2 == 1) { // One char + movzwl(result, new AMD64Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (intCnt2 == 2) { // Two chars + movdl(vec, new AMD64Address(str2, 0)); // move 32 bits + } else if (intCnt2 == 4) { // Four chars + movq(vec, new AMD64Address(str2, 0)); // move 64 bits + } else { // cnt2 = { 3, 5, 6, 7 } + // Array header size is 12 bytes in 32-bit VM + // + 6 bytes for 3 chars == 18 bytes, + // enough space to load vec and shift. + movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16)); + psrldq(vec, 16 - (intCnt2 * 2)); + } + } else { // not constant substring + cmpl(cnt2, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough + + // We can read beyond string if str+16 does not cross page boundary + // since heaps are aligned and mapped by pages. + assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small"; + movl(result, str2); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, checkStr); + + // Move small strings to stack to allow load 16 bytes into vec. + subq(rsp, 16); + int stackOffset = wordSize - 2; + push(cnt2); + + bind(copySubstr); + movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copySubstr); + + pop(cnt2); + movq(str2, rsp); // New substring address + } // non constant + + bind(checkStr); + cmpl(cnt1, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); + + // Check cross page boundary. + movl(result, str1); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, bigStrings); + + subq(rsp, 16); + int stackOffset = -2; + if (intCnt2 < 0) { // not constant + push(cnt2); + stackOffset += wordSize; + } + movl(cnt2, cnt1); + + bind(copyStr); + movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copyStr); + + if (intCnt2 < 0) { // not constant + pop(cnt2); + } + movq(str1, rsp); // New string address + + bind(bigStrings); + // Load substring. + if (intCnt2 < 0) { // -1 + movdqu(vec, new AMD64Address(str2, 0)); + push(cnt2); // substr count + push(str2); // substr addr + push(str1); // string addr + } else { + // Small (< 8 chars) constant substrings are loaded already. + movl(cnt2, intCnt2); + } + push(tmp); // original SP + // Finished loading + + // ======================================================== + // Start search + // + + movq(result, str1); // string addr + + if (intCnt2 < 0) { // Only for non constant substring + jmpb(scanToSubstr); + + // SP saved at sp+0 + // String saved at sp+1*wordSize + // Substr saved at sp+2*wordSize + // Substr count saved at sp+3*wordSize + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movq(str2, new AMD64Address(rsp, 2 * wordSize)); + movl(cnt2, new AMD64Address(rsp, 3 * wordSize)); + movdqu(vec, new AMD64Address(str2, 0)); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + subq(str1, result); // Restore counter + shrl(str1, 1); + addl(cnt1, str1); + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + } // non constant + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + + bind(adjustStr); + cmpl(cnt1, 8); // Do not read beyond string + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + // Back-up string to avoid reading beyond string. + leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16)); + movl(cnt1, 8); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // After pcmpestri tmp(rcx) contains matched element index + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + jccb(ConditionFlag.GreaterEqual, foundSubstr); + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(cleanup); + + bind(foundSubstr); + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2)); + + if (intCnt2 > 0) { // Constant substring + // Repeat search for small substring (< 8 chars) + // from new point without reloading substring. + // Have to check that we don't read beyond string. + cmpl(tmp, 8 - intCnt2); + jccb(ConditionFlag.Greater, adjustStr); + // Fall through if matched whole substring. + } else { // non constant + assert intCnt2 == -1 : "should be != 0"; + + addl(tmp, cnt2); + // Found result if we matched whole substring. + cmpl(tmp, 8); + jccb(ConditionFlag.LessEqual, retFound); + + // Repeat search for small substring (<= 8 chars) + // from new point 'str1' without reloading substring. + cmpl(cnt2, 8); + // Have to check that we don't read beyond string. + jccb(ConditionFlag.LessEqual, adjustStr); + + Label checkNext = new Label(); + Label contScanSubstr = new Label(); + Label retFoundLong = new Label(); + // Compare the rest of substring (> 8 chars). + movq(str1, result); + + cmpl(tmp, cnt2); + // First 8 chars are already matched. + jccb(ConditionFlag.Equal, checkNext); + + bind(scanSubstr); + pcmpestri(vec, new AMD64Address(str1, 0), 0x0d); + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + + bind(checkNext); + subl(cnt2, 8); + jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring + addq(str1, 16); + addq(str2, 16); + subl(cnt1, 8); + cmpl(cnt2, 8); // Do not read beyond substring + jccb(ConditionFlag.GreaterEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring. + leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16)); + leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16)); + subl(cnt1, cnt2); + movl(cnt2, 8); + addl(cnt1, 8); + bind(contScanSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + jmpb(scanSubstr); + + bind(retFoundLong); + movq(str1, new AMD64Address(rsp, wordSize)); + } // non constant + + bind(retFound); + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + + bind(cleanup); + pop(rsp); // restore SP + + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java index 68cde9dcfdf..030bed71421 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java @@ -135,8 +135,8 @@ import java.util.Map; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.Register; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java index a7c1fb03087..240ff033074 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java @@ -26,8 +26,6 @@ import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCo import java.lang.reflect.Method; -import org.junit.Assert; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.DisassemblerProvider; @@ -36,10 +34,12 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; +import org.junit.Assert; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -52,6 +52,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCIBackend; +@AddExports("jdk.internal.vm.ci/jdk.vm.ci.runtime") public abstract class AssemblerTest extends GraalTest { private final MetaAccessProvider metaAccess; @@ -62,6 +63,14 @@ public abstract class AssemblerTest extends GraalTest { byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); } + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + public AssemblerTest() { JVMCIBackend providers = JVMCI.getRuntime().getHostJVMCIBackend(); this.metaAccess = providers.getMetaAccess(); @@ -79,7 +88,8 @@ public abstract class AssemblerTest extends GraalTest { try (Scope s = Debug.scope("assembleMethod", method, codeCache)) { RegisterConfig registerConfig = codeCache.getRegisterConfig(); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); - CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, new StructuredGraph(method, AllowAssumptions.NO, compilationId), null).getCallingConvention(); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).compilationId(compilationId).build(); + CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); CompilationResult compResult = new CompilationResult(); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java index d6df78393ea..4d8c3ea1cbb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.asm; +import org.graalvm.compiler.core.common.NumUtil; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index ba1267bca4b..57e476fc08e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Objects; import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; @@ -363,9 +364,10 @@ public class CompilationResult { * * @param accessedFields the collected set of fields accessed during compilation */ - public void setFields(Collection accessedFields) { - assert accessedFields != null; - fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + public void setFields(EconomicSet accessedFields) { + if (accessedFields != null) { + fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java index d28ab09afd2..96570b3cb09 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.code; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; /** * Represents a bailout exception with a stack trace in terms of the Java source being compiled diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java index 176480dd2a5..d9fc4f47c5f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java @@ -90,6 +90,7 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, displacement, scaled, addressingMode)); } + @Override public ValueNode getBase() { return base; } @@ -102,6 +103,7 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -121,4 +123,9 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { public void setDisplacement(int displacement) { this.displacement = displacement; } + + @Override + public long getMaxConstantDisplacement() { + return Long.MAX_VALUE; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 786b6692aa6..aee507d5e24 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -23,13 +23,16 @@ package org.graalvm.compiler.core.aarch64; -import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; -import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.aarch64.AArch64Kind.DWORD; import static jdk.vm.ci.aarch64.AArch64Kind.QWORD; +import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.FloatConvert; @@ -41,12 +44,12 @@ import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp; -import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode; import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp; import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp; +import org.graalvm.compiler.lir.aarch64.AArch64Unary; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.vm.ci.aarch64.AArch64Kind; @@ -91,11 +94,30 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } } + protected Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) { + // Issue a zero extending load of the proper bit size and set the result to + // the proper kind. + Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD)); + + int targetSize = resultBits <= 32 ? 32 : 64; + switch (memoryKind) { + case BYTE: + case WORD: + case DWORD: + case QWORD: + getLIRGen().append(new AArch64Unary.MemoryOp(isSigned, targetSize, + memoryKind.getSizeInBytes() * 8, result, address, state)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + return result; + } + @Override public Value emitMul(Value a, Value b, boolean setFlags) { - // TODO (das) setFlags handling - should be handled higher up. Ask for ideas at mailing list - assert !setFlags : "Set flags on multiplication is not supported"; - return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.MUL, AArch64ArithmeticOp.FMUL), true, a, b); + AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL; + return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b); } @Override @@ -223,7 +245,7 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; } @@ -235,11 +257,21 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + LIRKind resultKind = getResultLirKind(toBits, inputVal); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; + } else if (isJavaConstant(inputVal)) { + JavaConstant javaConstant = asJavaConstant(inputVal); + long constant; + if (javaConstant.isNull()) { + constant = 0; + } else { + constant = javaConstant.asLong(); + } + int shiftCount = QWORD.getSizeInBytes() * 8 - fromBits; + return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); } - LIRKind resultKind = getResultLirKind(toBits, inputVal); Variable result = getLIRGen().newVariable(resultKind); getLIRGen().append(new AArch64SignExtendOp(result, getLIRGen().asAllocatable(inputVal), fromBits, toBits)); return result; @@ -249,7 +281,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem if (resultBitSize == 64) { return LIRKind.combine(inputValues).changeType(QWORD); } else { - assert resultBitSize == 32; + // FIXME: I have no idea what this assert was ever for + // assert resultBitSize == 32; return LIRKind.combine(inputValues).changeType(DWORD); } } @@ -352,8 +385,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanForward(Value inputVal) { - return emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode.BSF, inputVal); + public Variable emitBitScanForward(Value value) { + throw GraalError.unimplemented(); } @Override @@ -362,27 +395,23 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanReverse(Value inputVal) { - // TODO (das) old implementation said to use emitCountLeadingZeros instead - need extra node - // for that though - return emitBitManipulation(BitManipulationOpCode.BSR, inputVal); + public Value emitBitScanReverse(Value value) { + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(BSR, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountLeadingZeros(Value value) { - return emitBitManipulation(BitManipulationOpCode.CLZ, value); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountTrailingZeros(Value value) { - throw GraalError.unimplemented(); - } - - private Variable emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode op, Value inputVal) { - assert isNumericInteger(inputVal.getPlatformKind()); - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new AArch64BitManipulationOp(op, result, input)); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, getLIRGen().asAllocatable(value))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java index 03e777a2aa8..952fa97f5ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java @@ -42,11 +42,14 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; +import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp; +import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Compare; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp; @@ -56,6 +59,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; @@ -121,8 +125,19 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + Variable prevValue = newVariable(expectedValue.getValueKind()); + Variable scratch = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new CompareAndSwapOp(prevValue, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); + assert trueValue.getValueKind().equals(falseValue.getValueKind()); Variable result = newVariable(trueValue.getValueKind()); + append(new CondMoveOp(result, ConditionFlag.EQ, asAllocatable(trueValue), asAllocatable(falseValue))); + return result; + } + + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + Variable result = newVariable(newValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); return result; @@ -271,13 +286,25 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { boolean mirrored; AArch64Kind kind = (AArch64Kind) cmpKind; if (kind.isInteger()) { - if (LIRValueUtil.isVariable(b)) { - left = load(b); - right = loadNonConst(a); + Value aExt = a; + Value bExt = b; + + int compareBytes = cmpKind.getSizeInBytes(); + // AArch64 compares 32 or 64 bits: sign extend a and b as required. + if (compareBytes < a.getPlatformKind().getSizeInBytes()) { + aExt = arithmeticLIRGen.emitSignExtend(a, compareBytes * 8, 64); + } + if (compareBytes < b.getPlatformKind().getSizeInBytes()) { + bExt = arithmeticLIRGen.emitSignExtend(b, compareBytes * 8, 64); + } + + if (LIRValueUtil.isVariable(bExt)) { + left = load(bExt); + right = loadNonConst(aExt); mirrored = true; } else { - left = load(a); - right = loadNonConst(b); + left = load(aExt); + right = loadNonConst(bExt); mirrored = false; } append(new AArch64Compare.CompareOp(left, loadNonCompareConst(right))); @@ -367,7 +394,7 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { assert ((AArch64Kind) left.getPlatformKind()).isInteger() && ((AArch64Kind) right.getPlatformKind()).isInteger(); assert ((AArch64Kind) trueValue.getPlatformKind()).isInteger() && ((AArch64Kind) falseValue.getPlatformKind()).isInteger(); - ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(trueValue.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); + ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(left.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); Variable result = newVariable(trueValue.getValueKind()); append(new CondMoveOp(result, ConditionFlag.EQ, load(trueValue), load(falseValue))); return result; @@ -385,22 +412,21 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - // Make copy of key since the TableSwitch destroys its input. - Variable tmp = emitMove(key); - Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); - append(new AArch64ControlFlow.TableSwitchOp(lowKey, defaultTarget, targets, tmp, scratch)); + append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind()))); } @Override - public Variable emitByteSwap(Value operand) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + public Variable emitByteSwap(Value input) { + Variable result = newVariable(LIRKind.combine(input)); + append(new AArch64ByteSwapOp(result, input)); + return result; } @Override public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length))); + return result; } @Override @@ -443,4 +469,6 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public void emitPause() { append(new AArch64PauseOp()); } + + public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java index fe042027b37..0a4a962f4d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java @@ -86,21 +86,25 @@ public class AArch64MoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return AArch64MacroAssembler.isMovableImmediate(c.asInt()); - case Long: - return AArch64MacroAssembler.isMovableImmediate(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return AArch64MacroAssembler.isMovableImmediate(c.asInt()); + case Long: + return AArch64MacroAssembler.isMovableImmediate(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index b99cd62bdad..1343565bc71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -24,9 +24,14 @@ package org.graalvm.compiler.core.aarch64; import org.graalvm.compiler.core.gen.NodeMatchRules; +import org.graalvm.compiler.core.match.ComplexMatchResult; +import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.calc.SignExtendNode; +import org.graalvm.compiler.nodes.calc.ZeroExtendNode; import org.graalvm.compiler.nodes.memory.Access; import jdk.vm.ci.aarch64.AArch64Kind; @@ -56,4 +61,18 @@ public class AArch64NodeMatchRules extends NodeMatchRules { protected AArch64ArithmeticLIRGenerator getArithmeticLIRGenerator() { return (AArch64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic(); } + + @MatchRule("(ZeroExtend Read=access)") + @MatchRule("(ZeroExtend FloatingRead=access)") + public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { + AArch64Kind memoryKind = getMemoryKind(access); + return builder -> getArithmeticLIRGenerator().emitExtendMemory(false, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access)); + } + + @MatchRule("(SignExtend Read=access)") + @MatchRule("(SignExtend FloatingRead=access)") + public ComplexMatchResult signExtend(SignExtendNode root, Access access) { + AArch64Kind memoryKind = getMemoryKind(access); + return builder -> getArithmeticLIRGenerator().emitExtendMemory(true, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access)); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java index 0904f9ce409..c95707da994 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java @@ -38,8 +38,8 @@ public class AMD64AllocatorTest extends AllocatorTest { @Before public void checkAMD64() { assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java index a1384c11e43..7a6c0505481 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java @@ -24,22 +24,23 @@ package org.graalvm.compiler.core.amd64.test; import static org.junit.Assume.assumeTrue; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.jtt.LIRTest; import org.graalvm.compiler.lir.phases.LIRPhase; +import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; public class MatchRuleTest extends LIRTest { - private static LIR lir; + private LIR lir; @Before public void checkAMD64() { @@ -54,13 +55,19 @@ public class MatchRuleTest extends LIRTest { } } + @Override + protected LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = super.createLIRSuites(options); + suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); + return suites; + } + /** * Verifies, if the match rules in AMD64NodeMatchRules do work on the graphs by compiling and * checking if the expected LIR instruction show up. */ @Test public void test1() { - getLIRSuites().getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); compile(getResolvedJavaMethod("test1Snippet"), null); boolean found = false; for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { @@ -83,7 +90,7 @@ public class MatchRuleTest extends LIRTest { } } - public static class CheckPhase extends LIRPhase { + public class CheckPhase extends LIRPhase { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { lir = lirGenRes.getLIR(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index a43d03467b1..567a826055f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.core.amd64; import jdk.vm.ci.meta.JavaConstant; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.nodes.ValueNode; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java index 1281418aece..7d278ff43db 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java @@ -87,6 +87,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement)); } + @Override public ValueNode getBase() { return base; } @@ -99,6 +100,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -126,4 +128,9 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { public void setDisplacement(int displacement) { this.displacement = displacement; } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 4eba24888a6..0971cf54b71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -74,7 +74,7 @@ import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntr import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP; import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; @@ -1234,7 +1234,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen return; } else if (c instanceof VMConstant) { VMConstant vc = (VMConstant) c; - if (size == DWORD && !GeneratePIC.getValue()) { + if (size == DWORD && !GeneratePIC.getValue(getOptions())) { getLIRGen().append(new AMD64BinaryConsumer.VMConstOp(CMP.getMIOpcode(DWORD, false), left, vc)); } else { getLIRGen().append(new AMD64BinaryConsumer.DataOp(CMP.getRMOpcode(size), size, left, vc)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index f9d2f5c8e62..e207f830464 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.core.amd64; +import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; @@ -31,10 +32,10 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; -import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -72,6 +73,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp; import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp; import org.graalvm.compiler.lir.amd64.AMD64PauseOp; +import org.graalvm.compiler.lir.amd64.AMD64StringIndexOfOp; import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp; import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -112,10 +114,8 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { protected static final boolean canStoreConstant(JavaConstant c) { // there is no immediate move of 64-bit constants on Intel switch (c.getJavaKind()) { - case Long: { - long l = c.asLong(); - return (int) l == l; - } + case Long: + return NumUtil.isInt(c.asLong()); case Double: return false; case Object: @@ -183,7 +183,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); @@ -199,6 +199,33 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + @Override + public Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + + AMD64AddressValue addressValue = asAddressValue(address); + RegisterValue raxRes = AMD64.rax.asValue(kind); + emitMove(raxRes, expectedValue); + append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); + Variable result = newVariable(kind); + emitMove(result, raxRes); + return result; + } + + public void emitCompareAndSwapBranch(ValueKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability) { + assert kind.equals(expectedValue.getValueKind()); + assert kind.equals(newValue.getValueKind()); + assert condition == Condition.EQ || condition == Condition.NE; + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + RegisterValue raxValue = AMD64.rax.asValue(kind); + emitMove(raxValue, expectedValue); + append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, asAllocatable(newValue))); + append(new BranchOp(condition, trueLabel, falseLabel, trueLabelProbability)); + } + @Override public Value emitAtomicReadAndAdd(Value address, Value delta) { ValueKind kind = delta.getValueKind(); @@ -329,7 +356,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { throw GraalError.shouldNotReachHere("unexpected kind: " + cmpKind); } - if (isJavaConstant(a)) { + if (isConstantValue(a)) { return emitCompareMemoryConOp(size, asConstantValue(a), b, state); } else { return emitCompareRegMemoryOp(size, asAllocatable(a), b, state); @@ -399,7 +426,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { long maxOffset = linkage.getMaxCallTargetOffset(); - if (maxOffset != (int) maxOffset && !GeneratePIC.getValue()) { + if (maxOffset != (int) maxOffset && !GeneratePIC.getValue(getResult().getLIR().getOptions())) { append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info)); } else { append(new AMD64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info)); @@ -420,6 +447,24 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + /** + * Return a conservative estimate of the page size for use by the String.indexOf intrinsic. + */ + protected int getVMPageSize() { + return 4096; + } + + @Override + public Variable emitStringIndexOf(Value source, Value sourceCount, Value target, Value targetCount, int constantTargetCount) { + Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); + RegisterValue cnt1 = AMD64.rdx.asValue(sourceCount.getValueKind()); + emitMove(cnt1, sourceCount); + RegisterValue cnt2 = AMD64.rax.asValue(targetCount.getValueKind()); + emitMove(cnt2, targetCount); + append(new AMD64StringIndexOfOp(this, result, source, target, cnt1, cnt2, AMD64.rcx.asValue(), AMD64.xmm0.asValue(), constantTargetCount, getVMPageSize())); + return result; + } + @Override public void emitReturn(JavaKind kind, Value input) { AllocatableValue operand = Value.ILLEGAL; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java index fb767ee07fe..23904826487 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java @@ -28,7 +28,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; @@ -54,15 +54,19 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Long: - return NumUtil.isInt(c.asLong()); - case Object: - return c.isNull(); - default: - return true; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Long: + return NumUtil.isInt(c.asLong()); + case Object: + return c.isNull(); + default: + return true; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java index 2ff74388f70..198998ae652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java @@ -26,15 +26,14 @@ package org.graalvm.compiler.core.amd64; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; -import java.util.HashMap; -import java.util.Map; - import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Architecture; @@ -61,7 +60,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { public static final class BackupSlotProvider { private final FrameMapBuilder frameMapBuilder; - private Map categorized; + private EconomicMap categorized; public BackupSlotProvider(FrameMapBuilder frameMapBuilder) { this.frameMapBuilder = frameMapBuilder; @@ -70,7 +69,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { protected RegisterBackupPair getScratchRegister(PlatformKind kind) { PlatformKind.Key key = kind.getKey(); if (categorized == null) { - categorized = new HashMap<>(); + categorized = EconomicMap.create(Equivalence.DEFAULT); } else if (categorized.containsKey(key)) { return categorized.get(key); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 7787dd0e565..77355d4ab41 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -36,13 +36,13 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp; +import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; -import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeLIRBuilder; @@ -52,6 +52,7 @@ import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRValueUtil; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; @@ -69,18 +70,22 @@ import org.graalvm.compiler.nodes.calc.ReinterpretNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.util.GraphUtil; import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; public class AMD64NodeMatchRules extends NodeMatchRules { @@ -95,11 +100,15 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - protected AMD64Kind getMemoryKind(Access access) { - return (AMD64Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind(); + protected AMD64Kind getMemoryKind(LIRLowerableAccess access) { + return (AMD64Kind) getLirKind(access).getPlatformKind(); } - protected OperandSize getMemorySize(Access access) { + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + + protected OperandSize getMemorySize(LIRLowerableAccess access) { switch (getMemoryKind(access)) { case BYTE: return OperandSize.BYTE; @@ -118,25 +127,36 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) { + protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) { Condition cond = compare.condition(); AMD64Kind kind = getMemoryKind(access); + boolean matchedAsConstant = false; // For assertion checking if (value.isConstant()) { JavaConstant constant = value.asJavaConstant(); - if (constant != null && kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { - // Only imm32 as long - return null; + if (constant != null) { + if (kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + // A QWORD that can be encoded as int can be embedded as a constant + matchedAsConstant = kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && NumUtil.isInt(constant.asLong()); + } + if (kind == AMD64Kind.DWORD) { + // Any DWORD value should be embeddable as a constant + matchedAsConstant = true; } if (kind.isXMM()) { Debug.log("Skipping constant compares for float kinds"); return null; } } + boolean matchedAsConstantFinal = matchedAsConstant; - // emitCompareBranchMemory expects the memory on the right, so mirror the condition if - // that's not true. It might be mirrored again the actual compare is emitted but that's - // ok. + /* + * emitCompareBranchMemory expects the memory on the right, so mirror the condition if + * that's not true. It might be mirrored again the actual compare is emitted but that's ok. + */ Condition finalCondition = GraphUtil.unproxify(compare.getX()) == access ? cond.mirror() : cond; return new ComplexMatchResult() { @Override @@ -146,6 +166,11 @@ public class AMD64NodeMatchRules extends NodeMatchRules { boolean unorderedIsTrue = compare.unorderedIsTrue(); double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); Value other = operand(value); + /* + * Check that patterns which were matched as a constant actually end up seeing a + * constant in the LIR. + */ + assert !matchedAsConstantFinal || !LIRValueUtil.isVariable(other) : "expected constant value " + value; AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability); return null; @@ -153,7 +178,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { }; } - private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) { + private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, LIRLowerableAccess access) { LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); double trueLabelProbability = x.probability(x.trueSuccessor()); @@ -181,15 +206,22 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access, ValueKind addressKind) { return builder -> { AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); LIRFrameState state = getState(access); + if (addressKind != null) { + address = address.withKind(addressKind); + } return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state); }; } - private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + return emitConvertMemoryOp(kind, op, size, access, null); + } + + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits, ValueKind addressKind) { assert fromBits <= toBits && toBits <= 64; AMD64Kind kind = null; AMD64RMOp op; @@ -231,7 +263,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } if (kind != null && op != null) { - return emitConvertMemoryOp(kind, op, size, access); + return emitConvertMemoryOp(kind, op, size, access, addressKind); } return null; } @@ -244,7 +276,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (IntegerTest Read=access value))") @MatchRule("(If (IntegerTest FloatingRead=access value))") - public ComplexMatchResult integerTestBranchMemory(IfNode root, Access access, ValueNode value) { + public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { return emitIntegerTestBranchMemory(root, value, access); } @@ -262,7 +294,67 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") @MatchRule("(If (ObjectEquals=compare value Read=access))") @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") - public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, Access access) { + public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { + return emitCompareBranchMemory(root, compare, value, access); + } + + @MatchRule("(If (ObjectEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))") + public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) { + assert compare.condition() == Condition.EQ; + if (value == cas.getExpectedValue() && cas.usages().count() == 1) { + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") + public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { return emitCompareBranchMemory(root, compare, value, access); } @@ -290,19 +382,19 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } - private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } @MatchRule("(Add value Read=access)") @MatchRule("(Add value FloatingRead=access)") - public ComplexMatchResult addMemory(ValueNode value, Access access) { + public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -319,7 +411,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Sub value Read=access)") @MatchRule("(Sub value FloatingRead=access)") - public ComplexMatchResult subMemory(ValueNode value, Access access) { + public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -336,7 +428,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Mul value Read=access)") @MatchRule("(Mul value FloatingRead=access)") - public ComplexMatchResult mulMemory(ValueNode value, Access access) { + public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -353,7 +445,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(And value Read=access)") @MatchRule("(And value FloatingRead=access)") - public ComplexMatchResult andMemory(ValueNode value, Access access) { + public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -364,7 +456,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Or value Read=access)") @MatchRule("(Or value FloatingRead=access)") - public ComplexMatchResult orMemory(ValueNode value, Access access) { + public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -375,7 +467,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Xor value Read=access)") @MatchRule("(Xor value FloatingRead=access)") - public ComplexMatchResult xorMemory(ValueNode value, Access access) { + public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -395,20 +487,44 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(SignExtend Read=access)") @MatchRule("(SignExtend FloatingRead=access)") - public ComplexMatchResult signExtend(SignExtendNode root, Access access) { - return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); + public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) { + return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null); } @MatchRule("(ZeroExtend Read=access)") @MatchRule("(ZeroExtend FloatingRead=access)") - public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { + public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) { AMD64Kind memoryKind = getMemoryKind(access); return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } + @MatchRule("(Narrow Read=access)") + @MatchRule("(Narrow FloatingRead=access)") + public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) { + return new ComplexMatchResult() { + @Override + public Value evaluate(NodeLIRBuilder builder) { + AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); + LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()), + address.getBase(), address.getIndex()); + AMD64AddressValue newAddress = address.withKind(addressKind); + LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp()); + return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(), + root.getResultBits(), newAddress, getState(access)); + } + }; + } + + @MatchRule("(SignExtend (Narrow=narrow Read=access))") + @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") + public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { + LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp()); + return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); + } + @MatchRule("(FloatConvert Read=access)") @MatchRule("(FloatConvert FloatingRead=access)") - public ComplexMatchResult floatConvert(FloatConvertNode root, Access access) { + public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { switch (root.getFloatConvert()) { case D2F: return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access); @@ -437,7 +553,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Reinterpret Read=access)") @MatchRule("(Reinterpret FloatingRead=access)") - public ComplexMatchResult reinterpret(ReinterpretNode root, Access access) { + public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { return builder -> { LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp()); return emitReinterpretMemory(kind, access); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java index 99ecbb711c9..a7d79e7bedc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java @@ -26,6 +26,7 @@ import org.graalvm.compiler.java.DefaultSuitesProvider; import org.graalvm.compiler.lir.amd64.phases.StackMoveOptimizationPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; public class AMD64SuitesProvider extends DefaultSuitesProvider { @@ -35,9 +36,9 @@ public class AMD64SuitesProvider extends DefaultSuitesProvider { } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue(options)) { /* Note: this phase must be inserted after RedundantMoveElimination */ lirSuites.getPostAllocationOptimizationStage().appendPhase(new StackMoveOptimizationPhase()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java new file mode 100644 index 00000000000..0711203bb47 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.common; + +/** + * A {@linkplain RetryableBailoutException} that will be thrown if an on-going compilation in the + * compiler was cancelled. + */ +public final class CancellationBailoutException extends RetryableBailoutException { + + private static final long serialVersionUID = 6551793589275293360L; + + public CancellationBailoutException() { + super("Compilation cancelled."); + } + + public static void cancelCompilation() { + throw new CancellationBailoutException(); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java deleted file mode 100644 index 072372e5c7c..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common; - -import static org.graalvm.compiler.core.common.CollectionsFactory.Mode.STANDARD; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Factory for creating collection objects used during compilation. - */ -public class CollectionsFactory { - - private static final ThreadLocal tl = new ThreadLocal<>(); - - public static class ModeScope implements AutoCloseable { - private final Mode previousMode; - - public ModeScope(Mode previousMode) { - this.previousMode = previousMode; - } - - @Override - public void close() { - tl.set(previousMode); - } - } - - /** - * Constants denoting what type of collections are {@link CollectionsFactory#getMode() - * currently} returned by the factory. - */ - public enum Mode { - /** - * Denotes standard collections such as {@link HashSet} and {@link HashMap}. - */ - STANDARD, - - /** - * Denotes collections that have a deterministic iteration order over their keys/entries. - */ - DETERMINISTIC_ITERATION_ORDER; - } - - /** - * Gets the current mode determining the type of collection objects created by this factory. - */ - public static Mode getMode() { - Mode mode = tl.get(); - return mode == null ? Mode.STANDARD : mode; - } - - /** - * Updates the mode for the current thread. - * - * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of - * the current thread to the state before calling this method - */ - public static ModeScope changeMode(Mode mode) { - Mode previousMode = tl.get(); - tl.set(mode); - return new ModeScope(previousMode); - } - - public static HashMap newMap() { - return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>(); - } - - public static HashMap newMap(Map m) { - return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m); - } - - public static HashMap newMap(int initialCapacity) { - return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity); - } - - public static Map newIdentityMap() { - return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(Map m) { - return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m); - } - - /** - * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using} - * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an - * iteration order determined by the order in which elements are inserted in the set. - */ - public static Set newSet() { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java similarity index 75% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java index 9a0a8d22215..4eac53452cb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -20,20 +20,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot; +package org.graalvm.compiler.core.common; /** * A compact representation of the different encoding strategies for Objects and metadata. */ -public class CompressEncoding { - public final long base; - public final int shift; - public final int alignment; +public final class CompressEncoding { + private final long base; + private final int shift; - CompressEncoding(long base, int shift, int alignment) { + public CompressEncoding(long base, int shift) { this.base = base; this.shift = shift; - this.alignment = alignment; } public int compress(long ptr) { @@ -44,6 +42,22 @@ public class CompressEncoding { } } + public boolean hasBase() { + return base != 0; + } + + public boolean hasShift() { + return shift != 0; + } + + public long getBase() { + return base; + } + + public int getShift() { + return shift; + } + public long uncompress(int ptr) { if (ptr == 0) { return 0L; @@ -54,14 +68,13 @@ public class CompressEncoding { @Override public String toString() { - return "base: " + base + " shift: " + shift + " alignment: " + alignment; + return "base: " + base + " shift: " + shift; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + alignment; result = prime * result + (int) (base ^ (base >>> 32)); result = prime * result + shift; return result; @@ -71,7 +84,7 @@ public class CompressEncoding { public boolean equals(Object obj) { if (obj instanceof CompressEncoding) { CompressEncoding other = (CompressEncoding) obj; - return alignment == other.alignment && base == other.base && shift == other.shift; + return base == other.base && shift == other.shift; } else { return false; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 68d158db3b8..7b4665e735b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.core.common; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionKey; /** * This class encapsulates options that control the behavior of the Graal compiler. @@ -34,250 +34,242 @@ import org.graalvm.compiler.options.StableOptionValue; public final class GraalOptions { @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug) - public static final OptionValue Intrinsify = new OptionValue<>(true); + public static final OptionKey Intrinsify = new OptionKey<>(true); @Option(help = "Inline calls with monomorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlineMonomorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMonomorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with polymorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlinePolymorphicCalls = new OptionValue<>(true); + public static final OptionKey InlinePolymorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).", type = OptionType.Expert) - public static final OptionValue InlineMegamorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMegamorphicCalls = new OptionKey<>(true); @Option(help = "Maximum desired size of the compiler graph in nodes.", type = OptionType.User) - public static final OptionValue MaximumDesiredSize = new OptionValue<>(20000); + public static final OptionKey MaximumDesiredSize = new OptionKey<>(20000); @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.", type = OptionType.Expert) - public static final OptionValue MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); + public static final OptionKey MegamorphicInliningMinMethodProbability = new OptionKey<>(0.33D); @Option(help = "Maximum level of recursive inlining.", type = OptionType.Expert) - public static final OptionValue MaximumRecursiveInlining = new OptionValue<>(5); + public static final OptionKey MaximumRecursiveInlining = new OptionKey<>(5); @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert) - public static final OptionValue TrivialInliningSize = new OptionValue<>(10); + public static final OptionKey TrivialInliningSize = new OptionKey<>(10); @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert) - public static final OptionValue MaximumInliningSize = new OptionValue<>(300); + public static final OptionKey MaximumInliningSize = new OptionKey<>(300); @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.", type = OptionType.Expert) - public static final OptionValue SmallCompiledLowLevelGraphSize = new OptionValue<>(300); + public static final OptionKey SmallCompiledLowLevelGraphSize = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LimitInlinedInvokes = new OptionValue<>(5.0); + public static final OptionKey LimitInlinedInvokes = new OptionKey<>(5.0); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineEverything = new OptionValue<>(false); + public static final OptionKey InlineEverything = new OptionKey<>(false); // escape analysis settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue PartialEscapeAnalysis = new OptionValue<>(true); + public static final OptionKey PartialEscapeAnalysis = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisIterations = new OptionValue<>(2); + public static final OptionKey EscapeAnalysisIterations = new OptionKey<>(2); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisLoopCutoff = new OptionValue<>(20); + public static final OptionKey EscapeAnalysisLoopCutoff = new OptionKey<>(20); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalyzeOnly = new OptionValue<>(null); + public static final OptionKey EscapeAnalyzeOnly = new OptionKey<>(null); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); + public static final OptionKey MaximumEscapeAnalysisArrayLength = new OptionKey<>(32); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PEAInliningHints = new OptionValue<>(false); + public static final OptionKey PEAInliningHints = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationProbability = new OptionValue<>(0.5); + public static final OptionKey TailDuplicationProbability = new OptionKey<>(0.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationTrivialSize = new OptionValue<>(1); + public static final OptionKey TailDuplicationTrivialSize = new OptionKey<>(1); @Option(help = "", type = OptionType.Expert) - public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); + public static final OptionKey DeoptsToDisableOptimisticOptimization = new OptionKey<>(40); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopPeeling = new OptionValue<>(true); + public static final OptionKey LoopPeeling = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReassociateInvariants = new OptionValue<>(true); + public static final OptionKey ReassociateInvariants = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue FullUnroll = new OptionValue<>(true); + public static final OptionKey FullUnroll = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopUnswitch = new OptionValue<>(true); + public static final OptionKey LoopUnswitch = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f); + public static final OptionKey MinimumPeelProbability = new OptionKey<>(0.35f); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3); + public static final OptionKey LoopMaxUnswitch = new OptionKey<>(3); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true); + public static final OptionKey UseLoopLimitChecks = new OptionKey<>(true); // debugging settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue ZapStackOnMethodEntry = new OptionValue<>(false); + public static final OptionKey ZapStackOnMethodEntry = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue DeoptALot = new OptionValue<>(false); + public static final OptionKey DeoptALot = new OptionKey<>(false); @Option(help = "Stress the code emitting explicit exception throwing code.", type = OptionType.Debug) - public static final OptionValue StressExplicitExceptionCode = new OptionValue<>(false); + public static final OptionKey StressExplicitExceptionCode = new OptionKey<>(false); @Option(help = "Stress the code emitting invokes with explicit exception edges.", type = OptionType.Debug) - public static final OptionValue StressInvokeWithExceptionNode = new OptionValue<>(false); + public static final OptionKey StressInvokeWithExceptionNode = new OptionKey<>(false); + + @Option(help = "Stress the code by emitting reads at earliest instead of latest point.", type = OptionType.Debug) + public static final OptionKey StressTestEarlyReads = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue VerifyPhases = new OptionValue<>(false); + public static final OptionKey VerifyPhases = new OptionKey<>(false); // Debug settings: @Option(help = "", type = OptionType.Debug) - public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); + public static final OptionKey GCDebugStartCycle = new OptionKey<>(-1); @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug) - public static final OptionValue VerifyHeapAtReturn = new OptionValue<>(false); + public static final OptionKey VerifyHeapAtReturn = new OptionKey<>(false); // Other printing settings @Option(help = "Print profiling information when parsing a method's bytecode", type = OptionType.Debug) - public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); + public static final OptionKey PrintProfilingInformation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final StableOptionValue TraceEscapeAnalysis = new StableOptionValue<>(false); + public static final OptionKey TraceEscapeAnalysis = new OptionKey<>(false); // HotSpot command line options @Option(help = "Print inlining optimizations", type = OptionType.Debug) - public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); + public static final OptionKey HotSpotPrintInlining = new OptionKey<>(false); // Register allocator debugging @Option(help = "Comma separated list of registers that register allocation is limited to.", type = OptionType.Debug) - public static final OptionValue RegisterPressure = new OptionValue<>(null); + public static final OptionKey RegisterPressure = new OptionKey<>(null); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ConditionalElimination = new OptionValue<>(true); + public static final OptionKey ConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue RemoveNeverExecutedCode = new OptionValue<>(true); + public static final OptionKey RawConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbability = new OptionValue<>(true); + public static final OptionKey ReplaceInputsWithConstantsBasedOnStamps = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbabilityForOperations = new OptionValue<>(true); + public static final OptionKey RemoveNeverExecutedCode = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OmitHotExceptionStacktrace = new OptionValue<>(false); + public static final OptionKey UseExceptionProbability = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenSafepoints = new OptionValue<>(true); + public static final OptionKey OmitHotExceptionStacktrace = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenLoopSafepoints = new OptionValue<>(true); + public static final OptionKey GenSafepoints = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseTypeCheckHints = new OptionValue<>(true); + public static final OptionKey GenLoopSafepoints = new OptionKey<>(true); + + @Option(help = "", type = OptionType.Debug) + public static final OptionKey UseTypeCheckHints = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineVTableStubs = new OptionValue<>(true); + public static final OptionKey InlineVTableStubs = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AlwaysInlineVTableStubs = new OptionValue<>(false); + public static final OptionKey AlwaysInlineVTableStubs = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ResolveClassBeforeStaticInvoke = new OptionValue<>(false); + public static final OptionKey ResolveClassBeforeStaticInvoke = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue CanOmitFrame = new OptionValue<>(true); + public static final OptionKey CanOmitFrame = new OptionKey<>(true); // Ahead of time compilation @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert) - public static final OptionValue ImmutableCode = new OptionValue<>(false); + public static final OptionKey ImmutableCode = new OptionKey<>(false); @Option(help = "Generate position independent code", type = OptionType.Expert) - public static final OptionValue GeneratePIC = new OptionValue<>(false); + public static final OptionKey GeneratePIC = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue CallArrayCopy = new OptionValue<>(true); + public static final OptionKey CallArrayCopy = new OptionKey<>(true); // Runtime settings @Option(help = "", type = OptionType.Expert) - public static final OptionValue SupportJsrBytecodes = new OptionValue<>(true); + public static final OptionKey SupportJsrBytecodes = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue OptAssumptions = new OptionValue<>(true); + public static final OptionKey OptAssumptions = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptConvertDeoptsToGuards = new OptionValue<>(true); + public static final OptionKey OptConvertDeoptsToGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptReadElimination = new OptionValue<>(true); + public static final OptionKey OptReadElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReadEliminationMaxLoopVisits = new OptionValue<>(5); + public static final OptionKey ReadEliminationMaxLoopVisits = new OptionKey<>(5); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDeoptimizationGrouping = new OptionValue<>(true); + public static final OptionKey OptDeoptimizationGrouping = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptScheduleOutOfLoops = new OptionValue<>(true); + public static final OptionKey OptScheduleOutOfLoops = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminateGuards = new OptionValue<>(true); + public static final OptionKey OptEliminateGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptImplicitNullChecks = new OptionValue<>(true); + public static final OptionKey OptImplicitNullChecks = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptClearNonLiveLocals = new OptionValue<>(true); + public static final OptionKey OptClearNonLiveLocals = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptLoopTransform = new OptionValue<>(true); + public static final OptionKey OptLoopTransform = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFloatingReads = new OptionValue<>(true); + public static final OptionKey OptFloatingReads = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); + public static final OptionKey OptEliminatePartiallyRedundantGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFilterProfiledTypes = new OptionValue<>(true); + public static final OptionKey OptFilterProfiledTypes = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); - - @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptPushThroughPi = new OptionValue<>(true); + public static final OptionKey OptDevirtualizeInvokesOptimistically = new OptionKey<>(true); @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug) - public static final OptionValue MatchExpressions = new OptionValue<>(true); + public static final OptionKey MatchExpressions = new OptionKey<>(true); @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug) - public static final OptionValue SnippetCounters = new OptionValue<>(false); + public static final OptionKey SnippetCounters = new OptionKey<>(false); @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug) - public static final OptionValue EagerSnippets = new OptionValue<>(false); + public static final OptionKey EagerSnippets = new OptionKey<>(false); @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug) - public static final OptionValue UseSnippetGraphCache = new OptionValue<>(true); + public static final OptionKey UseSnippetGraphCache = new OptionKey<>(true); - @Option(help = "Enable expensive assertions", type = OptionType.Debug) - public static final OptionValue DetailedAsserts = new StableOptionValue() { - @Override - protected Boolean defaultValue() { - boolean enabled = false; - // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) - assert (enabled = true) == true; - return enabled; - } - }; - - @Option(help = "Enable Graal instrumentation") - public static final OptionValue UseGraalInstrumentation = new OptionValue<>(false); + @Option(help = "Enable expensive assertions.", type = OptionType.Debug) + public static final OptionKey DetailedAsserts = new OptionKey<>(Assertions.ENABLED); @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug) - public static final OptionValue TraceRA = new OptionValue<>(false); + public static final OptionKey TraceRA = new OptionKey<>(false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java deleted file mode 100644 index 7c1aca0bdc6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Consumer; - -/** - * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of - * ensuring a deterministic execution order during a capturing compilation. - */ -final class LinkedIdentityHashMap implements Map { - - private final LinkedHashMap, V> map; - - LinkedIdentityHashMap() { - map = new LinkedHashMap<>(); - } - - LinkedIdentityHashMap(Map m) { - map = new LinkedHashMap<>(m.size()); - putAll(m); - } - - LinkedIdentityHashMap(int expectedMaxSize) { - map = new LinkedHashMap<>(expectedMaxSize); - } - - /** - * Wrapper for an object that gives uses the object's identity for the purpose of equality - * comparisons and computing a hash code. - */ - static final class Id { - final T object; - - Id(T object) { - assert object != null; - this.object = object; - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - return obj instanceof Id && ((Id) obj).object == object; - } - - @Override - public int hashCode() { - return System.identityHashCode(object); - } - } - - @Override - public int size() { - return map.size(); - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return map.containsKey(id(key)); - } - - @SuppressWarnings("unchecked") - private Id id(Object key) { - if (key == null) { - return null; - } - return new Id<>((K) key); - } - - @Override - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - @Override - public V get(Object key) { - return map.get(id(key)); - } - - @Override - public V put(K key, V value) { - return map.put(id(key), value); - } - - @Override - public V remove(Object key) { - return map.remove(id(key)); - } - - @Override - @SuppressWarnings("unchecked") - public void putAll(Map m) { - if (m == null) { - throw new NullPointerException(); - } - if (m.getClass() == getClass()) { - LinkedIdentityHashMap that = (LinkedIdentityHashMap) m; - map.putAll(that.map); - - } else { - for (K key : m.keySet()) { - map.put(id(key), m.get(key)); - } - } - } - - @Override - public void clear() { - map.clear(); - } - - final class KeySet extends AbstractSet { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator iterator() { - return new Iterator() { - final Iterator> i = map.keySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public K next() { - return i.next().object; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - return containsKey(o); - } - - @Override - public boolean remove(Object o) { - return LinkedIdentityHashMap.this.remove(o) != null; - } - - @Override - public Spliterator spliterator() { - return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); - } - - @Override - public void forEach(Consumer action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set keySet() { - return new KeySet(); - } - - @Override - public Collection values() { - return map.values(); - } - - final class EntrySet extends AbstractSet> { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - final Iterator, V>> i = map.entrySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public Map.Entry next() { - Map.Entry, V> e = i.next(); - return new Map.Entry() { - - @Override - public K getKey() { - return e.getKey().object; - } - - @Override - public V getValue() { - return e.getValue(); - } - - @Override - public V setValue(V value) { - return e.setValue(value); - } - }; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public Spliterator> spliterator() { - throw new UnsupportedOperationException(); - } - - @Override - public void forEach(Consumer> action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set> entrySet() { - return new EntrySet(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LocationIdentity.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LocationIdentity.java index 38ba381a4a3..75b2375550d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LocationIdentity.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LocationIdentity.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.common; -import java.util.IdentityHashMap; - // JaCoCo Exclude /** @@ -32,7 +30,7 @@ import java.util.IdentityHashMap; * * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when * comparing two {@link LocationIdentity} values for equality. Likewise, they must not use - * {@link IdentityHashMap}s with {@link LocationIdentity} values as keys. + * {@link java.util.IdentityHashMap}s with {@link LocationIdentity} values as keys. */ public abstract class LocationIdentity { @@ -48,12 +46,39 @@ public abstract class LocationIdentity { } } - public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity(); + private static final class InitLocationIdentity extends LocationIdentity { + @Override + public boolean isImmutable() { + return true; + } + @Override + public String toString() { + return "INIT_LOCATION"; + } + } + + public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity(); + public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity(); + + /** + * Indicates that the given location is the union of all possible mutable locations. A write to + * such a location kill all reads from mutable locations and a read from this location is killed + * by any write (except for initialization writes). + */ public static LocationIdentity any() { return ANY_LOCATION; } + /** + * Location only allowed to be used for writes. Indicates that a completely new memory location + * is written. Kills no read. The previous value at the given location must be either + * uninitialized or null. Writes to this location do not need a GC pre-barrier. + */ + public static LocationIdentity init() { + return INIT_LOCATION; + } + /** * Denotes a location is unchanging in all cases. Not that this is different than the Java * notion of final which only requires definite assignment. @@ -68,6 +93,10 @@ public abstract class LocationIdentity { return this == ANY_LOCATION; } + public final boolean isInit() { + return this == INIT_LOCATION; + } + public final boolean isSingle() { return this != ANY_LOCATION; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java similarity index 83% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java index 5966c04c6c9..f34ce87ff4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java @@ -20,10 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.asm; +package org.graalvm.compiler.core.common; // JaCoCo Exclude +import jdk.vm.ci.code.CodeUtil; + /** * A collection of static utility functions that check ranges of numbers. */ @@ -183,4 +185,43 @@ public class NumUtil { return 0xFFFFFFFFFFFFFFFFL; } } + + /** + * Get the minimum value representable in a {@code bits} bit signed integer. + */ + public static long minValue(int bits) { + return CodeUtil.minValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit signed integer. + */ + public static long maxValue(int bits) { + return CodeUtil.maxValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit unsigned integer. + */ + public static long maxValueUnsigned(int bits) { + return getNbitNumberLong(bits); + } + + public static long maxUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return b; + } + return a; + } + + public static long minUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return a; + } + return b; + } + + public static boolean sameSign(long a, long b) { + return a < 0 == b < 0; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java similarity index 97% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java index 52da33abd57..2e2ef19c59c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java similarity index 97% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java index 61ef7303147..da3daf35f42 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java index 91ff0154db0..66ca5ec7ac0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java @@ -22,18 +22,15 @@ */ package org.graalvm.compiler.core.common.alloc; -import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; - -import java.util.HashMap; -import java.util.Map; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.PlatformKind; -import org.graalvm.compiler.core.common.GraalOptions; - /** * Configuration for register allocation. This is different to {@link RegisterConfig} as it only * returns registers specified by {@link GraalOptions#RegisterPressure}. @@ -82,11 +79,10 @@ public class RegisterAllocationConfig { } protected RegisterArray initAllocatable(RegisterArray registers) { - if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) { - String[] names = RegisterPressure.getValue().split(","); - Register[] regs = new Register[names.length]; - for (int i = 0; i < names.length; i++) { - regs[i] = findRegister(names[i], registers); + if (allocationRestrictedTo != null) { + Register[] regs = new Register[allocationRestrictedTo.length]; + for (int i = 0; i < allocationRestrictedTo.length; i++) { + regs[i] = findRegister(allocationRestrictedTo[i], registers); } return new RegisterArray(regs); } @@ -95,12 +91,18 @@ public class RegisterAllocationConfig { } protected final RegisterConfig registerConfig; - private final Map categorized = new HashMap<>(); + private final EconomicMap categorized = EconomicMap.create(Equivalence.DEFAULT); + private final String[] allocationRestrictedTo; private RegisterArray cachedRegisters; - public RegisterAllocationConfig(RegisterConfig registerConfig) { + /** + * @param allocationRestrictedTo if not {@code null}, register allocation will be restricted to + * registers whose names appear in this array + */ + public RegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { assert registerConfig != null; this.registerConfig = registerConfig; + this.allocationRestrictedTo = allocationRestrictedTo; } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java index a1d2661e71b..bc2627ebb5e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.common.cfg; -import java.util.Collections; -import java.util.List; - public abstract class AbstractBlockBase> { protected int id; @@ -34,7 +31,8 @@ public abstract class AbstractBlockBase> { protected T[] successors; private T dominator; - private List dominated; + private T firstDominated; + private T dominatedSibling; private int domNumber; private int maxChildDomNumber; @@ -97,19 +95,27 @@ public abstract class AbstractBlockBase> { this.domDepth = dominator.domDepth + 1; } + /** + * Level in the dominator tree starting with 0 for the start block. + */ public int getDominatorDepth() { return domDepth; } - public List getDominated() { - if (dominated == null) { - return Collections.emptyList(); - } - return dominated; + public T getFirstDominated() { + return this.firstDominated; } - public void setDominated(List blocks) { - dominated = blocks; + public void setFirstDominated(T block) { + this.firstDominated = block; + } + + public T getDominatedSibling() { + return this.dominatedSibling; + } + + public void setDominatedSibling(T block) { + this.dominatedSibling = block; } @Override @@ -158,4 +164,9 @@ public abstract class AbstractBlockBase> { public abstract double probability(); public abstract T getDominator(int distance); + + @Override + public int hashCode() { + return id; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java index ccc46e4e4e8..5b81652d5a2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java @@ -81,6 +81,8 @@ public interface AbstractControlFlowGraph> { return b; } else if (b == null) { return a; + } else if (a == b) { + return a; } else { int aDomDepth = a.getDominatorDepth(); int bDomDepth = b.getDominatorDepth(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java index ec9a55f4bca..cac5c9f7b33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java @@ -45,11 +45,22 @@ public class CFGVerifier { if (block.getDominator() != null) { assert block.getDominator().getId() < block.getId(); - assert block.getDominator().getDominated().contains(block); + + AbstractBlockBase domChild = block.getDominator().getFirstDominated(); + while (domChild != null) { + if (domChild == block) { + break; + } + domChild = domChild.getDominatedSibling(); + } + assert domChild != null : "dominators must contain block"; } - for (T dominated : block.getDominated()) { + + T dominated = block.getFirstDominated(); + while (dominated != null) { assert dominated.getId() > block.getId(); assert dominated.getDominator() == block; + dominated = dominated.getDominatedSibling(); } T postDominatorBlock = block.getPostdominator(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java index 41d884addd5..8b3048feec0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java @@ -105,4 +105,9 @@ public abstract class Loop> { } return false; } + + @Override + public int hashCode() { + return index + depth * 31; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java index 2cc96bcd43d..3327d9f1238 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.core.common.spi; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaField; @@ -32,6 +34,8 @@ public interface ConstantFieldProvider { public interface ConstantFieldTool { + OptionValues getOptions(); + JavaConstant readValue(); JavaConstant getReceiver(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java index ae40986bd5c..c6dfab4540a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.common.spi; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; @@ -39,7 +39,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider static class Options { @Option(help = "Determines whether to treat final fields with default values as constant.")// - public static final OptionValue TrustFinalDefaultFields = new OptionValue<>(true); + public static final OptionKey TrustFinalDefaultFields = new OptionKey<>(true); } protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) { @@ -93,7 +93,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider @SuppressWarnings("unused") protected boolean isFinalFieldValueConstant(ResolvedJavaField field, JavaConstant value, ConstantFieldTool tool) { - return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(); + return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(tool.getOptions()); } @SuppressWarnings("unused") @@ -104,7 +104,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider if (isWellKnownImplicitStableField(field)) { return true; } - if (field == stringHashField) { + if (field.equals(stringHashField)) { return true; } return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java index 7debe2c12ea..a8cf097051f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java @@ -59,8 +59,8 @@ public abstract class AbstractPointerStamp extends Stamp { return result; } - @Override - public Stamp join(Stamp stamp) { + protected Stamp defaultPointerJoin(Stamp stamp) { + assert getClass() == stamp.getClass(); AbstractPointerStamp other = (AbstractPointerStamp) stamp; boolean joinNonNull = this.nonNull || other.nonNull; boolean joinAlwaysNull = this.alwaysNull || other.alwaysNull; @@ -89,6 +89,42 @@ public abstract class AbstractPointerStamp extends Stamp { return copyWith(false, false); } + public static Stamp pointerNonNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asNonNull(); + } + + public static Stamp pointerMaybeNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asMaybeNull(); + } + + public static Stamp pointerAlwaysNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asAlwaysNull(); + } + + public Stamp asNonNull() { + if (isEmpty()) { + return this; + } + return copyWith(true, false); + } + + public Stamp asMaybeNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, false); + } + + public Stamp asAlwaysNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, true); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java index af71cb1964f..5bd75e637c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java @@ -27,11 +27,6 @@ import static jdk.vm.ci.meta.MetaUtil.getSimpleName; import java.util.Arrays; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; @@ -52,6 +47,10 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Abs; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Neg; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Not; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; +import org.graalvm.util.CollectionsUtil; + +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaKind; /** * Information about arithmetic operations. @@ -95,12 +94,6 @@ public final class ArithmeticOpTable { public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); - public ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { - this(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); - } - public interface ArithmeticOpWrapper { UnaryOp wrapUnaryOp(UnaryOp op); @@ -147,14 +140,13 @@ public final class ArithmeticOpTable { IntegerConvertOp signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend()); IntegerConvertOp narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow()); - Stream floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp); - + FloatConvertOp[] floatConvert = CollectionsUtil.filterAndMapToArray(inner.floatConvert, Objects::nonNull, wrapper::wrapFloatConvertOp, FloatConvertOp[]::new); return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); } - private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, + protected ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, Stream floatConvert) { + IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -174,7 +166,9 @@ public final class ArithmeticOpTable { this.signExtend = signExtend; this.narrow = narrow; this.floatConvert = new FloatConvertOp[FloatConvert.values().length]; - floatConvert.forEach(op -> this.floatConvert[op.getFloatConvert().ordinal()] = op); + for (FloatConvertOp op : floatConvert) { + this.floatConvert[op.getFloatConvert().ordinal()] = op; + } this.hash = Objects.hash(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow); } @@ -318,7 +312,7 @@ public final class ArithmeticOpTable { } public static String toString(Op... ops) { - return Arrays.asList(ops).stream().map(o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}").collect(Collectors.joining(",")); + return CollectionsUtil.mapAndJoin(ops, o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}", ","); } private boolean opsEquals(ArithmeticOpTable that) { @@ -742,6 +736,11 @@ public final class ArithmeticOpTable { protected Narrow() { super("Narrow"); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + return null; + } } protected IntegerConvertOp(String op) { @@ -755,5 +754,10 @@ public final class ArithmeticOpTable { public IntegerConvertOp unwrap() { return this; } + + /** + * Computes the stamp of the input for the given output stamp. + */ + public abstract Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java index ee0979f6d16..cb3ee14aa91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java @@ -46,7 +46,11 @@ public abstract class ArithmeticStamp extends Stamp { @Override public Stamp improveWith(Stamp other) { - return this.join(other); + if (this.isCompatible(other)) { + return this.join(other); + } + // Cannot improve, because stamps are not compatible. + return this; } @Override @@ -65,7 +69,7 @@ public abstract class ArithmeticStamp extends Stamp { if (!(obj instanceof ArithmeticStamp)) { return false; } - assert Objects.equals(ops, ((ArithmeticStamp) obj).ops); + assert Objects.equals(ops, ((ArithmeticStamp) obj).ops) : ops + " vs. " + ((ArithmeticStamp) obj).ops; return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java index c55efe65a00..916a0d5cc46 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java @@ -301,10 +301,6 @@ public class FloatStamp extends PrimitiveStamp { return null; } - public boolean isConstant() { - return (nonNaN && Double.compare(lowerBound, upperBound) == 0); - } - private static final ArithmeticOpTable OPS = new ArithmeticOpTable( new UnaryOp.Neg() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java index c76198db83d..834f9c6c90d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java @@ -31,6 +31,7 @@ import java.nio.ByteBuffer; import java.util.Formatter; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp; @@ -54,41 +55,101 @@ import jdk.vm.ci.meta.SerializableConstant; * The description consists of (inclusive) lower and upper bounds and up (may be set) and down * (always set) bit-masks. */ -public class IntegerStamp extends PrimitiveStamp { +public final class IntegerStamp extends PrimitiveStamp { private final long lowerBound; private final long upperBound; private final long downMask; private final long upMask; - public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { + private IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { super(bits, OPS); + this.lowerBound = lowerBound; this.upperBound = upperBound; this.downMask = downMask; this.upMask = upMask; + assert lowerBound >= CodeUtil.minValue(bits) : this; assert upperBound <= CodeUtil.maxValue(bits) : this; assert (downMask & CodeUtil.mask(bits)) == downMask : this; assert (upMask & CodeUtil.mask(bits)) == upMask : this; } - public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { - long lowerBound; - long upperBound; - if (((upMask >>> (bits - 1)) & 1) == 0) { - lowerBound = downMask; - upperBound = upMask; - } else if (((downMask >>> (bits - 1)) & 1) == 1) { - lowerBound = downMask; - upperBound = upMask; + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput) { + return create(bits, lowerBoundInput, upperBoundInput, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput, long downMask, long upMask) { + assert (downMask & ~upMask) == 0 : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); + + // Set lower bound, use masks to make it more precise + long minValue = minValueForMasks(bits, downMask, upMask); + long lowerBoundTmp = Math.max(lowerBoundInput, minValue); + + // Set upper bound, use masks to make it more precise + long maxValue = maxValueForMasks(bits, downMask, upMask); + long upperBoundTmp = Math.min(upperBoundInput, maxValue); + + // Assign masks now with the bounds in mind. + final long boundedDownMask; + final long boundedUpMask; + long defaultMask = CodeUtil.mask(bits); + if (lowerBoundTmp == upperBoundTmp) { + boundedDownMask = lowerBoundTmp; + boundedUpMask = lowerBoundTmp; + } else if (lowerBoundTmp >= 0) { + int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); + + boundedUpMask = upperBoundTmp | -1L >>> (upperBoundLeadingZeros + sameBitCount); + boundedDownMask = upperBoundTmp & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); } else { - lowerBound = downMask | (-1L << (bits - 1)); - upperBound = CodeUtil.maxValue(bits) & upMask; + if (upperBoundTmp >= 0) { + boundedUpMask = defaultMask; + boundedDownMask = 0; + } else { + int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); + + boundedUpMask = lowerBoundTmp | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); + boundedDownMask = lowerBoundTmp & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); + } } - lowerBound = CodeUtil.convert(lowerBound, bits, false); - upperBound = CodeUtil.convert(upperBound, bits, false); - return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); + + return new IntegerStamp(bits, lowerBoundTmp, upperBoundTmp, defaultMask & (downMask | boundedDownMask), defaultMask & upMask & boundedUpMask); + } + + static long significantBit(long bits, long value) { + return (value >>> (bits - 1)) & 1; + } + + static long minValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, upMask) == 0) { + // Value is always positive. Minimum value always positive. + assert significantBit(bits, downMask) == 0; + return downMask; + } else { + // Value can be positive or negative. Minimum value always negative. + return downMask | (-1L << (bits - 1)); + } + } + + static long maxValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, downMask) == 1) { + // Value is always negative. Maximum value always negative. + assert significantBit(bits, upMask) == 1; + return CodeUtil.signExtend(upMask, bits); + } else { + // Value can be positive or negative. Maximum value always positive. + return upMask & (CodeUtil.mask(bits) >>> 1); + } + } + + public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { + return new IntegerStamp(bits, minValueForMasks(bits, downMask, upMask), maxValueForMasks(bits, downMask, upMask), downMask, upMask); } @Override @@ -97,7 +158,7 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp empty() { + public IntegerStamp empty() { return new IntegerStamp(getBits(), CodeUtil.maxValue(getBits()), CodeUtil.minValue(getBits()), CodeUtil.mask(getBits()), 0); } @@ -230,23 +291,27 @@ public class IntegerStamp extends PrimitiveStamp { StringBuilder str = new StringBuilder(); str.append('i'); str.append(getBits()); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - if (downMask != 0) { - str.append(" \u21ca"); - new Formatter(str).format("%016x", downMask); - } - if (upMask != CodeUtil.mask(getBits())) { - str.append(" \u21c8"); - new Formatter(str).format("%016x", upMask); + if (hasValues()) { + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + if (downMask != 0) { + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); + } + if (upMask != CodeUtil.mask(getBits())) { + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); + } + } else { + str.append(""); } return str.toString(); } - private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { + private IntegerStamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { assert getBits() == other.getBits(); if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0 || (newUpMask == 0 && (newLowerBound > 0 || newUpperBound < 0))) { return empty(); @@ -255,7 +320,7 @@ public class IntegerStamp extends PrimitiveStamp { } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { return other; } else { - return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); + return IntegerStamp.create(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); } } @@ -269,17 +334,16 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp join(Stamp otherStamp) { + public IntegerStamp join(Stamp otherStamp) { if (otherStamp == this) { return this; } IntegerStamp other = (IntegerStamp) otherStamp; long newDownMask = downMask | other.downMask; - long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound); long newUpperBound = Math.min(upperBound, other.upperBound); long newUpMask = upMask & other.upMask; - IntegerStamp limit = StampFactory.forInteger(getBits(), newLowerBound, newUpperBound); - return createStamp(other, newUpperBound, newLowerBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return createStamp(other, newUpperBound, newLowerBound, newDownMask, newUpMask); } @Override @@ -303,6 +367,24 @@ public class IntegerStamp extends PrimitiveStamp { return false; } + public long unsignedUpperBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(upperBound(), getBits()); + } + return NumUtil.maxValueUnsigned(getBits()); + } + + public long unsignedLowerBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(lowerBound(), getBits()); + } + return 0; + } + + private boolean sameSignBounds() { + return NumUtil.sameSign(lowerBound, upperBound); + } + @Override public int hashCode() { final int prime = 31; @@ -369,6 +451,13 @@ public class IntegerStamp extends PrimitiveStamp { return null; } + public static boolean addCanOverflow(IntegerStamp a, IntegerStamp b) { + assert a.getBits() == b.getBits(); + return addOverflowsPositively(a.upperBound(), b.upperBound(), a.getBits()) || + addOverflowsNegatively(a.lowerBound(), b.lowerBound(), a.getBits()); + + } + public static boolean addOverflowsPositively(long x, long y, int bits) { long result = x + y; if (bits == 64) { @@ -430,15 +519,59 @@ public class IntegerStamp extends PrimitiveStamp { } } + public static boolean multiplicationCanOverflow(IntegerStamp a, IntegerStamp b) { + // see IntegerStamp#foldStamp for details + assert a.getBits() == b.getBits(); + if (a.upMask() == 0) { + return false; + } else if (b.upMask() == 0) { + return false; + } + if (a.isUnrestricted()) { + return true; + } + if (b.isUnrestricted()) { + return true; + } + int bits = a.getBits(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); + + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); + + boolean mayOverflow = false; + if (a.canBePositive()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, maxPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, minPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, maxNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, minNegB, bits); + + } + } + if (a.canBeNegative()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, minPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, maxPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, minNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, maxNegB, bits); + } + } + return mayOverflow; + } + public static boolean subtractionCanOverflow(IntegerStamp x, IntegerStamp y) { assert x.getBits() == y.getBits(); - // Checkstyle: stop - long x_l = x.lowerBound(); - long x_h = x.upperBound(); - long y_l = y.lowerBound(); - long y_h = y.upperBound(); - // Checkstyle: resume - return subtractionOverflows(x_l, y_h, x.getBits()) || subtractionOverflows(x_h, y_l, x.getBits()); + return subtractionOverflows(x.lowerBound(), y.upperBound(), x.getBits()) || subtractionOverflows(x.upperBound(), y.lowerBound(), x.getBits()); } public static boolean subtractionOverflows(long x, long y, int bits) { @@ -618,7 +751,7 @@ public class IntegerStamp extends PrimitiveStamp { * upper bound after multiplication. * * For example if we consider two stamps a & b that both contain - * negative and positive values, the product of minN_a * minN_b + * negative and positive values, the product of minNegA * minNegB * (both the smallest negative value for each stamp) can only be the * highest positive number. The other candidates can be computed in * a similar fashion. Some of them can never be a new minimum or @@ -627,87 +760,86 @@ public class IntegerStamp extends PrimitiveStamp { * * @formatter:off * - * [x..........0..........y] - * ------------------------- - * [minN maxN minP maxP] - * where maxN = min(0,y) && minP = max(0,x) + * [x................0................y] + * ------------------------------------- + * [minNeg maxNeg minPos maxPos] + * + * where maxNeg = min(0,y) && minPos = max(0,x) * * - * |minN_a maxN_a minP_a maxP_a - * _______|________________________________ - * minN_b |MAX / : / MIN - * maxN_b | / MIN : MAX / - * |---------------+---------------- - * minP_b | / MAX : MIN / - * maxP_b |MIN / : / MAX + * |minNegA maxNegA minPosA maxPosA + * _______ |____________________________________ + * minNegB | MAX / : / MIN + * maxNegB | / MIN : MAX / + * |------------------+----------------- + * minPosB | / MAX : MIN / + * maxPosB | MIN / : / MAX * * @formatter:on */ // We materialize all factors here. If they are needed, the signs of // the stamp will ensure the correct value is used. - // Checkstyle: stop - long minN_a = a.lowerBound(); - long maxN_a = Math.min(0, a.upperBound()); - long minP_a = Math.max(0, a.lowerBound()); - long maxP_a = a.upperBound(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); - long minN_b = b.lowerBound(); - long maxN_b = Math.min(0, b.upperBound()); - long minP_b = Math.max(0, b.lowerBound()); - long maxP_b = b.upperBound(); - // Checkstyle: resume + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); // multiplication has shift semantics long newUpMask = ~CodeUtil.mask(Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask)) & CodeUtil.mask(bits); if (a.canBePositive()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxP_a, maxP_b, bits)) { + if (multiplicationOverflows(maxPosA, maxPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxP_a * maxP_b; - if (multiplicationOverflows(minP_a, minP_b, bits)) { + long maxCandidate = maxPosA * maxPosB; + if (multiplicationOverflows(minPosA, minPosB, bits)) { return a.unrestricted(); } - long minCandidate = minP_a * minP_b; + long minCandidate = minPosA * minPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minP_a, maxN_b, bits)) { + if (multiplicationOverflows(minPosA, maxNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minP_a * maxN_b; - if (multiplicationOverflows(maxP_a, minN_b, bits)) { + long maxCandidate = minPosA * maxNegB; + if (multiplicationOverflows(maxPosA, minNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxP_a * minN_b; + long minCandidate = maxPosA * minNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } } if (a.canBeNegative()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxN_a, minP_b, bits)) { + if (multiplicationOverflows(maxNegA, minPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxN_a * minP_b; - if (multiplicationOverflows(minN_a, maxP_b, bits)) { + long maxCandidate = maxNegA * minPosB; + if (multiplicationOverflows(minNegA, maxPosB, bits)) { return a.unrestricted(); } - long minCandidate = minN_a * maxP_b; + long minCandidate = minNegA * maxPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minN_a, minN_b, bits)) { + if (multiplicationOverflows(minNegA, minNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minN_a * minN_b; - if (multiplicationOverflows(maxN_a, maxN_b, bits)) { + long maxCandidate = minNegA * minNegB; + if (multiplicationOverflows(maxNegA, maxNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxN_a * maxN_b; + long minCandidate = maxNegA * maxNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } @@ -1083,22 +1215,28 @@ public class IntegerStamp extends PrimitiveStamp { assert inputBits == stamp.getBits(); assert inputBits <= resultBits; - long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); - long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); - - if (stamp.lowerBound() < 0 && stamp.upperBound() >= 0) { - /* signed range including 0 and -1 */ - /* - * after sign extension, the whole range from 0 to MAX_INT is - * possible - */ - return IntegerStamp.stampForMask(resultBits, downMask, upMask); + if (inputBits == resultBits) { + return input; } - long lowerBound = CodeUtil.zeroExtend(stamp.lowerBound(), inputBits); - long upperBound = CodeUtil.zeroExtend(stamp.upperBound(), inputBits); + if (input.isEmpty()) { + return StampFactory.forInteger(resultBits).empty(); + } - return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); + long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); + long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); + long lowerBound = stamp.unsignedLowerBound(); + long upperBound = stamp.unsignedUpperBound(); + return IntegerStamp.create(resultBits, lowerBound, upperBound, downMask, upMask); + } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + if (stamp.isEmpty()) { + return StampFactory.forInteger(inputBits).empty(); + } + return StampFactory.forUnsignedInteger(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask(), stamp.upMask()); } }, @@ -1122,6 +1260,13 @@ public class IntegerStamp extends PrimitiveStamp { return new IntegerStamp(resultBits, stamp.lowerBound(), stamp.upperBound(), downMask, upMask); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + long mask = CodeUtil.mask(inputBits); + return StampFactory.forIntegerWithMask(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask() & mask, stamp.upMask() & mask); + } }, new IntegerConvertOp.Narrow() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java index 7563067b584..a24a8f269ad 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.core.common.type; +import static jdk.vm.ci.code.CodeUtil.signExtend; + +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.CodeUtil; @@ -56,6 +59,11 @@ public class StampFactory { public boolean equals(Object obj) { return this == obj; } + + @Override + public String toString() { + return "NodeIntrinsicStamp"; + } } // JaCoCo Exclude @@ -82,7 +90,7 @@ public class StampFactory { } else { mask = CodeUtil.mask(bits); } - setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); + setCache(kind, IntegerStamp.create(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); } private static void setFloatCache(JavaKind kind) { @@ -156,7 +164,7 @@ public class StampFactory { } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound, long downMask, long upMask) { - return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); + return IntegerStamp.create(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound) { @@ -176,46 +184,35 @@ public class StampFactory { */ public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, IntegerStamp maskStamp) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); } public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, long newDownMask, long newUpMask) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); } public static IntegerStamp forInteger(int bits) { - return new IntegerStamp(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + return IntegerStamp.create(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound) { + return forUnsignedInteger(bits, unsignedLowerBound, unsignedUpperBound, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound, long downMask, long upMask) { + long lowerBound = signExtend(unsignedLowerBound, bits); + long upperBound = signExtend(unsignedUpperBound, bits); + if (!NumUtil.sameSign(lowerBound, upperBound)) { + lowerBound = CodeUtil.minValue(bits); + upperBound = CodeUtil.maxValue(bits); + } + long mask = CodeUtil.mask(bits); + return IntegerStamp.create(bits, lowerBound, upperBound, downMask & mask, upMask & mask); } public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { - long defaultMask = CodeUtil.mask(bits); - if (lowerBound == upperBound) { - return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); - } - final long downMask; - final long upMask; - if (lowerBound >= 0) { - int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); - - upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); - downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); - } else { - if (upperBound >= 0) { - upMask = defaultMask; - downMask = 0; - } else { - int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); - - upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); - downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); - } - } - return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); + return IntegerStamp.create(bits, lowerBound, upperBound, 0, CodeUtil.mask(bits)); } public static FloatStamp forFloat(JavaKind kind, double lowerBound, double upperBound, boolean nonNaN) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java deleted file mode 100644 index e9a63ffaf86..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common.util; - -/** - * The {@code ArrayMap} class implements an efficient one-level map which is implemented as an - * array. Note that because of the one-level array inside, this data structure performs best when - * the range of integer keys is small and densely used. Note that the implementation can handle - * arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1. - */ -public class ArrayMap { - - private static final int INITIAL_SIZE = 5; // how big the initial array should be - private static final int EXTRA = 2; // how far on the left or right of a new element to grow - - Object[] map; - int low; - - /** - * Constructs a new {@code ArrayMap} with no initial assumptions. - */ - public ArrayMap() { - } - - /** - * Constructs a new {@code ArrayMap} that initially covers the specified interval. Note that - * this map will automatically expand if necessary later. - * - * @param low the low index, inclusive - * @param high the high index, exclusive - */ - public ArrayMap(int low, int high) { - this.low = low; - this.map = new Object[high - low + 1]; - } - - /** - * Puts a new value in the map at the specified index. - * - * @param i the index at which to store the value - * @param value the value to store at the specified index - */ - public void put(int i, T value) { - int index = i - low; - if (map == null) { - // no map yet - map = new Object[INITIAL_SIZE]; - low = index - 2; - map[INITIAL_SIZE / 2] = value; - } else if (index < 0) { - // grow backwards - growBackward(i, value); - } else if (index >= map.length) { - // grow forwards - growForward(i, value); - } else { - // no growth necessary - map[index] = value; - } - } - - /** - * Gets the value at the specified index in the map. - * - * @param i the index - * @return the value at the specified index; {@code null} if there is no value at the specified - * index, or if the index is out of the currently stored range - */ - public T get(int i) { - int index = i - low; - if (map == null || index < 0 || index >= map.length) { - return null; - } - Class type = null; - return Util.uncheckedCast(type, map[index]); - } - - public int length() { - return map.length; - } - - private void growBackward(int i, T value) { - int nlow = i - EXTRA; - Object[] nmap = new Object[low - nlow + map.length]; - System.arraycopy(map, 0, nmap, low - nlow, map.length); - map = nmap; - low = nlow; - map[i - low] = value; - } - - private void growForward(int i, T value) { - int nlen = i - low + 1 + EXTRA; - Object[] nmap = new Object[nlen]; - System.arraycopy(map, 0, nmap, 0, map.length); - map = nmap; - map[i - low] = value; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java index f97b1712df2..b0dc7fd691d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java @@ -23,8 +23,9 @@ package org.graalvm.compiler.core.common.util; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; /** * Utility class that allows the compiler to monitor compilations that take a very long time. @@ -34,80 +35,74 @@ public final class CompilationAlarm implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Time limit in seconds before a compilation expires (0 to disable the limit).", type = OptionType.Debug) - public static final OptionValue CompilationExpirationPeriod = new OptionValue<>(300); + public static final OptionKey CompilationExpirationPeriod = new OptionKey<>(300); // @formatter:on } - private CompilationAlarm() { - } - - private static boolean enabled() { - return Options.CompilationExpirationPeriod.getValue() > 0; + private CompilationAlarm(long expiration) { + this.expiration = expiration; } /** - * Thread local storage for compilation start timestamps. Everytime a compiler thread calls - * {@link #trackCompilationPeriod()} it will save the start timestamp of the compilation. + * Thread local storage for the active compilation alarm. */ - private static final ThreadLocal compilationStartedTimeStamps = new ThreadLocal<>(); + private static final ThreadLocal currentAlarm = new ThreadLocal<>(); - private static boolean compilationStarted() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start == null) { - compilationStartedTimeStamps.set(System.currentTimeMillis()); - return true; - } - } - return false; - } + private static final CompilationAlarm NEVER_EXPIRES = new CompilationAlarm(0); - private static void compilationFinished() { - if (enabled()) { - assert compilationStartedTimeStamps.get() != null; - compilationStartedTimeStamps.set(null); - } + /** + * Gets the current compilation alarm. If there is no current alarm, a non-null value is + * returned that will always return {@code false} for {@link #hasExpired()}. + */ + public static CompilationAlarm current() { + CompilationAlarm alarm = currentAlarm.get(); + return alarm == null ? NEVER_EXPIRES : alarm; } /** - * Determines if the current compilation is expired. A compilation expires if it takes longer - * than {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. + * Determines if this alarm has expired. A compilation expires if it takes longer than + * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. * * @return {@code true} if the current compilation already takes longer than * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}, {@code false} * otherwise */ - public static boolean hasExpired() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start != null) { - long time = System.currentTimeMillis(); - assert time >= start; - return time - start > Options.CompilationExpirationPeriod.getValue() * 1000; - } - } - return false; + public boolean hasExpired() { + return this != NEVER_EXPIRES && System.currentTimeMillis() > expiration; } @Override public void close() { - compilationFinished(); + if (this != NEVER_EXPIRES) { + currentAlarm.set(null); + } } - private static final CompilationAlarm INSTANCE = enabled() ? new CompilationAlarm() : null; + /** + * The time at which this alarm expires. + */ + private final long expiration; /** - * Gets an object that can be used in a try-with-resource statement to set an time limit based - * alarm for a compilation. + * Starts an alarm for setting a time limit on a compilation if there isn't already an active + * alarm and {@link CompilationAlarm.Options#CompilationExpirationPeriod}{@code > 0}. The + * returned value can be used in a try-with-resource statement to disable the alarm once the + * compilation is finished. * - * @return a {@link CompilationAlarm} instance if there is no current alarm for the calling - * thread otherwise {@code null} + * @return a {@link CompilationAlarm} if there was no current alarm for the calling thread + * before this call otherwise {@code null} */ - public static CompilationAlarm trackCompilationPeriod() { - if (compilationStarted()) { - return INSTANCE; + public static CompilationAlarm trackCompilationPeriod(OptionValues options) { + int period = Options.CompilationExpirationPeriod.getValue(options); + if (period > 0) { + CompilationAlarm current = currentAlarm.get(); + if (current == null) { + long expiration = System.currentTimeMillis() + period * 1000; + current = new CompilationAlarm(expiration); + currentAlarm.set(current); + return current; + } } return null; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java index 6f58e683bc6..d13d9fecf10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java @@ -31,6 +31,8 @@ import java.util.Arrays; */ public final class IntList { + private static final int[] EMPTY_INT_ARRAY = new int[0]; + private int[] array; private int size; @@ -80,9 +82,13 @@ public final class IntList { */ public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) { assert initialCapacity >= length : "initialCapacity < length"; - int[] array = new int[initialCapacity]; - System.arraycopy(other.array, startIndex, array, 0, length); - return new IntList(array, length); + if (initialCapacity == 0) { + return new IntList(EMPTY_INT_ARRAY, 0); + } else { + int[] array = new int[initialCapacity]; + System.arraycopy(other.array, startIndex, array, 0, length); + return new IntList(array, length); + } } public int size() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java index 240fdc07fb6..da6da390026 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.core.common.util; import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -57,11 +58,21 @@ public final class ModuleAPI { */ public static final ModuleAPI addExports; + /** + * {@code jdk.internal.module.Modules.addOpens(Module, String, Module)}. + */ + public static final ModuleAPI addOpens; + /** * {@code java.lang.reflect.Module.getResourceAsStream(String)}. */ public static final ModuleAPI getResourceAsStream; + /** + * {@code java.lang.reflect.Module.getPackages()}. + */ + public static final ModuleAPI getPackages; + /** * {@code java.lang.reflect.Module.canRead(Module)}. */ @@ -105,6 +116,47 @@ public final class ModuleAPI { } } + /** + * Opens all packages in {@code moduleMember}'s module for deep reflection (i.e., allow + * {@link AccessibleObject#setAccessible(boolean)} to be called for any class/method/field) by + * {@code requestor}'s module. + */ + public static void openAllPackagesForReflectionTo(Class moduleMember, Class requestor) { + Object moduleToOpen = getModule.invoke(moduleMember); + Object requestorModule = getModule.invoke(requestor); + if (moduleToOpen != requestorModule) { + String[] packages = getPackages.invoke(moduleToOpen); + for (String pkg : packages) { + addOpens.invokeStatic(moduleToOpen, pkg, requestorModule); + } + } + } + + /** + * Opens {@code declaringClass}'s package to allow a method declared in {@code accessor} to call + * {@link AccessibleObject#setAccessible(boolean)} on an {@link AccessibleObject} representing a + * field or method declared by {@code declaringClass}. + */ + public static void openForReflectionTo(Class declaringClass, Class accessor) { + Object moduleToOpen = getModule.invoke(declaringClass); + Object accessorModule = getModule.invoke(accessor); + if (moduleToOpen != accessorModule) { + addOpens.invokeStatic(moduleToOpen, declaringClass.getPackage().getName(), accessorModule); + } + } + + /** + * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to + * {@code requestor}'s module. + */ + public static void exportPackageTo(Class moduleMember, String packageName, Class requestor) { + Object moduleToExport = getModule.invoke(moduleMember); + Object requestorModule = getModule.invoke(requestor); + if (moduleToExport != requestorModule) { + addExports.invokeStatic(moduleToExport, packageName, requestorModule); + } + } + private void checkAvailability() throws InternalError { if (method == null) { throw new InternalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); @@ -118,10 +170,12 @@ public final class ModuleAPI { Class moduleClass = getModule.method.getReturnType(); Class modulesClass = Class.forName("jdk.internal.module.Modules"); getResourceAsStream = new ModuleAPI(moduleClass.getMethod("getResourceAsStream", String.class)); + getPackages = new ModuleAPI(moduleClass.getMethod("getPackages")); canRead = new ModuleAPI(moduleClass.getMethod("canRead", moduleClass)); isExported = new ModuleAPI(moduleClass.getMethod("isExported", String.class)); isExportedTo = new ModuleAPI(moduleClass.getMethod("isExported", String.class, moduleClass)); addExports = new ModuleAPI(modulesClass.getDeclaredMethod("addExports", moduleClass, String.class, moduleClass)); + addOpens = new ModuleAPI(modulesClass.getDeclaredMethod("addOpens", moduleClass, String.class, moduleClass)); } catch (NoSuchMethodException | SecurityException | ClassNotFoundException e) { throw new InternalError(e); } @@ -129,10 +183,12 @@ public final class ModuleAPI { ModuleAPI unavailable = new ModuleAPI(null); getModule = unavailable; getResourceAsStream = unavailable; + getPackages = unavailable; canRead = unavailable; isExported = unavailable; isExportedTo = unavailable; addExports = unavailable; + addOpens = unavailable; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java similarity index 52% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java index d33456001bd..d5fcd1fd12d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2017, 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 @@ -20,36 +20,39 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.api.collections; +package org.graalvm.compiler.core.common.util; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Set; +import java.util.AbstractList; +import java.util.List; +import java.util.RandomAccess; /** - * A default implementation of {@link CollectionsProvider} that creates standard JDK collection - * class objects. + * A {@code ReversedList} is a view on an other list with the elements in reverse order. + * + * This implementation is made for {@link RandomAccess} lists. */ -public class DefaultCollectionsProvider implements CollectionsProvider { +public class ReversedList extends AbstractList implements RandomAccess { + private final List original; - @Override - public Set newIdentitySet() { - return Collections.newSetFromMap(newIdentityMap()); + public ReversedList(List original) { + assert original instanceof RandomAccess; + this.original = original; } @Override - public Map newIdentityMap() { - return new IdentityHashMap<>(); + public T get(int index) { + return original.get(original.size() - index - 1); } @Override - public Map newIdentityMap(int expectedMaxSize) { - return new IdentityHashMap<>(expectedMaxSize); + public int size() { + return original.size(); } - @Override - public Map newIdentityMap(Map initFrom) { - return new IdentityHashMap<>(initFrom); + /** + * Creates a list that is a view on {@code list} in reverse order. + */ + public static ReversedList reversed(List list) { + return new ReversedList<>(list); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java index 4e29d619daa..fff16890ebd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; - -import java.util.Collection; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; import java.util.List; import org.graalvm.compiler.debug.TTY; @@ -74,29 +74,6 @@ public class Util { return (T) object; } - public interface Stringify { - String apply(Object o); - } - - public static String join(Collection c, String sep) { - return join(c, sep, "", "", null); - } - - public static String join(Collection c, String sep, String prefix, String suffix, Stringify stringify) { - StringBuilder buf = new StringBuilder(prefix); - boolean first = true; - for (Object e : c) { - if (!first) { - buf.append(sep); - } else { - first = false; - } - buf.append(stringify != null ? stringify.apply(e) : String.valueOf(e)); - } - buf.append(suffix); - return buf.toString(); - } - /** * Sets the element at a given position of a list and ensures that this position exists. If the * list is current shorter than the position, intermediate positions are filled with a given @@ -191,25 +168,45 @@ public class Util { * Print a HotSpot-style inlining message to the console. */ public static void printInlining(final ResolvedJavaMethod method, final int bci, final int inliningDepth, final boolean success, final String msg, final Object... args) { - if (HotSpotPrintInlining.getValue()) { - StringBuilder sb = new StringBuilder(); - // 1234567 - sb.append(" "); // print timestamp - // 1234 - sb.append(" "); // print compilation number - // % s ! b n - sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); - sb.append(" "); // more indent - sb.append(" "); // initial inlining indent - for (int i = 0; i < inliningDepth; i++) { - sb.append(" "); - } - sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); - TTY.println(sb.toString()); + StringBuilder sb = new StringBuilder(); + // 1234567 + sb.append(" "); // print timestamp + // 1234 + sb.append(" "); // print compilation number + // % s ! b n + sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); + sb.append(" "); // more indent + sb.append(" "); // initial inlining indent + for (int i = 0; i < inliningDepth; i++) { + sb.append(" "); } + sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); + TTY.println(sb.toString()); } private static String methodName(ResolvedJavaMethod method) { return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code field} with the value + * {@code flag}. + */ + public static void setAccessible(Field field, boolean flag) { + if (!Java8OrEarlier) { + ModuleAPI.openForReflectionTo(field.getDeclaringClass(), Util.class); + } + field.setAccessible(flag); + } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code executable} with the value + * {@code flag}. + */ + public static void setAccessible(Executable executable, boolean flag) { + if (!Java8OrEarlier) { + ModuleAPI.openForReflectionTo(executable.getDeclaringClass(), Util.class); + } + executable.setAccessible(flag); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java index 5129a503b7e..7351a71116d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java @@ -27,12 +27,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -74,6 +70,9 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; /** * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is @@ -206,13 +205,13 @@ public class MatchProcessor extends AbstractProcessor { name = next(); } originatingElements.addAll(type.originatingElements); - requiredPackages.add(type.nodePackage); } else if (Character.isLowerCase(peek("name").charAt(0))) { name = next(); type = valueType; } else { throw new RuleParseError("Unexpected token \"%s\" when looking for name or node type", peek(null)); } + requiredPackages.add(type.nodePackage); if (name != null) { if (!capturedNames.contains(name)) { capturedNames.add(name); @@ -234,7 +233,7 @@ public class MatchProcessor extends AbstractProcessor { /** * Recursively accumulate any required Position declarations. */ - void generatePositionDeclarations(Set declarations) { + void generatePositionDeclarations(EconomicSet declarations) { matchDescriptor.generatePositionDeclarations(declarations); } @@ -366,7 +365,7 @@ public class MatchProcessor extends AbstractProcessor { /** * The types which are know for purpose of parsing MatchRule expressions. */ - Map knownTypes = new HashMap<>(); + EconomicMap knownTypes = EconomicMap.create(Equivalence.DEFAULT); private TypeDescriptor valueType; @@ -407,7 +406,7 @@ public class MatchProcessor extends AbstractProcessor { } } - public void generatePositionDeclarations(Set declarations) { + public void generatePositionDeclarations(EconomicSet declarations) { if (inputs.length == 0) { return; } @@ -532,7 +531,7 @@ public class MatchProcessor extends AbstractProcessor { out.println(); // Generate declarations for the wrapper class to invoke the code generation methods. - for (MethodInvokerItem invoker : info.invokers.values()) { + for (MethodInvokerItem invoker : info.invokers.getValues()) { StringBuilder args = new StringBuilder(); StringBuilder types = new StringBuilder(); int count = invoker.fields.size(); @@ -663,14 +662,14 @@ public class MatchProcessor extends AbstractProcessor { final TypeElement topDeclaringType; final List matchRules = new ArrayList<>(); - private final Set originatingElements = new HashSet<>(); - public Set positionDeclarations = new LinkedHashSet<>(); + private final EconomicSet originatingElements = EconomicSet.create(Equivalence.DEFAULT); + public EconomicSet positionDeclarations = EconomicSet.create(Equivalence.DEFAULT); /** * The mapping between elements with MatchRules and the wrapper class used invoke the code * generation after the match. */ - Map invokers = new LinkedHashMap<>(); + EconomicMap invokers = EconomicMap.create(Equivalence.DEFAULT); /** * The set of packages which must be imported to refer the classes mention in matchRules. @@ -728,7 +727,7 @@ public class MatchProcessor extends AbstractProcessor { TypeMirror valueTypeMirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType(); valueType = new TypeDescriptor(valueTypeMirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), new String[0], false, false); - Map map = new LinkedHashMap<>(); + EconomicMap map = EconomicMap.create(Equivalence.DEFAULT); for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { currentElement = element; @@ -740,7 +739,7 @@ public class MatchProcessor extends AbstractProcessor { } currentElement = null; - for (MatchRuleDescriptor info : map.values()) { + for (MatchRuleDescriptor info : map.getValues()) { createFiles(info); } @@ -834,7 +833,7 @@ public class MatchProcessor extends AbstractProcessor { declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), matchable.commutative(), matchable.shareable(), element); } - private void processMatchRule(Map map, Element element, AnnotationMirror mirror) { + private void processMatchRule(EconomicMap map, Element element, AnnotationMirror mirror) { if (!processedMatchRule.contains(element)) { try { processedMatchRule.add(element); @@ -961,7 +960,7 @@ public class MatchProcessor extends AbstractProcessor { Element enclosing = method.getEnclosingElement(); String declaringClass = ""; String separator = ""; - Set originatingElementsList = info.originatingElements; + EconomicSet originatingElementsList = info.originatingElements; originatingElementsList.add(method); while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java index e0f57456f04..b1171dba201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java @@ -22,23 +22,24 @@ */ package org.graalvm.compiler.core.sparc.test; -import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; +import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.junit.Assume.assumeTrue; -import jdk.vm.ci.sparc.SPARC; import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.core.test.backend.AllocatorTest; +import jdk.vm.ci.sparc.SPARC; + public class SPARCAllocatorTest extends AllocatorTest { @Before public void checkSPARC() { assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test @@ -47,7 +48,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test1snippet(long x) { - return x + 5; + return x + 41; } @Test @@ -56,7 +57,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test2snippet(long x) { - return x * 5; + return x * 41; } @Test @@ -65,7 +66,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test3snippet(long x) { - return x / 3 + x % 3; + return x / 41 + x % 41; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java index 5edf7793eb5..07fcd45be21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java @@ -113,12 +113,13 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Variable emitBitCount(Value operand) { Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); - Value usedOperand = operand; + AllocatableValue usedOperand = getLIRGen().asAllocatable(operand); if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend - usedOperand = getLIRGen().newVariable(operand.getValueKind()); - getLIRGen().append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand)); + AllocatableValue intermediateOperand = getLIRGen().newVariable(operand.getValueKind()); + getLIRGen().append(new SPARCOP3Op(Op3s.Srl, usedOperand, g0.asValue(), intermediateOperand)); + usedOperand = intermediateOperand; } - getLIRGen().append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result)); + getLIRGen().append(new SPARCOP3Op(Op3s.Popc, g0.asValue(), usedOperand, result)); return result; } @@ -141,9 +142,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitMathAbs(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathAbs(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -155,14 +156,14 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @Override - public Value emitMathSqrt(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathSqrt(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -174,7 +175,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @@ -193,9 +194,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { return emitUnary(Xnor, input); } - private Variable emitUnary(Opfs opf, Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + private Variable emitUnary(Opfs opf, Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @@ -211,11 +212,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { private Variable emitBinary(ValueKind resultKind, Opfs opf, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); - if (opf.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOPFOp(opf, b, a, result, state)); - } else { - getLIRGen().append(new SPARCOPFOp(opf, a, b, result, state)); - } + getLIRGen().append(new SPARCOPFOp(opf, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b), result, state)); return result; } @@ -495,78 +492,78 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitFloatConvert(FloatConvert op, Value inputVal) { - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Value result; + public Value emitFloatConvert(FloatConvert op, Value inputValue) { + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); + AllocatableValue result; switch (op) { case D2F: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(SINGLE)); - getLIRGen().append(new SPARCOPFOp(Fdtos, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(SINGLE)); + getLIRGen().append(new SPARCOPFOp(Fdtos, inputAllocatable, result)); break; case F2D: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(DOUBLE)); - getLIRGen().append(new SPARCOPFOp(Fstod, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(DOUBLE)); + getLIRGen().append(new SPARCOPFOp(Fstod, inputAllocatable, result)); break; case I2F: { - AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); + AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); result = getLIRGen().newVariable(intEncodedFloatReg.getValueKind()); - moveBetweenFpGp(intEncodedFloatReg, input); + moveBetweenFpGp(intEncodedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result)); break; } case I2D: { // Unfortunately we must do int -> float -> double because fitod has float // and double encoding in one instruction - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(convertedFloatReg, input); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(convertedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitod, convertedFloatReg, result)); break; } case L2D: { - AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(longEncodedDoubleReg, input); + AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(longEncodedDoubleReg, inputAllocatable); AllocatableValue convertedDoubleReg = getLIRGen().newVariable(longEncodedDoubleReg.getValueKind()); getLIRGen().append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg)); result = convertedDoubleReg; break; } case D2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case F2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case F2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case D2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case L2F: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - moveBetweenFpGp(convertedDoubleReg, input); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + moveBetweenFpGp(convertedDoubleReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result)); break; } @@ -609,10 +606,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { assert fromBits <= toBits && toBits <= XWORD.getSizeInBits(); LIRKind shiftKind = LIRKind.value(WORD); LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? XWORD : WORD); - Value result; int shiftCount = XWORD.getSizeInBits() - fromBits; if (fromBits == toBits) { - result = inputVal; + return inputVal; } else if (isJavaConstant(inputVal)) { JavaConstant javaConstant = asJavaConstant(inputVal); long constant; @@ -622,30 +618,33 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { constant = javaConstant.asLong(); } return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); - } else if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result)); } else { - Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); - getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputVal); + Variable result = getLIRGen().newVariable(resultKind); + if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { + getLIRGen().append(new SPARCOP3Op(Sra, inputAllocatable, g0.asValue(LIRKind.value(WORD)), result)); + } else { + Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); + getLIRGen().append(new SPARCOP3Op(Sllx, inputAllocatable, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); + getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + } + return result; } - return result; } @Override - public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + public Value emitZeroExtend(Value inputValue, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { - return inputVal; + return inputValue; } - Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); if (fromBits == 32) { - getLIRGen().append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result)); + getLIRGen().append(new SPARCOP3Op(Srl, inputAllocatable, g0.asValue(), result)); } else { Value mask = getLIRGen().emitConstant(LIRKind.value(XWORD), forLong(mask(fromBits))); - getLIRGen().append(new SPARCOP3Op(And, inputVal, mask, result)); + getLIRGen().append(new SPARCOP3Op(And, inputAllocatable, mask, result)); } return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java index 0716b556974..abdef18c51e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java @@ -67,4 +67,19 @@ public class SPARCImmediateAddressNode extends AddressNode implements LIRLowerab gen.setResult(this, new SPARCImmediateAddressValue(kind, baseValue, displacement)); } + + @Override + public ValueNode getBase() { + return base; + } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + @Override + public ValueNode getIndex() { + return null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java index 06c5725369e..3fee3e82ea1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java @@ -65,6 +65,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable gen.setResult(this, new SPARCIndexedAddressValue(kind, baseValue, indexValue)); } + @Override public ValueNode getBase() { return base; } @@ -74,6 +75,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -82,4 +84,9 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable updateUsages(this.index, index); this.index = index; } + + @Override + public long getMaxConstantDisplacement() { + return Long.MAX_VALUE; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java index 0023a12738c..fccbc9502fb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java @@ -194,7 +194,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - Value left; + AllocatableValue left; Value right; Condition actualCondition; if (isJavaConstant(x)) { @@ -234,9 +234,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private void emitIntegerTest(Value a, Value b) { assert ((SPARCKind) a.getPlatformKind()).isInteger(); if (LIRValueUtil.isVariable(b)) { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadNonConst(a))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadSimm13(a))); } else { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadNonConst(b))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadSimm13(b))); } } @@ -250,6 +250,16 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { return load(value); } + private Value loadSimm13(Value value) { + if (isJavaConstant(value)) { + JavaConstant c = asJavaConstant(value); + if (c.isNull() || SPARCAssembler.isSimm13(c)) { + return value; + } + } + return load(value); + } + @Override public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { // Emit compare @@ -304,24 +314,24 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private boolean emitIntegerCompare(SPARCKind cmpKind, Value a, Value b) { boolean mirrored; assert cmpKind.isInteger(); - Value left; + AllocatableValue left; Value right; if (LIRValueUtil.isVariable(b)) { left = load(b); - right = loadNonConst(a); + right = loadSimm13(a); mirrored = true; } else { left = load(a); - right = loadNonConst(b); + right = loadSimm13(b); mirrored = false; } int compareBytes = cmpKind.getSizeInBytes(); // SPARC compares 32 or 64 bits if (compareBytes < left.getPlatformKind().getSizeInBytes()) { - left = arithmeticLIRGen.emitSignExtend(left, compareBytes * 8, XWORD.getSizeInBytes() * 8); + left = asAllocatable(arithmeticLIRGen.emitSignExtend(left, cmpKind.getSizeInBits(), XWORD.getSizeInBits())); } if (compareBytes < right.getPlatformKind().getSizeInBytes()) { - right = arithmeticLIRGen.emitSignExtend(right, compareBytes * 8, XWORD.getSizeInBytes() * 8); + right = arithmeticLIRGen.emitSignExtend(right, cmpKind.getSizeInBits(), XWORD.getSizeInBits()); } append(SPARCOP3Op.newBinaryVoid(Subcc, left, right)); return mirrored; @@ -365,10 +375,10 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { - AllocatableValue scratchValue = newVariable(key.getValueKind()); + Variable scratchValue = newVariable(key.getValueKind()); AllocatableValue base = AllocatableValue.ILLEGAL; for (Constant c : strategy.getKeyConstants()) { - if (!(c instanceof JavaConstant) || !getMoveFactory().canInlineConstant((JavaConstant) c)) { + if (!getMoveFactory().canInlineConstant(c)) { base = constantTableBaseProvider.getConstantTableBase(); break; } @@ -376,7 +386,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { append(createStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue)); } - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } @@ -396,7 +406,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public Variable emitByteSwap(Value input) { Variable result = newVariable(LIRKind.combine(input)); - append(new SPARCByteSwapOp(this, result, input)); + append(new SPARCByteSwapOp(this, result, asAllocatable(input))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java index 17395808f8e..f483eb47b76 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java @@ -91,21 +91,25 @@ public class SPARCMoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return SPARCAssembler.isSimm13(c.asInt()); - case Long: - return SPARCAssembler.isSimm13(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return SPARCAssembler.isSimm13(c.asInt()); + case Long: + return SPARCAssembler.isSimm13(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java index a8bbdbe7f97..53c137fe193 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java @@ -29,17 +29,27 @@ import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.sparc.SPARCAddressValue; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; /** @@ -58,6 +68,10 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return null; } + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; SPARCKind toKind = null; @@ -127,6 +141,41 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return emitZeroExtendMemory(access, root.getInputBits(), root.getResultBits()); } + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + SPARCAddressValue address = (SPARCAddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + + Value result = getLIRGeneratorTool().emitValueCompareAndSwap(address, expectedValue, newValue); + getLIRGeneratorTool().emitCompareBranch(kind.getPlatformKind(), result, expectedValue, condition, false, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + @Override public SPARCLIRGenerator getLIRGeneratorTool() { return (SPARCLIRGenerator) super.getLIRGeneratorTool(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java index 62e71409d9a..449c37f72e7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java @@ -26,6 +26,7 @@ import java.util.ListIterator; import org.graalvm.compiler.java.DefaultSuitesProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -39,8 +40,8 @@ public class SPARCSuitesProvider extends DefaultSuitesProvider { } @Override - public Suites createSuites() { - Suites s = super.createSuites(); + public Suites createSuites(OptionValues options) { + Suites s = super.createSuites(options); ListIterator> l = s.getLowTier().findPhase(ExpandLogicPhase.class); while (PhaseSuite.findNextPhase(l, ExpandLogicPhase.class)) { // Search for last occurrence of ExpandLogicPhase diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java index 03ca1c4136b..6ae2e4d0a29 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java @@ -313,7 +313,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); } private void compareGraphs(final String snippet, final String referenceSnippet) { @@ -331,7 +331,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - new PartialEscapePhase(false, canonicalizer).apply(graph, context); + new PartialEscapePhase(false, canonicalizer, graph.getOptions()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index 8c8c74f3442..340bb888ad1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -41,10 +41,10 @@ import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; +import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.bytecode.BridgeMethodUtils; import org.graalvm.compiler.core.CompilerThreadFactory; @@ -67,6 +67,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; @@ -80,7 +81,9 @@ import org.graalvm.compiler.phases.verify.VerifyUpdateUsages; import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals; import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.compiler.test.GraalTest; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.Register; @@ -98,7 +101,7 @@ import jdk.vm.ci.meta.Value; * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of * identity comparisons. */ -public class CheckGraalInvariants extends GraalTest { +public class CheckGraalInvariants extends GraalCompilerTest { private static boolean shouldVerifyEquals(ResolvedJavaMethod m) { if (m.getName().equals("identityEquals")) { @@ -114,7 +117,7 @@ public class CheckGraalInvariants extends GraalTest { private static boolean shouldProcess(String classpathEntry) { if (classpathEntry.endsWith(".jar")) { String name = new File(classpathEntry).getName(); - return name.contains("jvmci") || name.contains("graal"); + return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler"); } return false; } @@ -134,9 +137,13 @@ public class CheckGraalInvariants extends GraalTest { Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus()); - String propertyName = Java8OrEarlier ? "sun.boot.class.path" : "jdk.module.path"; - String bootclasspath = System.getProperty(propertyName); - Assert.assertNotNull("Cannot find value of " + propertyName, bootclasspath); + String bootclasspath; + if (Java8OrEarlier) { + bootclasspath = System.getProperty("sun.boot.class.path"); + } else { + bootclasspath = System.getProperty("jdk.module.path") + File.pathSeparatorChar + System.getProperty("jdk.module.upgrade.path"); + } + Assert.assertNotNull("Cannot find boot class path", bootclasspath); final List classNames = new ArrayList<>(); for (String path : bootclasspath.split(File.pathSeparator)) { @@ -162,66 +169,85 @@ public class CheckGraalInvariants extends GraalTest { String property = System.getProperty(CheckGraalInvariants.class.getName() + ".filters"); String[] filters = property == null ? null : property.split(","); + OptionValues options = getInitialOptions(); CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread", new DebugConfigAccess() { @Override public GraalDebugConfig getDebugConfig() { - return DebugEnvironment.initialize(System.out); + return DebugEnvironment.ensureInitialized(options); } }); int availableProcessors = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); List errors = Collections.synchronizedList(new ArrayList<>()); - // Order outer classes before the inner classes - classNames.sort((String a, String b) -> a.compareTo(b)); - // Initialize classes in single thread to avoid deadlocking issues during initialization - List> classes = initializeClasses(classNames); - for (Class c : classes) { - String className = c.getName(); - executor.execute(() -> { - try { - checkClass(c, metaAccess); - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); - } - }); - for (Method m : c.getDeclaredMethods()) { - if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { - // ignore - } else { - String methodName = className + "." + m.getName(); - if (matches(filters, methodName)) { - executor.execute(() -> { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { - graphBuilderSuite.apply(graph, context); - // update phi stamps - graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); - checkGraph(context, graph); - } catch (VerificationError e) { - errors.add(e.getMessage()); - } catch (LinkageError e) { - // suppress linkages errors resulting from eager resolution - } catch (BailoutException e) { - // Graal bail outs on certain patterns in Java bytecode (e.g., - // unbalanced monitors introduced by jacoco). - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); - } - }); + for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(method).build(); + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + errors.add(String.format("Expected error while checking %s", m)); + } catch (VerificationError e) { + // expected! + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e))); + } + } + if (errors.isEmpty()) { + // Order outer classes before the inner classes + classNames.sort((String a, String b) -> a.compareTo(b)); + // Initialize classes in single thread to avoid deadlocking issues during initialization + List> classes = initializeClasses(classNames); + for (Class c : classes) { + String className = c.getName(); + executor.execute(() -> { + try { + checkClass(c, metaAccess); + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); + } + }); + + for (Method m : c.getDeclaredMethods()) { + if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { + // ignore + } else { + String methodName = className + "." + m.getName(); + if (matches(filters, methodName)) { + executor.execute(() -> { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options).method(method).build(); + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { + checkMethod(method); + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + } catch (VerificationError e) { + errors.add(e.getMessage()); + } catch (LinkageError e) { + // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode (e.g., + // unbalanced monitors introduced by jacoco). + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); + } + }); + } } } } + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.HOURS); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } } - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.HOURS); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - if (!errors.isEmpty()) { StringBuilder msg = new StringBuilder(); String nl = String.format("%n"); @@ -262,11 +288,30 @@ public class CheckGraalInvariants extends GraalTest { } } + private static void checkMethod(ResolvedJavaMethod method) { + if (method.getAnnotation(Snippet.class) == null) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + for (int i = 0; i < parameterAnnotations.length; i++) { + for (Annotation a : parameterAnnotations[i]) { + Class annotationType = a.annotationType(); + if (annotationType == ConstantParameter.class || annotationType == VarargsParameter.class || annotationType == NonNullParameter.class) { + VerificationError verificationError = new VerificationError("Parameter %d of %s is annotated with %s but the method is not annotated with %s", i, method, + annotationType.getSimpleName(), + Snippet.class.getSimpleName()); + throw verificationError; + } + } + } + } + } + /** * Checks the invariants for a single graph. */ private static void checkGraph(HighTierContext context, StructuredGraph graph) { if (shouldVerifyEquals(graph.method())) { + // If you add a new type to test here, be sure to add appropriate + // methods to the BadUsageWithEquals class below new VerifyUsageWithEquals(Value.class).apply(graph, context); new VerifyUsageWithEquals(Register.class).apply(graph, context); new VerifyUsageWithEquals(RegisterCategory.class).apply(graph, context); @@ -305,4 +350,108 @@ public class CheckGraalInvariants extends GraalTest { t.printStackTrace(new PrintWriter(sw)); return sw.toString(); } + + static class BadUsageWithEquals { + Value aValue; + Register aRegister; + RegisterCategory aRegisterCategory; + JavaType aJavaType; + JavaField aJavaField; + JavaMethod aJavaMethod; + LocationIdentity aLocationIdentity; + LIRKind aLIRKind; + ArithmeticOpTable anArithmeticOpTable; + ArithmeticOpTable.Op anArithmeticOpTableOp; + + static Value aStaticValue; + static Register aStaticRegister; + static RegisterCategory aStaticRegisterCategory; + static JavaType aStaticJavaType; + static JavaField aStaticJavaField; + static JavaMethod aStaticJavaMethod; + static LocationIdentity aStaticLocationIdentity; + static LIRKind aStaticLIRKind; + static ArithmeticOpTable aStaticArithmeticOpTable; + static ArithmeticOpTable.Op aStaticArithmeticOpTableOp; + + boolean test01(Value f) { + return aValue == f; + } + + boolean test02(Register f) { + return aRegister == f; + } + + boolean test03(RegisterCategory f) { + return aRegisterCategory == f; + } + + boolean test04(JavaType f) { + return aJavaType == f; + } + + boolean test05(JavaField f) { + return aJavaField == f; + } + + boolean test06(JavaMethod f) { + return aJavaMethod == f; + } + + boolean test07(LocationIdentity f) { + return aLocationIdentity == f; + } + + boolean test08(LIRKind f) { + return aLIRKind == f; + } + + boolean test09(ArithmeticOpTable f) { + return anArithmeticOpTable == f; + } + + boolean test10(ArithmeticOpTable.Op f) { + return anArithmeticOpTableOp == f; + } + + boolean test12(Value f) { + return aStaticValue == f; + } + + boolean test13(Register f) { + return aStaticRegister == f; + } + + boolean test14(RegisterCategory f) { + return aStaticRegisterCategory == f; + } + + boolean test15(JavaType f) { + return aStaticJavaType == f; + } + + boolean test16(JavaField f) { + return aStaticJavaField == f; + } + + boolean test17(JavaMethod f) { + return aStaticJavaMethod == f; + } + + boolean test18(LocationIdentity f) { + return aStaticLocationIdentity == f; + } + + boolean test19(LIRKind f) { + return aStaticLIRKind == f; + } + + boolean test20(ArithmeticOpTable f) { + return aStaticArithmeticOpTable == f; + } + + boolean test21(ArithmeticOpTable.Op f) { + return aStaticArithmeticOpTableOp == f; + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java index 85cf35b70ce..7b5d173b407 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java @@ -90,7 +90,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test1() { - getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); + createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).remove(); test1Snippet(new String(alphabet)); test("test1Snippet", (Object) null); @@ -114,7 +114,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test2() { - assert getSuites().getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); + assert createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); test2Snippet(new String(alphabet)); test("test2Snippet", (Object) null); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java new file mode 100644 index 00000000000..81331104a9c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; + +public class CompareCanonicalizerTest2 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + private StructuredGraph getCanonicalizedGraph(String name) { + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); + new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); + return graph; + } + + public void testIntegerTestCanonicalization(String name) { + StructuredGraph graph = getCanonicalizedGraph(name); + Assert.assertThat(graph.getNodes().filter(IntegerLessThanNode.class), isNotEmpty()); + } + + @Test + public void test0() { + testIntegerTestCanonicalization("integerTestCanonicalization0"); + } + + @Test + public void test1() { + testIntegerTestCanonicalization("integerTestCanonicalization1"); + } + + public static void integerTestCanonicalization0(int a) { + if (1 < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void integerTestCanonicalization1(int a) { + if (a - 1 < -1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java index 1048d725105..5b19c320351 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java @@ -33,7 +33,9 @@ import jdk.vm.ci.meta.JavaConstant; import org.junit.Test; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.test.AddExports; +@AddExports("jdk.internal.vm.ci/jdk.vm.ci.meta") public class ConditionTest { @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java deleted file mode 100644 index b27daf302ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test; - -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.nodes.IfNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; - -import sun.misc.Unsafe; - -public class ConditionalEliminationLoadFieldConstantFoldTest extends GraalCompilerTest { - public static int intSideEffect; - - public static final B FinalField = new B(10); - - private abstract static class A { - - } - - private static class B extends A { - final int a; - - B(int a) { - this.a = a; - } - } - - private static class C extends A { - final B b; - - C(B b) { - this.b = b; - } - } - - private static class D extends A { - final C c; - - D(C c) { - this.c = c; - } - } - - private static class E extends D { - final Object o; - - E(C c, Object o) { - super(c); - this.o = o; - } - } - - public static final B CONST_B = new B(10); - public static final C CONST_C = new C(CONST_B); - public static final D CONST_D = new D(CONST_C); - - public int testReadConstInBranch(B b) { - if (b == CONST_B) { - if (b.a == 5) { - intSideEffect = b.a; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testMultipleReadsConstInBranch(D d) { - if (d == CONST_D) { - C c = d.c; - B b = c.b; - int res = b.a + 12; - if (res == 125) { - intSideEffect = 12; - } - } - return 0; - } - - public int testLoadFinalInstanceOf(E e) { - Object o = e.o; - if (o == CONST_C) { - if (o instanceof A) { - // eliminate, implied by a.x == Const(Subclass) - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testLoadFinalTwiceInstanceOf(E e) { - if (e.o == CONST_C) { - if (e.o instanceof A) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - static class C1 { - final int a; - - C1(int a) { - this.a = a; - } - } - - static class C2 { - final C1 c1; - - C2(C1 c1) { - this.c1 = c1; - } - } - - public static int foldThatIsNotAllowed(C2 c2) { - // read before, this will be used to load through when folding - C1 c1Unknown = c2.c1; - - // be naughty (will be a store field after canonicalization as it has a constant offset, so - // we would be able to eliminate the inner if after an early read elimination but we would - // fold before and ce the inner if already) - // - // note: if the offset would not be constant but a parameter we would not even be able to - // remove in inner most if as we cannot rewrite the unsafe store to a store field node as - // the store might kill ANY_LOCATION - UNSAFE.putObject(c2, C2_C1_OFFSET, C1_AFTER_READ_CONST); - - if (c2 == C2_CONST) { - if (c1Unknown == C1_CONST) { - /* - * This if can be eliminated (as we rewrite the unsafe store with a constant offset - * to a store field node) but the remaining branch must be the false branch. If we - * do not fold through both field loads we will canonicalize the unsafe store to a - * store field, see the new value and can thus eliminate the true branch - * - * if we fold through the load fields we would load from the object read before the - * store so we miss the unsafe update - */ - if (c2.c1.a == 10) { - intSideEffect = 1; - return 1; - } else { - intSideEffect = 2; - return 2; - } - } else { - intSideEffect = -2; - return -2; - } - } else { - intSideEffect = -1; - return -1; - } - } - - public int testLoadFinalTwiceNoReadEliminationInstanceOf(E e) { - if (e.o == CONST_C) { - /* - * we cannot eliminate the second read of e.o although it is a final field. the call to - * System.gc (or any other memory checkpoint killing ANY_LOCATION) will prohibit the - * elimination of the second load, thus we have two different load nodes, we know that - * that first load field is a constant but we do not know for the second one, assuming - * e.o is final, as it might have been written in between - * - * this prohibits us to remove the if (fold through all loads to final fields) and the - * instance of e.o - */ - System.gc(); - C c = (C) e.o; - if (c.b.a == 10) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - - } - - private static final C1 C1_CONST = new C1(0); - private static final C2 C2_CONST = new C2(C1_CONST); - private static final C1 C1_AFTER_READ_CONST = new C1(10); - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - private static final sun.misc.Unsafe UNSAFE = getUnsafe(); - private static final long C2_C1_OFFSET; - - static { - try { - Field f = C2.class.getDeclaredField("c1"); - C2_C1_OFFSET = UNSAFE.objectFieldOffset(f); - } catch (NoSuchFieldException | SecurityException e) { - throw new RuntimeException(e); - } - } - - @Test - public void test01() { - checkGraph("testReadConstInBranch", 1); - test("testReadConstInBranch", new B(1)); - } - - @Test - public void test02() { - checkGraph("testMultipleReadsConstInBranch", 1); - } - - @Test - public void test03() { - checkGraph("testLoadFinalInstanceOf", 1); - } - - @Test - public void test04() { - checkGraph("testLoadFinalTwiceInstanceOf", 1); - } - - @Test - public void test05() { - checkGraph("testLoadFinalTwiceNoReadEliminationInstanceOf", 2); - } - - @Test(expected = AssertionError.class) - @SuppressWarnings("try") - public void test06() { - Result actual = executeActual(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - UNSAFE.putObject(C2_CONST, C2_C1_OFFSET, C1_CONST); - Result expected = executeExpected(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - Assert.assertEquals(expected.returnValue, actual.returnValue); - } - - @SuppressWarnings("try") - private StructuredGraph checkGraph(String name, int nrOfIfsAfter) { - StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - CanonicalizerPhase c = new CanonicalizerPhase(); - c.apply(g, getDefaultHighTierContext()); - new EarlyReadEliminationPhase(c).apply(g, getDefaultHighTierContext()); - new IterativeConditionalEliminationPhase(c, false).apply(g, getDefaultHighTierContext()); - Assert.assertEquals("Nr of Ifs left does not match", nrOfIfsAfter, g.getNodes().filter(IfNode.class).count()); - c.apply(g, getDefaultHighTierContext()); - return g; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java index 5f8b980e0a9..599820413b9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; public class ConditionalEliminationMulTest extends GraalCompilerTest { @@ -76,11 +75,9 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { private StructuredGraph prepareGraph(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); + DominatorConditionalEliminationPhase.create(false).apply(graph, context); CanonicalizerPhase c = new CanonicalizerPhase(); c.apply(graph, context); - new DominatorConditionalEliminationPhase(false).apply(graph, context); - c.apply(graph, context); return graph; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java index 30f8db587bb..16ab348e335 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java @@ -44,14 +44,17 @@ import org.graalvm.compiler.phases.tiers.PhaseContext; */ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase { + private static boolean condition1; + private static boolean condition2; + private static class TestClass { int x; } @SuppressWarnings("all") - public static int testSnippet(int a, TestClass t) { + public static int testSnippet1(TestClass t) { int result = 0; - if (a == 0) { + if (condition1) { GraalDirectives.controlFlowAnchor(); result = t.x; } @@ -61,11 +64,38 @@ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase @Test public void test1() { - StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES); + test("testSnippet1", 1); + } + + @SuppressWarnings("all") + public static int testSnippet2(TestClass t) { + int result = 0; + if (condition1) { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } else { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } + + if (condition2) { + result = t.x; + GraalDirectives.controlFlowAnchor(); + } + + return result; + } + + @Test + public void test2() { + test("testSnippet2", 1); + } + + private void test(String snippet, int guardCount) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Assert.assertEquals(2, graph.getNodes().filter(GuardNode.class).count()); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - Assert.assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + DominatorConditionalEliminationPhase.create(true).apply(graph, context); + Assert.assertEquals(guardCount, graph.getNodes().filter(GuardNode.class).count()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java index 5c2b861ef15..2bd9ecab175 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java @@ -41,7 +41,7 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int referenceSnippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -54,10 +54,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test1Snippet(int a) { if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -65,10 +65,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test2Snippet(int a) { if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -81,10 +81,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test3Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -98,10 +98,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test4Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -114,7 +114,7 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test5Snippet(int a) { if ((a & 5) == 5) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 7) != 0) { return 0; @@ -130,19 +130,19 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } public static int reference6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); return 0; } @@ -153,17 +153,17 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test7Snippet(int a) { if ((a & 15) == 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference7Snippet(int a) { if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -175,20 +175,20 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test8Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference8Snippet(int a) { if ((a & 60) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -201,23 +201,23 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test9Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference9Snippet(int a) { if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -239,16 +239,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase int v = b.byteValue(); long a = v & 0xffffffff; if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; @@ -257,12 +257,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference10Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test10() { testConditionalElimination("test10Snippet", "reference10Snippet"); } @@ -272,16 +273,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase long a = v & 0xffffffff; if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @@ -289,12 +290,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference11Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test11() { testConditionalElimination("test11Snippet", "reference11Snippet"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java new file mode 100644 index 00000000000..fb1cf057578 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Test; + +public class ConditionalEliminationTest12 extends ConditionalEliminationTestBase { + + static class A { + + } + + static class B extends A { + + } + + static class C extends B { + + } + + static class D extends C { + + } + + @SuppressWarnings({"static-method", "unused"}) + private int referenceMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings({"static-method", "unused"}) + private int testMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + if (a instanceof B) { + B b = (B) a; + if (b instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings("unused") + @Test + public void testFloatingGuards() { + // Make sure class D is loaded. + D d = new D(); + testConditionalElimination("testMethod", "referenceMethod"); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java new file mode 100644 index 00000000000..4f30cea3df7 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase { + public ConditionalEliminationTest13() { + super(false); + } + + private static int sink0; + private static int sink1; + private static int sink2; + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } + + public static void referenceSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (0 < a) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet2(int a) { + if (0 < a) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet3(int a) { + if (0 < a) { + if (a == 1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + @SuppressWarnings("unused") + public static void referenceSnippet4(int a) { + sink1 = 0; + } + + public static void testSnippet4(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet5(int a) { + if (a < 0) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet6(int a) { + if (a < 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet6(int a) { + if (a < 0) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet7(int a) { + if (0 < a) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet8(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + private static int either(int a, int b) { + return (sink0 + sink1 + sink2) == 0 ? a : b; + } + + public static void testSnippet10(int a) { + if (Integer.compareUnsigned(a, a + either(1, 2)) < 0 || a == 0xffff_ffff || a == 0xffff_fffe) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + if (Integer.compareUnsigned(a, 42) <= 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0 && a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet13(int a) { + int x = either(0, 1); + if (a <= a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test1() { + testConditionalElimination("testSnippet1", "referenceSnippet1"); + } + + @Test + public void test2() { + testConditionalElimination("testSnippet2", "referenceSnippet2"); + } + + @Test + public void test3() { + testConditionalElimination("testSnippet3", "testSnippet3"); + } + + @Test + public void test4() { + testConditionalElimination("testSnippet4", "referenceSnippet4"); + } + + @Test + public void test5() { + testConditionalElimination("testSnippet5", "testSnippet5"); + } + + @Test + public void test6() { + testConditionalElimination("testSnippet6", "referenceSnippet6"); + } + + @Test + public void test7() { + testConditionalElimination("testSnippet7", "referenceSnippet2"); + } + + @Test + public void test8() { + testConditionalElimination("testSnippet8", "referenceSnippet4"); + } + + @Test + public void test9() { + testConditionalElimination("testSnippet9", "referenceSnippet9"); + } + + @Test + public void test10() { + testConditionalElimination("testSnippet10", "referenceSnippet4"); + } + + @Test + public void test11() { + testConditionalElimination("testSnippet11", "referenceSnippet11"); + } + + @Test + public void test12() { + testConditionalElimination("testSnippet12", "referenceSnippet12"); + } + + @Test + public void test13() { + testConditionalElimination("testSnippet13", "testSnippet13"); + } + + @Test + public void test14() { + testConditionalElimination("testSnippet14", "referenceSnippet14"); + } + + @Override + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + super.prepareGraph(graph, canonicalizer, context, applyLowering); + graph.clearAllStateAfter(); + graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); + Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After preparation"); + canonicalizer.apply(graph, context); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java index 0e9604496b8..5a2dd0f6d36 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java @@ -103,7 +103,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new FloatingReadPhase().apply(graph); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + DominatorConditionalEliminationPhase.create(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count()); @@ -125,7 +125,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + DominatorConditionalEliminationPhase.create(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java index ef8d7c7e650..bb738056d64 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** @@ -29,6 +30,7 @@ import org.junit.Test; * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those * that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest3 extends ConditionalEliminationTestBase { private static final String REFERENCE_SNIPPET = "referenceSnippet"; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java index 255e5a87ec7..de1376b83c1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; import org.graalvm.compiler.api.directives.GraalDirectives; @@ -39,6 +40,10 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase interface B extends A { } + interface C extends B { + + } + static final class DistinctA { } @@ -115,32 +120,63 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase @Test public void test3() { - testConditionalElimination("test3Snippet", "reference3Snippet", true); + testConditionalElimination("test3Snippet", "reference3Snippet", true, false); } public static int reference4Snippet(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 1; } public static int test4Snippet1(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 1; } public static int test4Snippet2(Object a) { if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); + } + return 1; + } + + @SuppressWarnings({"cast", "unused"}) + public static int test4Snippet3(Object a) { + Object pi = (A) a; + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + return 1; + } + + public static int test4Snippet4(Object a) { + if (!(a instanceof A)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(((A) a) instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + return 1; + } + + @SuppressWarnings({"cast"}) + public static int test4Snippet5(Object a) { + Object pi = (A) a; + if (pi == null) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); } return 1; } @@ -149,5 +185,13 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase public void test4() { testConditionalElimination("test4Snippet1", "reference4Snippet"); testConditionalElimination("test4Snippet2", "reference4Snippet"); + testConditionalElimination("test4Snippet3", "reference4Snippet"); + testConditionalElimination("test4Snippet5", "reference4Snippet"); + } + + @Ignore + @Test + public void test5() { + testConditionalElimination("test4Snippet4", "reference4Snippet", false, true); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java index a6f69e3cdff..743d8b305c6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** @@ -29,6 +30,7 @@ import org.junit.Test; * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those * that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest7 extends ConditionalEliminationTestBase { @SuppressWarnings("all") diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java index 32c8f5f4644..2921e453e0f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -36,6 +34,7 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; /** * Collection of tests for @@ -43,11 +42,10 @@ import org.graalvm.compiler.phases.tiers.PhaseContext; * that triggered bugs in this phase. */ public class ConditionalEliminationTestBase extends GraalCompilerTest { - private final boolean disableSimplification; protected ConditionalEliminationTestBase() { - disableSimplification = true; + this(true); } protected ConditionalEliminationTestBase(boolean disableSimplification) { @@ -55,11 +53,11 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { } protected void testConditionalElimination(String snippet, String referenceSnippet) { - testConditionalElimination(snippet, referenceSnippet, false); + testConditionalElimination(snippet, referenceSnippet, false, false); } @SuppressWarnings("try") - protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference) { + protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); @@ -72,9 +70,7 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { } CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) { - canonicalizer1.apply(graph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - // new DominatorConditionalEliminationPhase(true).apply(graph, context); + prepareGraph(graph, canonicalizer1, context, applyLowering); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); @@ -84,21 +80,29 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { } StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { - - new ConvertDeoptimizeToGuardPhase().apply(referenceGraph, context); + prepareGraph(referenceGraph, canonicalizer, context, applyLowering); if (applyConditionalEliminationOnReference) { - new DominatorConditionalEliminationPhase(true).apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - } else { - canonicalizer.apply(referenceGraph, context); + DominatorConditionalEliminationPhase.create(true).apply(referenceGraph, context); } + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { Debug.handle(t); } assertEquals(referenceGraph, graph); } + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + if (applyLowering) { + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + } + canonicalizer.apply(graph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + } + public void testProxies(String snippet, int expectedProxiesCreated) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -110,9 +114,9 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { canonicalizer.apply(graph, context); int baseProxyCount = graph.getNodes().filter(ProxyNode.class).count(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + DominatorConditionalEliminationPhase.create(true).apply(graph, context); canonicalizer.apply(graph, context); - new SchedulePhase().apply(graph, context); + new SchedulePhase(graph.getOptions()).apply(graph, context); int actualProxiesCreated = graph.getNodes().filter(ProxyNode.class).count() - baseProxyCount; Assert.assertEquals(expectedProxiesCreated, actualProxiesCreated); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java index c5e2ecbb57c..5a8f6418b37 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java @@ -22,16 +22,16 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; +import static org.graalvm.compiler.core.common.util.CompilationAlarm.Options.CompilationExpirationPeriod; -import org.graalvm.compiler.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; +import org.junit.Test; public class CooperativePhaseTest extends GraalCompilerTest { @@ -43,9 +43,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { return; } } @@ -57,9 +58,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RetryableBailoutException("Expiring..."); } } @@ -67,13 +69,14 @@ public class CooperativePhaseTest extends GraalCompilerTest { } - private static class ParlyCooperativePhase extends Phase { + private static class PartiallyCooperativePhase extends Phase { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); for (int i = 0; i < 10; i++) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -84,7 +87,8 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { - if (CompilationAlarm.hasExpired()) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -101,9 +105,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test01() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new CooperativePhase().apply(g); } } @@ -111,9 +117,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(expected = RetryableBailoutException.class, timeout = 60_000) @SuppressWarnings("try") public void test02() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new UnCooperativePhase().apply(g); } } @@ -121,17 +129,20 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test03() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); + initializeForTimeout(); // 0 disables alarm utility - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 0); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { - new ParlyCooperativePhase().apply(g); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 0); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); + new PartiallyCooperativePhase().apply(g); } } @Test(timeout = 60_000) @SuppressWarnings("try") public void test04() { + initializeForTimeout(); StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); new CooperativePhaseWithoutAlarm().apply(g); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java index 776497efd65..cc213a828e9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java @@ -30,8 +30,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -40,10 +39,8 @@ public final class DontReuseArgumentSpaceTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @BytecodeParserNeverInline diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java index 80df81dca8d..fb06a104201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.Suites; @@ -137,8 +138,8 @@ public class EnumSwitchTest extends GraalCompilerTest { } @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites ret = super.createSuites(options); ret.getHighTier().prependPhase(new Phase() { @Override protected void run(StructuredGraph graph) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java index bd5c99f6897..c11a0c5483a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -74,7 +71,7 @@ public class FinalizableSubclassTest extends GraalCompilerTest { Constructor[] constructors = cl.getConstructors(); Assert.assertTrue(constructors.length == 1); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]); - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, NO_PROFILING_INFO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), allowAssumptions).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()); new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 9332f698b5d..3ed3cf7308b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -44,12 +44,6 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.test.Graal; @@ -58,10 +52,12 @@ import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.GraalCompiler.Request; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.util.ModuleAPI; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -98,7 +94,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.compiler.options.DerivedOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; @@ -112,9 +108,16 @@ import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.TargetDescription; @@ -127,13 +130,15 @@ import jdk.vm.ci.meta.ProfilingInfo; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.services.Services; /** * Base class for Graal compiler unit tests. *

* White box tests for Graal compiler transformations use this pattern: *

    - *
  1. Create a graph by {@linkplain #parseEager(String, AllowAssumptions) parsing} a method.
  2. + *
  3. Create a graph by {@linkplain #parseEager parsing} a method.
  4. *
  5. Manually modify the graph (e.g. replace a parameter node with a constant).
  6. *
  7. Apply a transformation to the graph.
  8. *
  9. Assert that the transformed graph is equal to an expected graph.
  10. @@ -147,12 +152,46 @@ import jdk.vm.ci.meta.SpeculationLog; *

    * These tests will be run by the {@code mx unittest} command. */ +@AddExports({"jdk.internal.vm.ci/jdk.vm.ci.meta", + "jdk.internal.vm.ci/jdk.vm.ci.services", + "jdk.internal.vm.ci/jdk.vm.ci.code", + "jdk.internal.vm.ci/jdk.vm.ci.services", + "java.base/jdk.internal.org.objectweb.asm", + "java.base/jdk.internal.org.objectweb.asm.tree"}) public abstract class GraalCompilerTest extends GraalTest { + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + + private static final int BAILOUT_RETRY_LIMIT = 1; private final Providers providers; private final Backend backend; - private final DerivedOptionValue suites; - private final DerivedOptionValue lirSuites; + + /** + * Representative class for the {@code java.base} module. + */ + public static final Class JAVA_BASE = Class.class; + + /** + * Representative class for the {@code jdk.vm.ci} module. + */ + public static final Class JDK_VM_CI = Services.class; + + /** + * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to + * this object's module. This must be called before accessing packages that are no longer public + * as of JDK 9. + */ + protected final void exportPackage(Class moduleMember, String packageName) { + if (!Java8OrEarlier) { + ModuleAPI.exportPackageTo(moduleMember, packageName, getClass()); + } + } /** * Denotes a test method that must be inlined by the {@link BytecodeParser}. @@ -212,8 +251,8 @@ public abstract class GraalCompilerTest extends GraalTest { protected static void shouldBeOptimizedAway() { } - protected Suites createSuites() { - Suites ret = backend.getSuites().getDefaultSuites().copy(); + protected Suites createSuites(OptionValues opts) { + Suites ret = backend.getSuites().getDefaultSuites(opts).copy(); ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); if (iter == null) { /* @@ -293,16 +332,14 @@ public abstract class GraalCompilerTest extends GraalTest { return ret; } - protected LIRSuites createLIRSuites() { - LIRSuites ret = backend.getSuites().getDefaultLIRSuites().copy(); + protected LIRSuites createLIRSuites(OptionValues opts) { + LIRSuites ret = backend.getSuites().getDefaultLIRSuites(opts).copy(); return ret; } public GraalCompilerTest() { this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -321,8 +358,6 @@ public abstract class GraalCompilerTest extends GraalTest { this.backend = runtime.getHostBackend(); } this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -333,8 +368,6 @@ public abstract class GraalCompilerTest extends GraalTest { public GraalCompilerTest(Backend backend) { this.backend = backend; this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } private Scope debugScope; @@ -532,14 +565,6 @@ public abstract class GraalCompilerTest extends GraalTest { return backend; } - protected Suites getSuites() { - return suites.getValue(); - } - - protected LIRSuites getLIRSuites() { - return lirSuites.getValue(); - } - protected final Providers getProviders() { return providers; } @@ -621,7 +646,7 @@ public abstract class GraalCompilerTest extends GraalTest { return invoke(method, receiver, args); } - protected static class Result { + public static class Result { public final Object returnValue; public final Throwable exception; @@ -665,12 +690,16 @@ public abstract class GraalCompilerTest extends GraalTest { } protected Result executeActual(ResolvedJavaMethod method, Object receiver, Object... args) { + return executeActual(getInitialOptions(), method, receiver, args); + } + + protected Result executeActual(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { before(method); Object[] executeArgs = argsWithReceiver(receiver, args); checkArgs(method, executeArgs); - InstalledCode compiledMethod = getCode(method); + InstalledCode compiledMethod = getCode(method, options); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { @@ -718,14 +747,19 @@ public abstract class GraalCompilerTest extends GraalTest { return applyArgSuppliers(executeArgs); } - protected void test(String name, Object... args) { + protected final Result test(String name, Object... args) { + return test(getInitialOptions(), name, args); + } + + protected final Result test(OptionValues options, String name, Object... args) { try { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; - test(method, receiver, args); + return test(options, method, receiver, args); } catch (AssumptionViolatedException e) { // Suppress so that subsequent calls to this method within the // same Junit @Test annotated method can proceed. + return null; } } @@ -745,12 +779,16 @@ public abstract class GraalCompilerTest extends GraalTest { return supplier; } - protected void test(ResolvedJavaMethod method, Object receiver, Object... args) { + protected Result test(ResolvedJavaMethod method, Object receiver, Object... args) { + return test(getInitialOptions(), method, receiver, args); + } + + protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); - if (getCodeCache() == null) { - return; + if (getCodeCache() != null) { + testAgainstExpected(options, method, expect, receiver, args); } - testAgainstExpected(method, expect, receiver, args); + return expect; } /** @@ -770,17 +808,30 @@ public abstract class GraalCompilerTest extends GraalTest { return res; } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(method, expect, Collections. emptySet(), receiver, args); + protected final void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, Collections. emptySet(), receiver, args); } - protected Result executeActualCheckDeopt(ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { + protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, shouldNotDeopt, receiver, args); + } + + protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(options, method, expect, Collections. emptySet(), receiver, args); + } + + protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + Result actual = executeActualCheckDeopt(options, method, shouldNotDeopt, receiver, args); + assertEquals(expect, actual); + } + + protected Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); } - Result actual = executeActual(method, receiver, args); + Result actual = executeActual(options, method, receiver, args); profile = method.getProfilingInfo(); // profile can change after execution for (DeoptimizationReason reason : shouldNotDeopt) { Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); @@ -801,19 +852,18 @@ public abstract class GraalCompilerTest extends GraalTest { } } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - Result actual = executeActualCheckDeopt(method, shouldNotDeopt, receiver, args); - assertEquals(expect, actual); - } - private Map cache = new HashMap<>(); /** * Gets installed code for a given method, compiling it first if necessary. The graph is parsed - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions) eagerly}. + * {@link #parseEager eagerly}. */ - protected InstalledCode getCode(ResolvedJavaMethod method) { - return getCode(method, null); + protected final InstalledCode getCode(ResolvedJavaMethod method) { + return getCode(method, null, false, false, getInitialOptions()); + } + + protected final InstalledCode getCode(ResolvedJavaMethod method, OptionValues options) { + return getCode(method, null, false, false, options); } /** @@ -823,12 +873,8 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled. If null, a graph will be obtained from * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. */ - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return getCode(installedCodeOwner, graph, false); - } - - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph0, boolean forceCompile) { - return getCode(installedCodeOwner, graph0, forceCompile, false); + protected final InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { + return getCode(installedCodeOwner, graph, false, false, graph == null ? getInitialOptions() : graph.getOptions()); } /** @@ -839,10 +885,24 @@ public abstract class GraalCompilerTest extends GraalTest { * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. * @param forceCompile specifies whether to ignore any previous code cached for the (method, * key) pair - * @param installDefault specifies whether to install as the default implementation + */ + protected final InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { + return getCode(installedCodeOwner, graph, forceCompile, false, graph == null ? getInitialOptions() : graph.getOptions()); + } + + /** + * Gets installed code for a given method and graph, compiling it first if necessary. + * + * @param installedCodeOwner the method the compiled code will be associated with when installed + * @param graph the graph to be compiled. If null, a graph will be obtained from + * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. + * @param forceCompile specifies whether to ignore any previous code cached for the (method, + * key) pair + * @param installAsDefault specifies whether to install as the default implementation + * @param options the options that will be used in {@link #parseForCompile(ResolvedJavaMethod)} */ @SuppressWarnings("try") - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installDefault) { + protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { if (!forceCompile) { InstalledCode cached = cache.get(installedCodeOwner); if (cached != null) { @@ -851,41 +911,54 @@ public abstract class GraalCompilerTest extends GraalTest { } } } + // loop for retrying compilation + for (int retry = 0; retry <= BAILOUT_RETRY_LIMIT; retry++) { + final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); - final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); - - InstalledCode installedCode = null; - try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), installedCodeOwner.getSignature())); - } - long start = System.currentTimeMillis(); - CompilationResult compResult = compile(installedCodeOwner, graph, id); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); - } - - try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { - if (installDefault) { - installedCode = addDefaultMethod(installedCodeOwner, compResult); - } else { - installedCode = addMethod(installedCodeOwner, compResult); + InstalledCode installedCode = null; + try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { + final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); + if (printCompilation) { + TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), + installedCodeOwner.getSignature())); } - if (installedCode == null) { - throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + long start = System.currentTimeMillis(); + CompilationResult compResult = compile(installedCodeOwner, graph, new CompilationResult(), id, options); + if (printCompilation) { + TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); + } + + try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { + try { + if (installAsDefault) { + installedCode = addDefaultMethod(installedCodeOwner, compResult); + } else { + installedCode = addMethod(installedCodeOwner, compResult); + } + if (installedCode == null) { + throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + } + } catch (BailoutException e) { + if (retry <= BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) { + // retry (if there is no predefined graph) + TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id)); + continue; + } + throw e; + } + } catch (Throwable e) { + throw Debug.handle(e); } } catch (Throwable e) { throw Debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); - } - if (!forceCompile) { - cache.put(installedCodeOwner, installedCode); + if (!forceCompile) { + cache.put(installedCodeOwner, installedCode); + } + return installedCode; } - return installedCode; + throw GraalError.shouldNotReachHere(); } /** @@ -893,15 +966,18 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method * is null. * - * The default implementation in {@link GraalCompilerTest} is to call - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions)}. + * The default implementation in {@link GraalCompilerTest} is to call {@link #parseEager}. */ - protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { - return parseEager(method, AllowAssumptions.YES); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options); } - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - return parseEager(method, AllowAssumptions.YES, compilationId); + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), getInitialOptions()); + } + + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, compilationId, options); } /** @@ -913,11 +989,18 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #parseForCompile(ResolvedJavaMethod)}. */ protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return compile(installedCodeOwner, graph, getOrCreateCompilationId(installedCodeOwner, graph)); + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { - return compile(installedCodeOwner, graph, new CompilationResult(), compilationId); + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), compilationId, options); + } + + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) { + assert graph == null || graph.getOptions() == options; + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } /** @@ -927,16 +1010,16 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled for {@code installedCodeOwner}. If null, a graph will * be obtained from {@code installedCodeOwner} via * {@link #parseForCompile(ResolvedJavaMethod)}. - * @param compilationResult * @param compilationId */ @SuppressWarnings("try") - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId) { - StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId) : graph; + protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId, options) : graph; lastCompiledGraph = graphToCompile; try (Scope s = Debug.scope("Compile", graphToCompile)) { + assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - graphToCompile.getProfilingInfo(), getSuites(), getLIRSuites(), compilationResult, CompilationResultBuilderFactory.Default); + graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } catch (Throwable e) { throw Debug.handle(e); @@ -1002,21 +1085,21 @@ public abstract class GraalCompilerTest extends GraalTest { * produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { + protected final StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { return parseProfiled(getResolvedJavaMethod(methodName), allowAssumptions); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault default} mode to * produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseProfiled(m, allowAssumptions, getCompilationId(m)); - } - - protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getDefaultGraphBuilderSuite(), allowAssumptions, compilationId); + protected final StructuredGraph parseProfiled(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse1(method, getDefaultGraphBuilderSuite(), allowAssumptions, getCompilationId(method), getInitialOptions()); } /** @@ -1024,39 +1107,78 @@ public abstract class GraalCompilerTest extends GraalTest { * set to true to produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions) { - return parseEager(getResolvedJavaMethod(methodName), allowAssumptions); + return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, getInitialOptions()); } /** * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} * set to true to produce a graph. + * + * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph */ - protected final StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseEager(m, allowAssumptions, getCompilationId(m)); + protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, OptionValues options) { + return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, options); } - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId); + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parseEager(method, allowAssumptions, getCompilationId(method), getInitialOptions()); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { + return parseEager(method, allowAssumptions, getCompilationId(method), options); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param compilationId the compilation identifier to be associated with the graph + * @param options the option values to be used when compiling the graph + */ + protected StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId, options); } /** * Parses a Java method using {@linkplain GraphBuilderConfiguration#withFullInfopoints(boolean) * full debug} set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseDebug(m, allowAssumptions, getCompilationId(m)); - } - - protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, compilationId); + protected StructuredGraph parseDebug(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, getCompilationId(method), + getInitialOptions()); } @SuppressWarnings("try") - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { + private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, + OptionValues options) { assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, getSpeculationLog(), compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options, allowAssumptions).method(javaMethod).speculationLog(getSpeculationLog()).useProfilingInfo(true).compilationId( + compilationId).build(); try (Scope ds = Debug.scope("Parsing", javaMethod, graph)) { graphBuilderSuite.apply(graph, getDefaultHighTierContext()); return graph; @@ -1186,4 +1308,13 @@ public abstract class GraalCompilerTest extends GraalTest { protected boolean isArchitecture(String name) { return name.equals(backend.getTarget().arch.getName()); } + + /** + * This method should be called in "timeout" tests which JUnit runs in a different thread. + */ + public static void initializeForTimeout() { + // timeout tests run in a separate thread which needs the DebugEnvironment to be + // initialized + DebugEnvironment.ensureInitialized(getInitialOptions()); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java index 6dd6b2b5b19..7f319c38a80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java @@ -71,7 +71,7 @@ public class GraphEncoderTest extends GraalCompilerTest { encoder.prepare(originalGraph); } encoder.finishPrepare(); - Map startOffsets = new HashMap<>(); + Map startOffsets = new HashMap<>(); for (StructuredGraph originalGraph : originalGraphs) { startOffsets.put(originalGraph, encoder.encode(originalGraph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java deleted file mode 100644 index ee219719139..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.BeginNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.GuardNode; -import org.graalvm.compiler.nodes.LogicNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.java.InstanceOfNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.ValueProxy; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; - -public class GuardEliminationCornerCasesTest extends GraalCompilerTest { - - static class A { - - } - - static class B extends A { - - } - - static class C extends B { - - } - - static class D extends C { - - } - - @SuppressWarnings({"static-method", "unused"}) - private int testMethod(Object a) { - if (a instanceof A) { - if (a instanceof C) { - if (a instanceof B) { - B b = (B) a; - if (b instanceof C) { - return 1; - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - return 0; - } - - @Test - public void testFloatingGuards() { - HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = parseEager("testMethod", AllowAssumptions.YES); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after parsing"); - - GuardNode myGuardNode = null; - for (Node n : graph.getNodes()) { - if (n instanceof GuardNode) { - GuardNode guardNode = (GuardNode) n; - LogicNode condition = guardNode.getCondition(); - if (condition instanceof InstanceOfNode) { - InstanceOfNode instanceOfNode = (InstanceOfNode) condition; - if (instanceOfNode.getValue() instanceof ValueProxy) { - myGuardNode = guardNode; - break; - } - } - } - } - - AbstractBeginNode myBegin = (AbstractBeginNode) myGuardNode.getAnchor(); - AbstractBeginNode prevBegin = BeginNode.prevBegin((FixedNode) myBegin.predecessor()); - myGuardNode.setAnchor(prevBegin); - - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after manual modification"); - graph.reverseUsageOrder(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST).apply(graph); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java index a84872e309b..ac2b54f6d2e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java @@ -24,10 +24,6 @@ package org.graalvm.compiler.core.test; import java.util.List; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; @@ -45,6 +41,10 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -111,8 +111,8 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { private StructuredGraph parsedForCompile; @Override - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - graph = super.parseForCompile(method, compilationId); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + graph = super.parseForCompile(method, compilationId, options); parsedForCompile = (StructuredGraph) graph.copy(); return graph; } @@ -209,7 +209,7 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { @Override public int hashCode() { int result = ((identity == null) ? 0 : identity.hashCode()); - return result + object.hashCode(); + return result + System.identityHashCode(object); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java index eb9b5ce1162..66be994fff3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.MidTierContext; @@ -151,8 +152,9 @@ public class HashCodeTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph buildGraphAfterMidTier(String name) { StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - new HighTier().apply(g, getDefaultHighTierContext()); - new MidTier().apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); + OptionValues options = getInitialOptions(); + new HighTier(options).apply(g, getDefaultHighTierContext()); + new MidTier(options).apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); return g; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java index 0cf12a00ffb..01235b6b9c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java @@ -38,7 +38,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -148,7 +147,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest { @Test public void test6() { - testCombinedIf("test6Snippet", 3); + testCombinedIf("test6Snippet", 4); test("test6Snippet", new int[]{0}); } @@ -205,7 +204,6 @@ public class IfCanonicalizerTest extends GraalCompilerTest { MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new ValueAnchorCleanupPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java index f93a6f7c3f8..93c8f0fc904 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java @@ -25,10 +25,6 @@ package org.graalvm.compiler.core.test; import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; import static org.junit.Assert.assertNotNull; -import jdk.vm.ci.code.site.Call; -import jdk.vm.ci.code.site.Infopoint; -import jdk.vm.ci.code.site.InfopointReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; @@ -42,6 +38,11 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; +import jdk.vm.ci.code.site.Call; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.ResolvedJavaMethod; + /** * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. */ @@ -63,7 +64,7 @@ public class InfopointReasonTest extends GraalCompilerTest { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(method, AllowAssumptions.YES); final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -75,7 +76,7 @@ public class InfopointReasonTest extends GraalCompilerTest { @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method, AllowAssumptions.from(OptAssumptions.getValue())); + final StructuredGraph graph = parseDebug(method, AllowAssumptions.ifTrue(OptAssumptions.getValue(getInitialOptions()))); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { if (ipn.getReason() == InfopointReason.BYTECODE_POSITION) { @@ -84,8 +85,8 @@ public class InfopointReasonTest extends GraalCompilerTest { } assertTrue(graphLineSPs > 0); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); - final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), getSuites(), - getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java index 7a450de3281..cb6e4e09b58 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java @@ -22,12 +22,11 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.InvalidInstalledCodeException; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; public class InstalledCodeInvalidationTest extends GraalCompilerTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java index f580313a3fd..4dca5901e9b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java @@ -26,19 +26,18 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import org.junit.Test; - import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.test.ExportingClassLoader; +import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; -public final class InterfaceMethodHandleTest extends GraalCompilerTest implements Opcodes { +public final class InterfaceMethodHandleTest extends GraalCompilerTest { private static final MethodHandle INTERFACE_HANDLE_M; private static final MethodHandle INTERFACE_HANDLE_M2; @@ -136,58 +135,65 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement private static final String BASENAME = InterfaceMethodHandleTest.class.getName(); private static final String NAME = BASENAME + "_B"; - private AsmLoader loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + private final AsmLoader loader; - /** - * Construct a type which claims to implement {@link I} but with incorrect access on {@link I#m} - * so that an exception must be thrown. - */ - public static byte[] bytesForB() { + public InterfaceMethodHandleTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + } - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - String jvmName = NAME.replace('.', '/'); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); + static class Gen implements Opcodes { + /** + * Construct a type which claims to implement {@link I} but with incorrect access on + * {@link I#m} so that an exception must be thrown. + */ + public static byte[] bytesForB() { - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + String jvmName = NAME.replace('.', '/'); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); - mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 11); - mv.visitEnd(); + cw.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 11); + mv.visitEnd(); - return cw.toByteArray(); + cw.visitEnd(); + + return cw.toByteArray(); + } } public static class AsmLoader extends ExportingClassLoader { @@ -203,7 +209,7 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement if (loaded != null) { return loaded; } - byte[] bytes = bytesForB(); + byte[] bytes = Gen.bytesForB(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java index 9e0d5a9430b..9cfc71bd305 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java @@ -35,7 +35,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -101,7 +100,6 @@ public class LockEliminationTest extends GraalCompilerTest { new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new ValueAnchorCleanupPhase().apply(graph); new LockEliminationPhase().apply(graph); return graph; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java index 75c5d71b369..bf1a63b61e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java @@ -24,15 +24,12 @@ package org.graalvm.compiler.core.test; import jdk.vm.ci.meta.JavaConstant; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Assert; import org.junit.Test; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; @@ -55,7 +52,7 @@ public class LongNodeChainTest extends GraalCompilerTest { private void longAddChain(boolean reverse) { HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).build(); ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1)); ValueNode value = null; if (reverse) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java index ae12cbfd4dc..e4a74f9b4b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java @@ -28,12 +28,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; public class MemoryArithmeticTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return getCode(method, graph, true); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, true, installAsDefault, options); } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java index 398fc133e0d..4027868516f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,7 @@ import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; @@ -89,6 +88,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { private static final Container container = new Container(); private static final List containerList = new ArrayList<>(); + private static final double LOOP_ENTRY_PROBABILITY = 0.9; /** * In this test the read should be scheduled before the write. @@ -165,7 +165,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -190,7 +190,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -213,7 +213,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop3Snippet(int a) { int j = 0; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (i - container.a == 0) { break; } @@ -246,7 +246,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop5Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; @@ -272,13 +272,13 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop6Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -301,15 +301,15 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop7Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int k = 0; k < a; ++k) { + for (int k = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, k < a); ++k) { if (k % 2 == 1) { - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -333,12 +333,12 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop8Snippet(int a, int b) { int result = container.a; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; break; } else { - for (int j = 0; j < b; j++) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); j++) { container.a = 0; } } @@ -378,25 +378,6 @@ public class MemoryScheduleTest extends GraphScheduleTest { Assert.assertEquals(0, readBlock.getLoopDepth()); } - /** - * Here the read should float to the end (into the same block as the return). - */ - public static int testArrayCopySnippet(Integer intValue, char[] a, char[] b, int len) { - System.arraycopy(a, 0, b, 0, len); - return intValue.intValue(); - } - - @Test - public void testArrayCopy() { - ScheduleResult schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); - StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); - assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); - ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); - assertTrue(ret.result() + " should be a FloatingReadNode", ret.result() instanceof FloatingReadNode); - assertDeepEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); - assertReadWithinAllReturnBlocks(schedule, true); - } - /** * Here the read should not float to the end. */ @@ -644,7 +625,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop4Snippet(int count) { int[] a = new int[count]; - for (int i = 0; i < a.length; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a.length); i++) { a[i] = i; } @@ -652,7 +633,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { int iwrap = count - 1; int sum = 0; - while (i < count) { + while (GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < count)) { sum += (a[i] + a[iwrap]) / 2; iwrap = i; i++; @@ -723,34 +704,33 @@ public class MemoryScheduleTest extends GraphScheduleTest { @SuppressWarnings("try") private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + OptionValues options = new OptionValues(getInitialOptions(), OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, options); try (Scope d = Debug.scope("FloatingReadTest", graph)) { - try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { - HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - canonicalizer.apply(graph, context); - if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - new InliningPhase(canonicalizer).apply(graph, context); - } - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - graph.clearAllStateAfter(); - } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates"); - - new FloatingReadPhase().apply(graph); - new RemoveValueProxyPhase().apply(graph); - - MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); - - SchedulePhase schedule = new SchedulePhase(schedulingStrategy); - schedule.apply(graph); - assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); - return graph.getLastSchedule(); + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + new InliningPhase(canonicalizer).apply(graph, context); } + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + graph.clearAllStateAfter(); + } + Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates"); + + new FloatingReadPhase().apply(graph); + new RemoveValueProxyPhase().apply(graph); + + MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); + new GuardLoweringPhase().apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); + + SchedulePhase schedule = new SchedulePhase(schedulingStrategy); + schedule.apply(graph); + assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); + return graph.getLastSchedule(); } catch (Throwable e) { throw Debug.handle(e); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java index 458227396f4..15d714f1878 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java @@ -31,7 +31,9 @@ import org.junit.Test; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.test.AddExports; +@AddExports("java.base/java.lang") public final class MethodHandleEagerResolution extends GraalCompilerTest { private static final MethodHandle FIELD_HANDLE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java index ee5ca6685a8..2d1a58d1136 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java @@ -74,7 +74,7 @@ public class NodePropertiesTest extends GraalCompilerTest { } sideEffect = null; // cannot shift - return a * x * 3; + return a * x * 41; } public static final int ITERATIONS_LOOP_1 = 128; @@ -298,7 +298,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(120, gc1.finalCycles, 25); + Assert.assertEquals(40, gc1.finalCycles, 25); } static class ImprovementSavingCanonicalizer extends CustomCanonicalizer { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java index ea1de661d3f..a0091273103 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java @@ -41,25 +41,23 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.ServiceLoader; import java.util.Set; -import org.junit.Test; - import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.test.GraalTest; - -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import org.junit.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; /** - * Verifies a class declaring one or more {@linkplain OptionValue options} has a class initializer + * Verifies a class declaring one or more {@linkplain OptionKey options} has a class initializer * that only initializes the option(s). This sanity check mitigates the possibility of an option * value being used before being set. */ @@ -69,7 +67,7 @@ public class OptionsVerifierTest { public void verifyOptions() throws IOException { try (Classpath cp = new Classpath()) { HashSet> checked = new HashSet<>(); - for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, getClass().getClassLoader())) { + for (OptionDescriptors opts : OptionsParser.getOptionsLoader()) { for (OptionDescriptor desc : opts) { OptionsVerifier.checkClass(desc.getDeclaringClass(), desc, checked, cp); } @@ -259,7 +257,7 @@ public class OptionsVerifierTest { private boolean checkInvokeTarget(Executable method) { Class holder = method.getDeclaringClass(); if (method instanceof Constructor) { - if (OptionValue.class.isAssignableFrom(holder)) { + if (OptionKey.class.isAssignableFrom(holder)) { return true; } } else if (Arrays.asList(boxingTypes).contains(holder)) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java index 9cfacabc7b8..3b07d6a8053 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java @@ -26,6 +26,7 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaType; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.graalvm.compiler.debug.Debug; @@ -42,7 +43,6 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; public class PushNodesThroughPiTest extends GraalCompilerTest { @@ -72,6 +72,7 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { return ret; } + @Ignore @Test @SuppressWarnings("try") public void test1() { @@ -105,7 +106,6 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PushThroughPiPhase().apply(graph); canonicalizer.apply(graph, context); return graph; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java index 57ca56a6aae..5f186df6599 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; /* consider @@ -93,7 +92,6 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); - new OptimizeGuardAnchorsPhase().apply(graph); canonicalizer.apply(graph, context); Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java index 6596d4d22c5..b4737bfb441 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java @@ -242,7 +242,7 @@ public class ReentrantBlockIteratorTest extends GraalCompilerTest { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); // schedule for IGV - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); return blocks; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java index f750ecd1d49..9832f1323f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Assert; import org.junit.Test; @@ -48,7 +46,7 @@ public class SimpleCFGTest extends GraalCompilerTest { @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); EndNode trueEnd = graph.add(new EndNode()); EndNode falseEnd = graph.add(new EndNode()); @@ -109,7 +107,13 @@ public class SimpleCFGTest extends GraalCompilerTest { } public static void assertDominatedSize(Block block, int size) { - Assert.assertEquals("number of dominated blocks of " + block, size, block.getDominated().size()); + int count = 0; + Block domChild = block.getFirstDominated(); + while (domChild != null) { + count++; + domChild = domChild.getDominatedSibling(); + } + Assert.assertEquals("number of dominated blocks of " + block, size, count); } public static void assertPostdominator(Block block, Block expectedPostdominator) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java index 235f31292e6..fd749aec09d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java @@ -22,27 +22,20 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; import java.lang.reflect.Method; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assume; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.DelegatingDebugConfig; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; @@ -50,6 +43,11 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.test.GraalTest; +import org.junit.Assume; +import org.junit.Test; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Test that interfaces are correctly initialized by a static field resolution during eager graph @@ -92,7 +90,7 @@ public class StaticInterfaceFieldTest extends GraalTest { final Method m = getMethod(clazz, methodName); ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("GraphBuilding", graph, method)) { graphBuilderSuite.apply(graph, context); } catch (Throwable e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java index 2dc0a53fe30..73356c8669b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java @@ -186,12 +186,12 @@ public class TypeSystemTest extends GraalCompilerTest { * tail-duplication gets activated thus resulting in a graph with more nodes than the * reference graph. */ - new DominatorConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders())); + DominatorConditionalEliminationPhase.create(false).apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); - new DominatorConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders())); + DominatorConditionalEliminationPhase.create(false).apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); @@ -208,7 +208,7 @@ public class TypeSystemTest extends GraalCompilerTest { public static void outputGraph(StructuredGraph graph, String message) { TTY.println("========================= " + message); - SchedulePhase schedulePhase = new SchedulePhase(); + SchedulePhase schedulePhase = new SchedulePhase(graph.getOptions()); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); for (Block block : schedule.getCFG().getBlocks()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java index e6e6249aff8..6b44e9c7a97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java @@ -123,7 +123,7 @@ public class TypeWriterTest extends GraalCompilerTest { UnsafeArrayTypeWriter writer = UnsafeArrayTypeWriter.create(supportsUnalignedMemoryAccess); putValues(writer); - byte[] array = new byte[(int) writer.getBytesWritten()]; + byte[] array = new byte[TypeConversion.asU4(writer.getBytesWritten())]; writer.toArray(array); UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(array, 0, supportsUnalignedMemoryAccess); checkValues(reader); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java index 2c96072aa48..ea9587d8ec2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java @@ -22,24 +22,20 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - -import org.junit.Test; - import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Exercise handling of unbalanced monitor operations by the parser. Algorithmically Graal assumes @@ -49,12 +45,16 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; * handle this directly is simplifying for targets of Graal since they don't have to provide a data * flow that checks this property. */ -public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes { +public class UnbalancedMonitorsTest extends GraalCompilerTest { private static final String CLASS_NAME = UnbalancedMonitorsTest.class.getName(); private static final String INNER_CLASS_NAME = CLASS_NAME + "$UnbalancedMonitors"; private static final String CLASS_NAME_INTERNAL = CLASS_NAME.replace('.', '/'); private static final String INNER_CLASS_NAME_INTERNAL = INNER_CLASS_NAME.replace('.', '/'); + public UnbalancedMonitorsTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } + private static AsmLoader LOADER = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); @Test @@ -85,7 +85,7 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes private void checkForBailout(String name) throws ClassNotFoundException { ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name); try { - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); Plugins plugins = new Plugins(new InvocationPlugins(getMetaAccess())); GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; @@ -101,6 +101,8 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes assertTrue("should have bailed out", false); } + static class Gen implements Opcodes { + // @formatter:off // Template class used with Bytecode Outline to generate ASM code // public static class UnbalancedMonitors { @@ -134,165 +136,167 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes // } // @formatter:on - public static byte[] generateClass() { + public static byte[] generateClass() { - ClassWriter cw = new ClassWriter(0); + ClassWriter cw = new ClassWriter(0); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); - cw.visitSource("UnbalancedMonitorsTest.java", null); + cw.visitSource("UnbalancedMonitorsTest.java", null); - cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); + cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); - visitConstructor(cw); - visitWrongOrder(cw); - visitBlockStructured(cw, true, false); - visitBlockStructured(cw, true, true); - visitBlockStructured(cw, false, false); - visitBlockStructured(cw, false, true); - cw.visitEnd(); + visitConstructor(cw); + visitWrongOrder(cw); + visitBlockStructured(cw, true, false); + visitBlockStructured(cw, true, true); + visitBlockStructured(cw, false, false); + visitBlockStructured(cw, false, true); + cw.visitEnd(); - return cw.toByteArray(); - } + return cw.toByteArray(); + } - private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { - String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); - // Generate too many or too few exits down the either the normal or exceptional return paths - int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); - int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - for (int i = 0; i < normalExitCount; i++) { + private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { + String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); + // Generate too many or too few exits down the either the normal or exceptional return + // paths + int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); + int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l1); + for (int i = 0; i < normalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l5); + mv.visitInsn(IRETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); + for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); + } + + private static void visitWrongOrder(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); - } - mv.visitLabel(l5); - mv.visitInsn(IRETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitLabel(l1); + // Swapped exit order with exit above + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l5); + mv.visitInsn(ARETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); } - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - private static void visitWrongOrder(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - // Swapped exit order with exit above - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l5); - mv.visitInsn(ARETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - - private static void visitConstructor(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitInsn(RETURN); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitMaxs(1, 1); - mv.visitEnd(); + private static void visitConstructor(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitInsn(RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } } public static class AsmLoader extends ClassLoader { @@ -308,7 +312,7 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java index 7e8914b2991..7e685a24492 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java @@ -22,11 +22,6 @@ */ package org.graalvm.compiler.core.test; -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -34,27 +29,19 @@ import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; import sun.misc.Unsafe; public class UnsafeReadEliminationTest extends GraalCompilerTest { - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - public static long[] Memory = new long[]{1, 2}; public static double SideEffectD; public static double SideEffectL; @@ -129,15 +116,16 @@ public class UnsafeReadEliminationTest extends GraalCompilerTest { } public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) { + OptionValues options = graph.getOptions(); PhaseContext context = getDefaultHighTierContext(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count()); // after lowering the same applies for reads and writes new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(reads, graph.getNodes().filter(ReadNode.class).count()); Assert.assertEquals(writes, graph.getNodes().filter(WriteNode.class).count()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java new file mode 100644 index 00000000000..236be5cff40 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.lang.reflect.Field; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Test; + +public class UnsafeVirtualizationTest extends GraalCompilerTest { + + public static class A { + int f1; + int f2; + } + + private static final long AF1Offset; + private static final long AF2Offset; + static { + long o1 = -1; + long o2 = -1; + try { + Field f1 = A.class.getDeclaredField("f1"); + Field f2 = A.class.getDeclaredField("f2"); + o1 = UNSAFE.objectFieldOffset(f1); + o2 = UNSAFE.objectFieldOffset(f2); + } catch (NoSuchFieldException | SecurityException e) { + throw new AssertionError(e); + } + AF1Offset = o1; + AF2Offset = o2; + } + + public static int unsafeSnippet0(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset); + } + + public static int unsafeSnippet1(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + a.f2 = i1; + return (int) UNSAFE.getDouble(a, AF1Offset); + } + + @Test + public void testUnsafePEA01() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), true); + } + + @Test + public void testUnsafePEA02() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), true); + } + + public void testPartialEscapeReadElimination(StructuredGraph graph, boolean canonicalizeBefore) { + OptionValues options = graph.getOptions(); + PhaseContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + if (canonicalizeBefore) { + canonicalizer.apply(graph, context); + } + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java index 0a50d9192cf..35e86347ea7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -30,14 +30,13 @@ import java.lang.reflect.Modifier; import org.junit.Test; import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -129,7 +128,7 @@ public class VerifyBailoutUsageTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyBailoutUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java index 00df7430a07..be8c87f5e29 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -37,7 +37,6 @@ import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -307,7 +306,7 @@ public class VerifyDebugUsageTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java index 855be893315..343aceef50e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; @@ -40,7 +40,6 @@ import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -274,7 +273,7 @@ public class VerifyVirtualizableTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyVirtualizableUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java index 5f689224d48..486420bc279 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java @@ -45,12 +45,12 @@ public abstract class BackendTest extends GraalCompilerTest { @SuppressWarnings("try") protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) { try (Scope s = Debug.scope("FrontEnd")) { - GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), getSuites()); + GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions())); } catch (Throwable e) { throw Debug.handle(e); } - LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, getLIRSuites()); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); return lirGen; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java index 5704e05f80b..5186169b13f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java @@ -26,7 +26,6 @@ import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -36,7 +35,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; - +import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; @@ -63,8 +62,7 @@ import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.calc.ShiftNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; import org.graalvm.compiler.nodes.calc.SubNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -241,30 +239,26 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { static DebugConfig overrideGraalDebugConfig(PrintStream log, String methodFilter, String methodMeter) { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), - GraalDebugConfig.Options.Count.getValue(), - GraalDebugConfig.Options.TrackMemUse.getValue(), - GraalDebugConfig.Options.Time.getValue(), - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), + GraalDebugConfig.Options.Count.getValue(options), + GraalDebugConfig.Options.TrackMemUse.getValue(options), + GraalDebugConfig.Options.Time.getValue(options), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), methodFilter, methodMeter, log, dumpHandlers, verifyHandlers); return debugConfig; } - private static OverrideScope overrideMetricPrinterConfig() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - abstract Phase additionalPhase(); @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites ret = super.createSuites(options); ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); PhaseSuite.findNextPhase(iter, CanonicalizerPhase.class); iter.add(additionalPhase()); @@ -274,7 +268,7 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { @Test @SuppressWarnings("try") public void test() throws Throwable { - try (DebugConfigScope s = Debug.setConfig(getConfig()); OverrideScope o = getOScope();) { + try (DebugConfigScope s = Debug.setConfig(getConfig())) { executeMethod(TestApplication.class.getMethod("m01", testSignature), null, testArgs); executeMethod(TestApplication.class.getMethod("m02", testSignature), null, testArgs); executeMethod(TestApplication.class.getMethod("m03", testSignature), null, testArgs); @@ -289,6 +283,11 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { } } + void executeMethod(Method m, Object receiver, Object... args) { + OptionValues options = new OptionValues(getInitialOptions(), MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); + test(options, asResolvedJavaMethod(m), receiver, args); + } + @Before public void rememberScopeId() { scopeIdBeforeAccess = DebugScope.getCurrentGlobalScopeId(); @@ -301,10 +300,6 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { abstract DebugConfig getConfig(); - OverrideScope getOScope() { - return overrideMetricPrinterConfig(); - } - abstract void assertValues() throws Throwable; @SuppressWarnings("unchecked") @@ -312,7 +307,7 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { Map threadLocalMap = null; for (Field f : MethodMetricsImpl.class.getDeclaredFields()) { if (f.getName().equals("threadEntries")) { - f.setAccessible(true); + Util.setAccessible(f, true); Object map; try { map = ((ThreadLocal) f.get(null)).get(); @@ -373,9 +368,4 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { throw new RuntimeException(t); } } - - void executeMethod(Method m, Object receiver, Object... args) { - test(asResolvedJavaMethod(m), receiver, args); - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java index ba51364d087..fdb9704e712 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java @@ -23,9 +23,7 @@ package org.graalvm.compiler.core.test.debug; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.Test; @@ -43,9 +41,7 @@ import org.graalvm.compiler.debug.internal.CounterImpl; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; import org.graalvm.compiler.debug.internal.TimerImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -62,26 +58,21 @@ public class MethodMetricsTestInterception01 extends MethodMetricsTest { DebugConfig getConfig() { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), "CountingAddPhase", - GraalDebugConfig.Options.TrackMemUse.getValue(), + GraalDebugConfig.Options.TrackMemUse.getValue(options), "CountingAddPhase", - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), "MethodMetricsTest$TestApplication.*", "CountingAddPhase", System.out, dumpHandlers, verifyHandlers); return debugConfig; } - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - private DebugValueFactory factory; @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java index e00c2c89b25..af0d01c7961 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java @@ -23,9 +23,7 @@ package org.graalvm.compiler.core.test.debug; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.Test; @@ -42,9 +40,7 @@ import org.graalvm.compiler.debug.DebugValueFactory; import org.graalvm.compiler.debug.DebugVerifyHandler; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -127,13 +123,6 @@ public class MethodMetricsTestInterception02 extends MethodMetricsTest { }); } - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - @Test @Override public void test() throws Throwable { @@ -151,13 +140,15 @@ public class MethodMetricsTestInterception02 extends MethodMetricsTest { DebugConfig getConfig() { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), ""/* unscoped meter */, - GraalDebugConfig.Options.TrackMemUse.getValue(), + GraalDebugConfig.Options.TrackMemUse.getValue(options), ""/* unscoped time */, - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), null /* no method filter */, "" /* unscoped method metering */, System.out, dumpHandlers, verifyHandlers); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java index ccfc04fd822..d66191f7200 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java @@ -22,13 +22,11 @@ */ package org.graalvm.compiler.core.test.debug; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; @@ -36,7 +34,6 @@ import org.graalvm.compiler.debug.DebugMethodMetrics; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -48,6 +45,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -256,7 +254,7 @@ public class VerifyMethodMetricsTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java index 6ac8dd399ec..a5fa7f07f8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java @@ -66,7 +66,7 @@ public final class SafepointRethrowDeoptTest extends GraalCompilerTest { @Test public void test() { - Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue()); + Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue(getInitialOptions())); synchronized (SafepointRethrowDeoptTest.class) { // needs static fields terminate = 1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java index 735da745498..6be1e45f8d6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java @@ -160,7 +160,7 @@ public class EATestBase extends GraalCompilerTest { new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); - new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); } catch (Throwable e) { throw Debug.handle(e); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java index ebb431f5c3d..3af2ec92d7c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,21 +22,26 @@ */ package org.graalvm.compiler.core.test.ea; -import jdk.vm.ci.meta.JavaConstant; - -import org.junit.Assert; -import org.junit.Test; +import java.util.List; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ReturnNode; +import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; +import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.JavaConstant; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct @@ -179,6 +184,50 @@ public class EscapeAnalysisTest extends EATestBase { return obj.x <= 3 ? 1 : 0; } + @Test + public void testMergeAllocationsInt2() { + testEscapeAnalysis("testMergeAllocationsInt2Snippet", JavaConstant.forInt(1), true); + } + + public int testMergeAllocationsInt2Snippet(int a) { + /* + * The initial object in obj exists until the end of the function, but it can still be + * merged with the one allocated in the else block because noone can observe the identity. + */ + TestClassInt obj = new TestClassInt(1, 2); + if (a < 0) { + notInlineable(); + } else { + obj = new TestClassInt(1, 2); + notInlineable(); + } + return obj.x <= 3 ? 1 : 0; + } + + @Test + public void testMergeAllocationsInt3() { + // ensure that the result is not constant: + assertTrue(testMergeAllocationsInt3Snippet(true)); + assertFalse(testMergeAllocationsInt3Snippet(false)); + + prepareGraph("testMergeAllocationsInt3Snippet", true); + assertFalse(graph.getNodes().filter(ReturnNode.class).first().result().isConstant()); + } + + public boolean testMergeAllocationsInt3Snippet(boolean a) { + TestClassInt phi1; + TestClassInt phi2; + if (a) { + field = new TestClassObject(); + field = new TestClassObject(); + phi1 = phi2 = new TestClassInt(1, 2); + } else { + phi1 = new TestClassInt(2, 3); + phi2 = new TestClassInt(3, 4); + } + return phi1 == phi2; + } + @Test public void testMergeAllocationsObj() { testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false); @@ -259,9 +308,73 @@ public class EscapeAnalysisTest extends EATestBase { return obj.value <= 3 ? 1 : 0; } + /** + * Tests that a graph with allocations that does not make progress during PEA will not be + * changed. + */ + @Test + public void testChangeHandling() { + prepareGraph("testChangeHandlingSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count()); + List nodes = graph.getNodes().snapshot(); + // verify that an additional run doesn't add or remove nodes + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(nodes.size(), graph.getNodeCount()); + for (Node node : nodes) { + Assert.assertTrue(node.isAlive()); + } + } + + public volatile Object field; + + public int testChangeHandlingSnippet(int a) { + Object obj; + Integer one = 1; + obj = new MyException(one); + if (a < 0) { + notInlineable(); + } else { + obj = new Integer(1); + notInlineable(); + } + field = obj; + return 1; + } + + /** + * Test the case where allocations before and during a loop that have no usages other than their + * phi need to be recognized as an important change. This needs a loop so that the allocation is + * not trivially removed by dead code elimination. + */ + @Test + public void testRemovalSpecialCase() { + prepareGraph("testRemovalSpecialCaseSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + // create the situation by removing the if + graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0))); + new CanonicalizerPhase().apply(graph, context); + // verify that an additional run removes all allocations + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); + } + + public volatile int field2; + + public int testRemovalSpecialCaseSnippet(int a) { + Object phi = new Object(); + for (int i = 0; i < a; i++) { + field = null; + if (field2 == 1) { + phi = new Object(); + } + } + return phi == null ? 1 : 0; + } + @Test public void testCheckCast() { - testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false); + testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), true); } public Object testCheckCastSnippet() { @@ -314,7 +427,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testFullyUnrolledLoop() { prepareGraph("testFullyUnrolledLoopSnippet", false); new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); Assert.assertEquals(1, returnNodes.size()); Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); @@ -345,7 +458,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext()); - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); } public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java index 94ca53834f6..c42c6f001d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java @@ -28,7 +28,7 @@ import sun.misc.Unsafe; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -130,7 +130,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe1() { StructuredGraph graph = processMethod("testUnsafe1Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe2Snippet(int v, Object array) { @@ -143,7 +143,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe2() { StructuredGraph graph = processMethod("testUnsafe2Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetObject1 = Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * 1; @@ -159,7 +159,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe3() { StructuredGraph graph = processMethod("testUnsafe3Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe4Snippet(int v, Object[] array) { @@ -173,7 +173,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe4() { StructuredGraph graph = processMethod("testUnsafe4Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1; @@ -189,7 +189,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe5() { StructuredGraph graph = processMethod("testUnsafe5Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } @Override @@ -197,7 +197,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, true, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(false, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java new file mode 100644 index 00000000000..5c3f1c15453 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test.inlining; + +import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; +import org.graalvm.compiler.phases.common.inlining.InliningUtil; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.graalvm.util.EconomicSet; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import sun.misc.Unsafe; + +public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest { + + public static int IntSideEffect; + public static int[] Memory = new int[]{0}; + + public static void recursiveLoopMethodUnsafeLoad(int a) { + if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_INT_BASE_OFFSET) == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodUnsafeLoad(i); + } + } + + public static void recursiveLoopMethodFieldLoad(int a) { + if (IntSideEffect == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodFieldLoad(i); + } + } + + public static void recursiveLoopMethod(int a) { + if (a == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethod(i); + } + } + + private static final boolean LOG_PHASE_TIMINGS = false; + private static int InliningCountLowerBound = 1; + private static int InliningCountUpperBound = 32; + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallUnsafeLoad() { + testAndTime("recursiveLoopMethodUnsafeLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallFieldLoad() { + testAndTime("recursiveLoopMethodFieldLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallNoReads() { + testAndTime("recursiveLoopMethod"); + } + + private void testAndTime(String snippet) { + initializeForTimeout(); + for (int i = InliningCountLowerBound; i < InliningCountUpperBound; i++) { + StructuredGraph g1 = prepareGraph(snippet, i); + StructuredGraph g2 = (StructuredGraph) g1.copy(); + ResolvedJavaMethod method = g1.method(); + long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(new CanonicalizerPhase())); + long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, new CanonicalizerPhase(), g1.getOptions())); + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early partial escape analysis on a graph with %d nested loops compiling method %s\n", elapsedPEA, i, method); + } + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early read elimination on a graph with %d nested loops compiling method %s\n", elapsedRE, i, method); + } + } + } + + private long runAndTimePhase(StructuredGraph g, BasePhase phase) { + HighTierContext context = getDefaultHighTierContext(); + long start = System.currentTimeMillis(); + phase.apply(g, context); + long end = System.currentTimeMillis(); + Debug.dump(Debug.DETAILED_LOG_LEVEL, g, "After %s", phase.contractorName()); + return end - start; + } + + private StructuredGraph prepareGraph(String snippet, int inliningCount) { + ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); + StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); + PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); + HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + Invoke next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + StructuredGraph calleeGraph = parseBytecodes(next.callTarget().targetMethod(), context, canonicalizer); + ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); + for (int i = 0; i < inliningCount; i++) { + next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + EconomicSet canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod); + canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); + Debug.dump(Debug.DETAILED_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); + } + return callerGraph; + } + + private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { + StructuredGraph newGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.NO).method(method).build(); + context.getGraphBuilderSuite().apply(newGraph, context); + new DeadCodeEliminationPhase(Optional).apply(newGraph); + canonicalizer.apply(newGraph, context); + return newGraph; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java deleted file mode 100644 index 4e1d784d4a4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.inlining; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.inlining.InliningUtil; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; - -public class RecursiveInliningTest extends GraalCompilerTest { - - public static int SideEffectI; - public static int[] Memory = new int[]{1, 2}; - - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - - public static void recursiveLoopMethodUnsafeLoad(int a) { - if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_LONG_BASE_OFFSET) == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodUnsafeLoad(i); - } - } - - public static void recursiveLoopMethodFieldLoad(int a) { - if (SideEffectI == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodFieldLoad(i); - } - } - - public static void recursiveLoopMethod(int a) { - if (a == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethod(i); - } - } - - public static final boolean LOG = false; - - public static int IterationsStart = 1; - public static int IterationsEnd = 128; - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallUnsafeLoad() { - testAndTime("recursiveLoopMethodUnsafeLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallFieldLoad() { - testAndTime("recursiveLoopMethodFieldLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallNoReads() { - testAndTime("recursiveLoopMethod"); - } - - private void testAndTime(String snippet) { - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimeEarlyReadEliminationPhase(graph); - if (LOG) { - System.out.printf("Needed %dms to run early read elimination on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimePartialEscapeAnalysis(graph); - if (LOG) { - System.out.printf("Needed %dms to run early partial escape analysis on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - } - - private long runAndTimePartialEscapeAnalysis(StructuredGraph g) { - PartialEscapePhase p = new PartialEscapePhase(true, new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - p.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After PEA"); - return end - start; - } - - private long runAndTimeEarlyReadEliminationPhase(StructuredGraph g) { - EarlyReadEliminationPhase er = new EarlyReadEliminationPhase(new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - er.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After Early Read Elimination"); - return end - start; - } - - @SuppressWarnings("try") - private StructuredGraph getGraph(final String snippet, int nrOfInlinings) { - try (Scope s = Debug.scope("RecursiveInliningTest", new DebugDumpScope(snippet, true))) { - ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); - StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); - PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); - HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - - for (int i = 0; i < nrOfInlinings; i++) { - InvokeNode next = getNextInvoke(callerGraph); - ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); - StructuredGraph calleeGraph = getInlineeGraph(next, callerGraph, context, canonicalizer); - List canonicalizeNodes = new ArrayList<>(); - InliningUtil.inline(next, calleeGraph, false, canonicalizeNodes, calleeMethod); - canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); - Debug.dump(Debug.BASIC_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); - } - new SchedulePhase().apply(callerGraph); - return callerGraph; - } catch (Throwable e) { - throw Debug.handle(e); - } - } - - private static StructuredGraph getInlineeGraph(InvokeNode invoke, StructuredGraph caller, HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph result = InliningUtil.getIntrinsicGraph(context.getReplacements(), invoke.callTarget().targetMethod(), invoke.bci()); - if (result != null) { - return result; - } - return parseBytecodes(invoke.callTarget().targetMethod(), context, canonicalizer, caller); - } - - @SuppressWarnings("try") - private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { - StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null), INVALID_COMPILATION_ID); - if (!caller.isUnsafeAccessTrackingEnabled()) { - newGraph.disableUnsafeAccessTracking(); - } - if (context.getGraphBuilderSuite() != null) { - context.getGraphBuilderSuite().apply(newGraph, context); - } - assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); - new DeadCodeEliminationPhase(Optional).apply(newGraph); - canonicalizer.apply(newGraph, context); - return newGraph; - } - - private static InvokeNode getNextInvoke(StructuredGraph graph) { - return graph.getNodes().filter(InvokeNode.class).first(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java index c722047e256..66f5e038953 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.core.test.tutorial; import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCompilationRequest; - +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import org.graalvm.compiler.api.test.Graal; @@ -38,6 +38,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -83,6 +84,7 @@ public class InvokeGraal { protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) { /* Create a unique compilation identifier, visible in IGV. */ CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); + OptionValues options = getInitialOptions(); try (Scope s = Debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { /* @@ -91,7 +93,7 @@ public class InvokeGraal { * that we want the compilation to make optimistic assumptions about runtime state such * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(method).compilationId(compilationId).build(); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If @@ -103,12 +105,12 @@ public class InvokeGraal { * The optimization phases that are applied to the graph. This is the main configuration * point for Graal. Add or remove phases to customize your compilation. */ - Suites suites = backend.getSuites().getDefaultSuites(); + Suites suites = backend.getSuites().getDefaultSuites(options); /* * The low-level phases that are applied to the low-level representation. */ - LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(); + LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(options); /* * We want Graal to perform all speculative optimistic optimizations, using the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java index 92898acf01e..0493d6bf290 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test.tutorial; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.util.ArrayDeque; import java.util.Collections; @@ -45,7 +45,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; @@ -241,7 +240,7 @@ public class StaticAnalysis { * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 26541c81573..68390cbb3d6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.core; -import static org.graalvm.compiler.core.GraalCompilerOptions.EmitLIRRepeatCount; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - import java.util.Collection; import java.util.List; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; @@ -41,9 +38,10 @@ import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; -import org.graalvm.compiler.lir.BailoutAndRestartBackendException; import org.graalvm.compiler.lir.LIR; +import org.graalvm.compiler.lir.alloc.OutOfRegistersException; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.framemap.FrameMap; @@ -58,18 +56,16 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.instrumentation.ExtractInstrumentationPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; @@ -93,7 +89,6 @@ public class GraalCompiler { private static final DebugTimer BackEnd = Debug.timer("BackEnd"); private static final DebugTimer EmitLIR = Debug.timer("EmitLIR"); private static final DebugTimer EmitCode = Debug.timer("EmitCode"); - private static final LIRGenerationPhase LIR_GENERATION_PHASE = new LIRGenerationPhase(); /** * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. @@ -172,7 +167,7 @@ public class GraalCompiler { @SuppressWarnings("try") public static T compile(Request r) { try (Scope s = MethodMetricsRootScopeInfo.createRootScopeIfAbsent(r.installedCodeOwner); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod()) { + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { assert !r.graph.isFrozen(); try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start()) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); @@ -194,13 +189,10 @@ public class GraalCompiler { HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); - new DeadCodeEliminationPhase(Optional).apply(graph); + new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); } else { Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state"); } - if (UseGraalInstrumentation.getValue()) { - new ExtractInstrumentationPhase().apply(graph, highTierContext); - } suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); @@ -215,6 +207,8 @@ public class GraalCompiler { Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @@ -222,13 +216,6 @@ public class GraalCompiler { public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) { - // Repeatedly run the LIR code generation pass to improve statistical profiling results. - for (int i = 0; i < EmitLIRRepeatCount.getValue(); i++) { - SchedulePhase dummySchedule = new SchedulePhase(); - dummySchedule.apply(graph); - emitLIR(backend, graph, stub, registerConfig, lirSuites); - } - LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { @@ -240,36 +227,34 @@ public class GraalCompiler { } } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { - OverrideScope overrideScope = null; - LIRSuites lirSuites0 = lirSuites; - while (true) { - try (OverrideScope scope = overrideScope) { - return emitLIR0(backend, graph, stub, registerConfig, lirSuites0); - } catch (BailoutAndRestartBackendException e) { - if (BailoutAndRestartBackendException.Options.LIRUnlockBackendRestart.getValue() && e.shouldRestart()) { - overrideScope = e.getOverrideScope(); - lirSuites0 = e.updateLIRSuites(lirSuites); - if (lirSuites0 != null) { - continue; - } - } - /* - * The BailoutAndRestartBackendException is permanent. If restart fails or is - * disabled we throw the bailout. - */ - throw e; + String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); + String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); + try { + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + } catch (OutOfRegistersException e) { + if (allocationRestrictedTo != null) { + allocationRestrictedTo = null; + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); } + /* If the re-execution fails we convert the exception into a "hard" failure */ + throw new GraalError(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") - private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { + private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, + String[] allocationRestrictedTo) { try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) { + assert !graph.hasValueProxies(); ScheduleResult schedule = graph.getLastSchedule(); Block[] blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); @@ -283,7 +268,7 @@ public class GraalCompiler { codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder); + lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions()); Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order"); } catch (Throwable e) { throw Debug.handle(e); @@ -295,11 +280,11 @@ public class GraalCompiler { // LIR generation LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); - LIR_GENERATION_PHASE.apply(backend.getTarget(), lirGenRes, context); + new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) { Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation"); - LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig)); + LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation"); return result; } catch (Throwable e) { @@ -307,6 +292,8 @@ public class GraalCompiler { } } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @@ -336,7 +323,7 @@ public class GraalCompiler { } @SuppressWarnings("try") - public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, Collection accessedFields, + public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, EconomicSet accessedFields, int bytecodeSize, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { try (DebugCloseable a = EmitCode.start()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java index f8c8a0a30ad..e6bb919bad5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java @@ -23,8 +23,8 @@ package org.graalvm.compiler.core; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; /** * Options related to {@link GraalCompiler}. @@ -32,22 +32,20 @@ import org.graalvm.compiler.options.OptionValue; public class GraalCompilerOptions { // @formatter:off - @Option(help = "Repeatedly run the LIR code generation pass to improve statistical profiling results.", type = OptionType.Debug) - public static final OptionValue EmitLIRRepeatCount = new OptionValue<>(0); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintFilter = new OptionValue<>(null); + public static final OptionKey PrintFilter = new OptionKey<>(null); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintCompilation = new OptionValue<>(false); + public static final OptionKey PrintCompilation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); + public static final OptionKey PrintAfterCompilation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBailout = new OptionValue<>(false); + public static final OptionKey PrintBailout = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnBailout = new OptionValue<>(false); + public static final OptionKey ExitVMOnBailout = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnException = new OptionValue<>(false); + public static final OptionKey ExitVMOnException = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); + public static final OptionKey PrintStackTraceOnException = new OptionKey<>(false); // @formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java index 38cb71febee..3f92a886643 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.DebugInitializationParticipant; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.ServiceProvider; /** @@ -39,52 +40,53 @@ public class GraalDebugInitializationParticipant implements DebugInitializationP @Override public void apply(Params params) { - if (GraalDebugConfig.areDebugScopePatternsEnabled()) { + OptionValues options = params.getOptions(); + if (GraalDebugConfig.areDebugScopePatternsEnabled(options)) { params.enable = true; } - if ("".equals(GraalDebugConfig.Options.Count.getValue())) { + if ("".equals(GraalDebugConfig.Options.Count.getValue(options))) { params.enableUnscopedCounters = true; } - if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue())) { + if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue(options))) { params.enableUnscopedMethodMetrics = true; // mm requires full debugging support params.enable = true; } - if ("".equals(GraalDebugConfig.Options.Time.getValue())) { + if ("".equals(GraalDebugConfig.Options.Time.getValue(options))) { params.enableUnscopedTimers = true; } - if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue())) { + if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue(options))) { params.enableUnscopedMemUseTrackers = true; } // unscoped counters/timers/mem use trackers/method metrics should respect method filter // semantics if (!params.enable && (params.enableUnscopedMemUseTrackers || params.enableUnscopedMethodMetrics || params.enableUnscopedCounters || params.enableUnscopedTimers) && - GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter)) { + GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter, options)) { params.enable = true; params.enableMethodFilter = true; } - if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue() != null) { + if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue(options) != null) { // mm requires full debugging support params.enable = true; } - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { if (!params.enable) { TTY.println("WARNING: MethodMeter is disabled but GlobalMetricsInterceptedByMethodMetrics is enabled. Ignoring MethodMeter and GlobalMetricsInterceptedByMethodMetrics."); } else { - parseMethodMetricsDebugValueInterception(params); + parseMethodMetricsDebugValueInterception(params, options); } } - if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter) || params.enableUnscopedMethodMetrics) { - if (!MethodMetricsPrinter.methodMetricsDumpingEnabled()) { + if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter, options) || params.enableUnscopedMethodMetrics) { + if (!MethodMetricsPrinter.methodMetricsDumpingEnabled(options)) { TTY.println("WARNING: MethodMeter is enabled but MethodMeter dumping is disabled. Output will not contain MethodMetrics."); } } } - private static void parseMethodMetricsDebugValueInterception(Params params) { - String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(); + private static void parseMethodMetricsDebugValueInterception(Params params, OptionValues options) { + String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(options); boolean intercepted = false; if (interceptionGroup.contains("Timers")) { params.interceptTime = true; @@ -101,7 +103,6 @@ public class GraalDebugInitializationParticipant implements DebugInitializationP if (!intercepted) { TTY.println("WARNING: Ignoring GlobalMetricsInterceptedByMethodMetrics as the supplied argument does not contain Timers/Counters/MemUseTrackers."); - GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.setValue(null); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java index 4449ecc3e7d..fea9c328d2a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java @@ -24,13 +24,11 @@ package org.graalvm.compiler.core.gen; import java.util.ArrayDeque; import java.util.Arrays; -import java.util.Map; import java.util.Queue; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LabelRef; @@ -44,9 +42,12 @@ import org.graalvm.compiler.nodes.virtual.EscapeObjectState; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.MaterializedObjectState; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.VirtualObject; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.JavaValue; @@ -68,8 +69,8 @@ public class DebugInfoBuilder { private static final JavaValue[] NO_JAVA_VALUES = {}; private static final JavaKind[] NO_JAVA_KINDS = {}; - protected final Map virtualObjects = Node.newMap(); - protected final Map objectStates = Node.newIdentityMap(); + protected final EconomicMap virtualObjects = EconomicMap.create(Equivalence.IDENTITY); + protected final EconomicMap objectStates = EconomicMap.create(Equivalence.IDENTITY); protected final Queue pendingVirtualObjects = new ArrayDeque<>(); @@ -118,8 +119,13 @@ public class DebugInfoBuilder { assert currentField != null; int pos = 0; for (int i = 0; i < entryCount; i++) { - if (!currentField.values().get(i).isConstant() || currentField.values().get(i).asJavaConstant().getJavaKind() != JavaKind.Illegal) { - ValueNode value = currentField.values().get(i); + ValueNode value = currentField.values().get(i); + if (value == null) { + JavaKind entryKind = vobjNode.entryKind(i); + values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind()); + slotKinds[pos] = entryKind.getStackKind(); + pos++; + } else if (!value.isConstant() || value.asJavaConstant().getJavaKind() != JavaKind.Illegal) { values[pos] = toJavaValue(value); slotKinds[pos] = toSlotKind(value); pos++; @@ -137,7 +143,11 @@ public class DebugInfoBuilder { vobjValue.setValues(values, slotKinds); } - virtualObjectsArray = virtualObjects.values().toArray(new VirtualObject[virtualObjects.size()]); + virtualObjectsArray = new VirtualObject[virtualObjects.size()]; + int index = 0; + for (VirtualObject value : virtualObjects.getValues()) { + virtualObjectsArray[index++] = value; + } virtualObjects.clear(); } objectStates.clear(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index 2c70da10cb2..7443e3b7bbe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -22,25 +22,23 @@ */ package org.graalvm.compiler.core.gen; -import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; -import static org.graalvm.compiler.lir.LIR.verifyBlock; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.lir.LIR.verifyBlock; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.match.ComplexMatchValue; +import org.graalvm.compiler.core.match.MatchPattern; import org.graalvm.compiler.core.match.MatchRuleRegistry; import org.graalvm.compiler.core.match.MatchStatement; import org.graalvm.compiler.debug.Debug; @@ -99,6 +97,9 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.NodeValueMap; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -117,6 +118,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private final NodeMap nodeOperands; private final DebugInfoBuilder debugInfoBuilder; + private final int traceLIRGeneratorLevel; protected final LIRGenerator gen; @@ -124,16 +126,18 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private ValueNode lastInstructionPrinted; // Debugging only private final NodeMatchRules nodeMatchRules; - private Map, List> matchRules; + private EconomicMap, List> matchRules; public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { this.gen = (LIRGenerator) gen; this.nodeMatchRules = nodeMatchRules; this.nodeOperands = graph.createNodeMap(); this.debugInfoBuilder = createDebugInfoBuilder(graph, this); - if (MatchExpressions.getValue()) { - matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass()); + OptionValues options = graph.getOptions(); + if (MatchExpressions.getValue(options)) { + matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options); } + traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); assert nodeMatchRules.lirBuilder == null; nodeMatchRules.lirBuilder = this; @@ -177,9 +181,10 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override public ValueNode valueForOperand(Value value) { assert nodeOperands != null; - for (Entry entry : nodeOperands.entries()) { - if (entry.getValue().equals(value)) { - return (ValueNode) entry.getKey(); + UnmodifiableMapCursor cursor = nodeOperands.getEntries(); + while (cursor.advance()) { + if (cursor.getValue().equals(value)) { + return (ValueNode) cursor.getKey(); } } return null; @@ -206,7 +211,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio */ public void setMatchResult(Node x, Value operand) { assert operand.equals(ComplexMatchValue.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; - assert operand instanceof ComplexMatchValue || x.getUsageCount() == 1 : "interior matches must be single user"; + assert operand instanceof ComplexMatchValue || MatchPattern.isSingleValueUser(x) : "interior matches must be single user"; assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); @@ -227,7 +232,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } public final void append(LIRInstruction op) { - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(nodeOperands.graph().getOptions()) && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; InstructionPrinter ip = new InstructionPrinter(TTY.out()); @@ -318,6 +323,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override @SuppressWarnings("try") public void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap) { + + OptionValues options = graph.getOptions(); try (BlockScope blockScope = gen.getBlockScope(block)) { setSourcePosition(null); @@ -332,7 +339,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio AbstractMergeNode merge = (AbstractMergeNode) begin; LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0); label.setPhiValues(createPhiIn(merge)); - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) { TTY.println("Created PhiIn: " + label); } @@ -345,11 +352,12 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio // of instructions matchComplexExpressions(nodes); + boolean trace = traceLIRGeneratorLevel >= 3; for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; - if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { + if (trace) { TTY.println("LIRGen for " + valueNode); } Value operand = getOperand(valueNode); @@ -401,7 +409,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio protected void matchComplexExpressions(List nodes) { if (matchRules != null) { try (Scope s = Debug.scope("MatchComplexExpressions")) { - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { int i = 0; for (Node node : nodes) { Debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); @@ -432,7 +440,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio protected abstract boolean peephole(ValueNode valueNode); private void doRoot(ValueNode instr) { - if (Options.TraceLIRGeneratorLevel.getValue() >= 2) { + if (traceLIRGeneratorLevel >= 2) { TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java index 280b67041dc..2e281b6cdfe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java @@ -56,6 +56,8 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; @@ -87,6 +89,8 @@ import org.graalvm.compiler.nodes.memory.WriteNode; @MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = PiNode.class, inputs = {"object"}) +@MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) +@MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) public abstract class NodeMatchRules { NodeLIRBuilder lirBuilder; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index 9abe43aefff..6d0a36e373a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -26,9 +26,7 @@ import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; @@ -37,6 +35,8 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; /** * Container for state captured during a match. @@ -49,7 +49,7 @@ public class MatchContext { private final MatchStatement rule; - private Map namedNodes; + private EconomicMap namedNodes; private ArrayList consumed; @@ -85,7 +85,7 @@ public class MatchContext { public Result captureNamedValue(String name, Class type, Node value) { if (namedNodes == null) { - namedNodes = new HashMap<>(2); + namedNodes = EconomicMap.create(Equivalence.DEFAULT); } NamedNode current = namedNodes.get(name); if (current == null) { @@ -109,7 +109,7 @@ public class MatchContext { // don't interfere with this match. continue; } else if ((consumed == null || !consumed.contains(node)) && node != root) { - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(root.getOptions())) { Debug.log("unexpected node %s", node); for (int j = startIndex; j <= endIndex; j++) { Node theNode = nodes.get(j); @@ -151,7 +151,7 @@ public class MatchContext { * @return Result.OK if the node can be safely consumed. */ public Result consume(Node node) { - assert node.getUsageCount() <= 1 : "should have already been checked"; + assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; // Check NOT_IN_BLOCK first since that usually implies ALREADY_USED int index = nodes.indexOf(node); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java index 171c2dbfc34..e3c60e37851 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java @@ -26,6 +26,7 @@ import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; /** @@ -252,7 +253,7 @@ public class MatchPattern { } if (singleUser && !atRoot) { - if (node.getUsageCount() > 1) { + if (!isSingleValueUser(node)) { return Result.tooManyUsers(node, statement.getPattern()); } } @@ -267,6 +268,31 @@ public class MatchPattern { return result; } + public static boolean isSingleValueUser(Node node) { + int valueUsage = node.getUsageCount(); + if (valueUsage == 1) { + return true; + } + if (node.isAllowedUsageType(InputType.Guard)) { + // See if the other usages are non-Value usages. + valueUsage = 0; + for (Node usage : node.usages()) { + for (Position input : usage.inputPositions()) { + if (input.getInputType() == InputType.Value && input.get(usage) == node) { + valueUsage++; + if (valueUsage > 1) { + // Too many value users + return false; + } + } + } + } + assert valueUsage == 1; + return true; + } + return false; + } + /** * For a node starting at root, produce a String showing the inputs that matched against this * rule. It's assumed that a match has already succeeded against this rule, otherwise the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java index bab5c593b20..e595df33510 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java @@ -23,12 +23,8 @@ package org.graalvm.compiler.core.match; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.debug.Debug; @@ -38,7 +34,11 @@ import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; public class MatchRuleRegistry { @@ -67,30 +67,32 @@ public class MatchRuleRegistry { return result; } - private static final HashMap, Map, List>> registry = new HashMap<>(); + private static final EconomicMap, EconomicMap, List>> registry = EconomicMap.create(Equivalence.IDENTITY); /** * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass. * * @param theClass + * @param options * @return the set of {@link MatchStatement}s applicable to theClass. */ @SuppressWarnings("try") - public static synchronized Map, List> lookup(Class theClass) { - Map, List> result = registry.get(theClass); + public static synchronized EconomicMap, List> lookup(Class theClass, OptionValues options) { + EconomicMap, List> result = registry.get(theClass); if (result == null) { - Map, List> rules = createRules(theClass); + EconomicMap, List> rules = createRules(theClass); registry.put(theClass, rules); assert registry.get(theClass) == rules; result = rules; - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(options)) { try (Scope s = Debug.scope("MatchComplexExpressions")) { Debug.log("Match rules for %s", theClass.getSimpleName()); - for (Entry, List> entry : result.entrySet()) { - Debug.log(" For node class: %s", entry.getKey()); - for (MatchStatement statement : entry.getValue()) { + MapCursor, List> cursor = result.getEntries(); + while (cursor.advance()) { + Debug.log(" For node class: %s", cursor.getKey()); + for (MatchStatement statement : cursor.getValue()) { Debug.log(" %s", statement.getPattern()); } } @@ -108,8 +110,9 @@ public class MatchRuleRegistry { * This is a separate, public method so that external clients can create rules with a custom * lookup and without the default caching behavior. */ - public static Map, List> createRules(Class theClass) { - HashMap, MatchStatementSet> matchSets = new HashMap<>(); + @SuppressWarnings("unchecked") + public static EconomicMap, List> createRules(Class theClass) { + EconomicMap, MatchStatementSet> matchSets = EconomicMap.create(Equivalence.IDENTITY); Iterable sl = GraalServices.load(MatchStatementSet.class); for (MatchStatementSet rules : sl) { matchSets.put(rules.forClass(), rules); @@ -117,8 +120,8 @@ public class MatchRuleRegistry { // Walk the class hierarchy collecting lists and merge them together. The subclass // rules are first which gives them preference over earlier rules. - Map, List> rules = new HashMap<>(); - Class currentClass = theClass; + EconomicMap, List> rules = EconomicMap.create(Equivalence.IDENTITY); + Class currentClass = theClass; do { MatchStatementSet matchSet = matchSets.get(currentClass); if (matchSet != null) { @@ -133,7 +136,7 @@ public class MatchRuleRegistry { current.add(statement); } } - currentClass = currentClass.getSuperclass(); + currentClass = (Class) currentClass.getSuperclass(); } while (currentClass != NodeMatchRules.class); return rules; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java index 7d4fbb0ae8c..80398efe8c4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java @@ -103,12 +103,12 @@ public class MatchStatement { } // The pattern matched but some other code generation constraint disallowed code // generation for the pattern. - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(node.getOptions())) { Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); Debug.log("with nodes %s", formatMatch(node)); } } else { - if (LogVerbose.getValue() && result.code != MatchResultCode.WRONG_CLASS) { + if (LogVerbose.getValue(node.getOptions()) && result.code != MatchResultCode.WRONG_CLASS) { Debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java index c2ff09dff27..d714edea6a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAlloc import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,33 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class CoreCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new HighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new HighTier(options); } @Override - public PhaseSuite createMidTier() { - return new MidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new MidTier(options); } @Override - public PhaseSuite createLowTier() { - return new LowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new LowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { - return new PreAllocationOptimizationStage(); + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { + return new PreAllocationOptimizationStage(options); } @Override - public LIRPhaseSuite createAllocationStage() { - return new AllocationStage(); + public LIRPhaseSuite createAllocationStage(OptionValues options) { + return new AllocationStage(options); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { - return new PostAllocationOptimizationStage(); + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { + return new PostAllocationOptimizationStage(options); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java index 307a59b3049..c7736b37223 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.EconomyPreAllocationOptimizationStage; import org.graalvm.compiler.lir.phases.LIRPhaseSuite; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,32 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new EconomyHighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new EconomyHighTier(options); } @Override - public PhaseSuite createMidTier() { - return new EconomyMidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new EconomyMidTier(options); } @Override - public PhaseSuite createLowTier() { - return new EconomyLowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new EconomyLowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { return new EconomyPreAllocationOptimizationStage(); } @Override - public LIRPhaseSuite createAllocationStage() { + public LIRPhaseSuite createAllocationStage(OptionValues options) { return new EconomyAllocationStage(); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { return new EconomyPostAllocationOptimizationStage(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java index 76efa541752..fb4b35c5bef 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -32,9 +33,9 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; public class EconomyHighTier extends PhaseSuite { - public EconomyHighTier() { + public EconomyHighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java index db1b0f11018..3950f8ead8a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -34,9 +35,9 @@ import org.graalvm.compiler.phases.tiers.LowTierContext; public class EconomyLowTier extends PhaseSuite { - public EconomyLowTier() { + public EconomyLowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java index c6350bc2ffd..504bed773bc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; @@ -36,9 +37,9 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyMidTier extends PhaseSuite { - public EconomyMidTier() { + public EconomyMidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(new RemoveValueProxyPhase()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java index bb7236d6ced..aa06d1ff6dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.phases; -import java.util.Set; -import java.util.stream.Collectors; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.graph.Graph.NodeEvent; @@ -36,6 +33,8 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicSet; /** * A utility phase for detecting when a phase would change the graph and reporting extra information @@ -77,11 +76,17 @@ public class GraphChangeMonitoringPhase extends PhaseSui Debug.handle(t); } } - /* - * Ignore LogicConstantNode since those are sometimes created and deleted as part of running - * a phase. - */ - if (listener.getNodes().stream().filter(e -> !(e instanceof LogicConstantNode)).findFirst().isPresent()) { + + EconomicSet filteredNodes = EconomicSet.create(Equivalence.IDENTITY); + for (Node n : listener.getNodes()) { + if (n instanceof LogicConstantNode) { + // Ignore LogicConstantNode since those are sometimes created and deleted as part of + // running a phase. + } else { + filteredNodes.add(n); + } + } + if (!filteredNodes.isEmpty()) { /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { @@ -90,11 +95,10 @@ public class GraphChangeMonitoringPhase extends PhaseSui Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName()); } super.run(graph, context); - Set collect = listener.getNodes().stream().filter(e -> !e.isAlive()).filter(e -> !(e instanceof LogicConstantNode)).collect(Collectors.toSet()); if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), collect); + Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); } - Debug.log("*** %s %s %s\n", message, graph, collect); + Debug.log("*** %s %s %s\n", message, graph, filteredNodes); } } } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java index 675c1dd9d30..358d6cb0b4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java @@ -29,8 +29,8 @@ import static org.graalvm.compiler.core.common.GraalOptions.LoopPeeling; import static org.graalvm.compiler.core.common.GraalOptions.LoopUnswitch; import static org.graalvm.compiler.core.common.GraalOptions.OptConvertDeoptsToGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; +import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.PartialEscapeAnalysis; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import org.graalvm.compiler.loop.DefaultLoopPolicies; @@ -40,8 +40,9 @@ import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; @@ -51,8 +52,8 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; -import org.graalvm.compiler.phases.common.instrumentation.HighTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class HighTier extends PhaseSuite { @@ -61,57 +62,58 @@ public class HighTier extends PhaseSuite { // @formatter:off @Option(help = "Enable inlining", type = OptionType.Expert) - public static final OptionValue Inline = new OptionValue<>(true); + public static final OptionKey Inline = new OptionKey<>(true); // @formatter:on } - public HighTier() { + public HighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(canonicalizer); - if (Options.Inline.getValue()) { + if (Options.Inline.getValue(options)) { appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase(Optional)); - - if (ConditionalElimination.getValue()) { - appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - } } - if (OptConvertDeoptsToGuards.getValue()) { + if (OptConvertDeoptsToGuards.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new ConvertDeoptimizeToGuardPhase())); } + if (ConditionalElimination.getValue(options)) { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); + } + LoopPolicies loopPolicies = createLoopPolicies(); - if (FullUnroll.getValue()) { + if (FullUnroll.getValue(options)) { appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies)); } - if (OptLoopTransform.getValue()) { - if (LoopPeeling.getValue()) { + if (OptLoopTransform.getValue(options)) { + if (LoopPeeling.getValue(options)) { appendPhase(new LoopPeelingPhase(loopPolicies)); } - if (LoopUnswitch.getValue()) { + if (LoopUnswitch.getValue(options)) { appendPhase(new LoopUnswitchingPhase(loopPolicies)); } } appendPhase(canonicalizer); - if (PartialEscapeAnalysis.getValue()) { - appendPhase(new PartialEscapePhase(true, canonicalizer)); + if (PartialEscapeAnalysis.getValue(options)) { + appendPhase(new PartialEscapePhase(true, canonicalizer, options)); } + + if (OptReadElimination.getValue(options)) { + appendPhase(new EarlyReadEliminationPhase(canonicalizer)); + } + appendPhase(new RemoveValueProxyPhase()); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new HighTierReconcileInstrumentationPhase()); - } } public LoopPolicies createLoopPolicies() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java index 57c72bc63be..8ba0d99d1fd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java @@ -22,26 +22,26 @@ */ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; +import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; -import org.graalvm.compiler.phases.common.instrumentation.InlineInstrumentationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.LowTierContext; public class LowTier extends PhaseSuite { @@ -50,41 +50,38 @@ public class LowTier extends PhaseSuite { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final OptionValue ProfileCompiledMethods = new OptionValue<>(false); + public static final OptionKey ProfileCompiledMethods = new OptionKey<>(false); // @formatter:on } - public LowTier() { + public LowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + CanonicalizerPhase canonicalizerWithoutGVN = new CanonicalizerPhase(); + canonicalizerWithoutGVN.disableGVN(); + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); + canonicalizerWithoutGVN.disableReadCanonicalization(); } - if (Options.ProfileCompiledMethods.getValue()) { + if (Options.ProfileCompiledMethods.getValue(options)) { appendPhase(new ProfileCompiledMethodsPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new InlineInstrumentationPhase()); - } - - appendPhase(new RemoveValueProxyPhase()); appendPhase(new ExpandLogicPhase()); - /* Cleanup IsNull checks resulting from MID_TIER/LOW_TIER lowering and ExpandLogic phase. */ - if (ConditionalElimination.getValue()) { - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - /* Canonicalizer may create some new ShortCircuitOrNodes so clean them up. */ - appendPhase(new ExpandLogicPhase()); - } + appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS))); + + appendPhase(canonicalizerWithoutGVN); appendPhase(new UseTrappingNullChecksPhase()); appendPhase(new DeadCodeEliminationPhase(Required)); + appendPhase(new PropagateDeoptimizeProbabilityPhase()); + appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java index dc79e143ae1..2c02e865a00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java @@ -25,17 +25,14 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping; -import static org.graalvm.compiler.core.common.GraalOptions.OptEliminatePartiallyRedundantGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptFloatingReads; -import static org.graalvm.compiler.core.common.GraalOptions.OptPushThroughPi; -import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn; import org.graalvm.compiler.loop.phases.LoopSafepointEliminationPhase; import org.graalvm.compiler.loop.phases.ReassociateInvariantPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeoptimizationGroupingPhase; @@ -47,79 +44,46 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.VerifyHeapAtReturnPhase; -import org.graalvm.compiler.phases.common.instrumentation.MidTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; public class MidTier extends PhaseSuite { - public MidTier() { + public MidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } - if (OptPushThroughPi.getValue()) { - appendPhase(new PushThroughPiPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new ValueAnchorCleanupPhase()); appendPhase(new LockEliminationPhase()); - if (OptReadElimination.getValue()) { - appendPhase(new EarlyReadEliminationPhase(canonicalizer)); - } - - if (OptFloatingReads.getValue()) { + if (OptFloatingReads.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); } - appendPhase(new RemoveValueProxyPhase()); - appendPhase(canonicalizer); - - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - if (ConditionalElimination.getValue()) { + if (ConditionalElimination.getValue(options)) { appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, true)); } - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopSafepointEliminationPhase())); + appendPhase(new LoopSafepointEliminationPhase()); appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase())); + appendPhase(new GuardLoweringPhase()); - if (VerifyHeapAtReturn.getValue()) { + if (VerifyHeapAtReturn.getValue(options)) { appendPhase(new VerifyHeapAtReturnPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new MidTierReconcileInstrumentationPhase()); - } appendPhase(new FrameStateAssignmentPhase()); - if (ReassociateInvariants.getValue()) { + if (ReassociateInvariants.getValue(options)) { appendPhase(new ReassociateInvariantPhase()); } - if (OptDeoptimizationGrouping.getValue()) { + if (OptDeoptimizationGrouping.getValue(options)) { appendPhase(new DeoptimizationGroupingPhase()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 53214afb9d3..59861f99f4d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.target; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -45,6 +43,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; @@ -113,7 +112,13 @@ public abstract class Backend implements TargetProvider, ValueKindFactory translateToCallerRegisters(Set calleeRegisters); + public abstract EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters); /** * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java index 42b4eee5887..e767318a625 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java @@ -23,21 +23,20 @@ package org.graalvm.compiler.debug.test; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import java.lang.management.ThreadMXBean; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugConfig; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.DebugTimer; import org.graalvm.compiler.debug.Management; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; @SuppressWarnings("try") public class DebugTimerTest { @@ -66,35 +65,14 @@ public class DebugTimerTest { } while (true); } - @Test - public void test1() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - - DebugTimer timerA = Debug.timer("TimerA"); - DebugTimer timerB = Debug.timer("TimerB"); - - long spinA; - long spinB; - - try (DebugCloseable a1 = timerA.start()) { - spinA = spin(50); - try (DebugCloseable b1 = timerB.start()) { - spinB = spin(50); - } - } - - Assert.assertTrue(timerB.getCurrentValue() < timerA.getCurrentValue()); - if (timerA.getFlat() != null && timerB.getFlat() != null) { - assertTrue(spinB >= spinA || timerB.getFlat().getCurrentValue() < timerA.getFlat().getCurrentValue()); - assertEquals(timerA.getFlat().getCurrentValue(), timerA.getCurrentValue() - timerB.getFlat().getCurrentValue(), 10D); - } - } - } - + /** + * Asserts that a timer replied recursively without any other interleaving timers has the same + * flat and accumulated times. + */ @Test public void test2() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); + OptionValues options = new OptionValues(EconomicMap.create()); + DebugConfig debugConfig = Debug.fixedConfig(options, 0, 0, false, false, true, false, false, null, null, System.out); try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { DebugTimer timerC = Debug.timer("TimerC"); try (DebugCloseable c1 = timerC.start()) { @@ -117,36 +95,4 @@ public class DebugTimerTest { } } } - - @Test - public void test3() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - - DebugTimer timerD = Debug.timer("TimerD"); - DebugTimer timerE = Debug.timer("TimerE"); - - long spinD1; - long spinE; - - try (DebugCloseable d1 = timerD.start()) { - spinD1 = spin(50); - try (DebugCloseable e1 = timerE.start()) { - spinE = spin(50); - try (DebugCloseable d2 = timerD.start()) { - spin(50); - try (DebugCloseable d3 = timerD.start()) { - spin(50); - } - } - } - } - - Assert.assertTrue(timerE.getCurrentValue() < timerD.getCurrentValue()); - if (timerD.getFlat() != null && timerE.getFlat() != null) { - assertTrue(spinE >= spinD1 || timerE.getFlat().getCurrentValue() < timerD.getFlat().getCurrentValue()); - assertEquals(timerD.getFlat().getCurrentValue(), timerD.getCurrentValue() - timerE.getFlat().getCurrentValue(), 10D); - } - } - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java new file mode 100644 index 00000000000..ff12a8a64f8 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +/** + * Utility for query whether assertions are enabled. + */ +public class Assertions { + /** + * Determines if assertions are enabled. Strictly speaking, this may only be true for the + * {@link Assertions} class but we assume assertions are enabled/disabled for Graal as a whole. + */ + public static final boolean ENABLED = assertionsEnabled(); + + private static boolean assertionsEnabled() { + boolean enabled = false; + assert (enabled = true) == true; + return enabled; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java index cd5e7fca7ae..19a47784b0a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.debug; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; import static java.util.FormattableFlags.LEFT_JUSTIFY; import static java.util.FormattableFlags.UPPERCASE; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; import java.io.PrintStream; import java.util.ArrayList; @@ -47,6 +47,8 @@ import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; import org.graalvm.compiler.debug.internal.TimerImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionValuesAccess; import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -63,7 +65,12 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class Debug { - private static final Params params = new Params(); + /** + * The option values available in this package. + */ + static final OptionValues DEBUG_OPTIONS = GraalServices.loadSingle(OptionValuesAccess.class, true).getOptions(); + + static final Params params = new Params(); static { // Load the service providers that may want to modify any of the @@ -76,7 +83,7 @@ public class Debug { /** * The parameters for configuring the initialization of {@link Debug} class. */ - public static class Params { + public static final class Params { public boolean enable; public boolean enableMethodFilter; public boolean enableUnscopedTimers; @@ -86,13 +93,16 @@ public class Debug { public boolean interceptCount; public boolean interceptTime; public boolean interceptMem; + + @SuppressWarnings("static-method") + public OptionValues getOptions() { + return DEBUG_OPTIONS; + } } @SuppressWarnings("all") private static boolean initialize() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(); + return Assertions.ENABLED || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(DEBUG_OPTIONS); } private static final boolean ENABLED = initialize(); @@ -1239,14 +1249,21 @@ public class Debug { } public static DebugConfig silentConfig() { - return fixedConfig(0, 0, false, false, false, false, false, Collections. emptyList(), Collections. emptyList(), null); + return fixedConfig(new OptionValues(OptionValues.newOptionMap()), 0, 0, false, false, false, false, false, Collections. emptyList(), + Collections. emptyList(), null); } - public static DebugConfig fixedConfig(final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled, + public static DebugConfig fixedConfig(OptionValues options, final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, + final boolean isTimerEnabled, final boolean isVerifyEnabled, final boolean isMMEnabled, final Collection dumpHandlers, final Collection verifyHandlers, final PrintStream output) { return new DebugConfig() { + @Override + public OptionValues getOptions() { + return options; + } + @Override public int getLogLevel() { return logLevel; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java index 66b5c32311f..4bac721621e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java @@ -25,8 +25,15 @@ package org.graalvm.compiler.debug; import java.io.PrintStream; import java.util.Collection; +import org.graalvm.compiler.options.OptionValues; + public interface DebugConfig { + /** + * Returns the option values that can be used to configure details of debug clients. + */ + OptionValues getOptions(); + /** * Determines the current log level in the {@linkplain Debug#currentScope() current debug scope} * . diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java index 5b0f8518058..fcbebdbe8ac 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java @@ -23,14 +23,5 @@ package org.graalvm.compiler.debug; public interface DebugConfigCustomizer { - void customize(DebugConfig config, Object... extraArgs); - - static T lookupArg(Class c, Object... extraArgs) { - for (Object arg : extraArgs) { - if (c.isInstance(arg)) { - return c.cast(arg); - } - } - return null; - } + void customize(DebugConfig config); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java index 3b52c31215b..42ba3df9346 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java @@ -28,6 +28,14 @@ public interface DebugDumpHandler extends Closeable { void dump(Object object, String message); + /** + * Add arbitrary capability for use by the handler. + * + * @param capability + */ + default void addCapability(Object capability) { + } + /** * Flushes and releases resources managed by this dump handler. A subsequent call to * {@link #dump(Object, String)} will create and open new resources. That is, this method can be diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java index 9a15e241822..bafe577e431 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java @@ -22,43 +22,84 @@ */ package org.graalvm.compiler.debug; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Time; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.TrackMemUse; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; -import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.runtime.JVMCI; public class DebugEnvironment { - public static GraalDebugConfig initialize(PrintStream log, Object... extraArgs) { - // Initialize JVMCI before loading class Debug - JVMCI.initialize(); + /** + * Create a GraalDebugConfig if {@link Debug#isEnabled()} is true and one hasn't already been + * created. Additionally add {@code extraArgs} as capabilities to the {@link DebugDumpHandler}s + * associated with the current config. Capabilities can be added at any time. + * + * @return the current {@link GraalDebugConfig} or null if nothing was done + */ + public static GraalDebugConfig ensureInitialized(OptionValues options, Object... capabilities) { + return ensureInitializedHelper(options, false, capabilities); + } + + /** + * Create a new GraalDebugConfig if {@link Debug#isEnabled()} is true, even if one had already + * been created. Additionally add {@code extraArgs} as capabilities to the + * {@link DebugDumpHandler}s associated with the current config. Capabilities can be added at + * any time. + * + * @return the current {@link GraalDebugConfig} or null if nothing was done + */ + public static GraalDebugConfig forceInitialization(OptionValues options, Object... capabilities) { + return ensureInitializedHelper(options, true, capabilities); + } + + private static GraalDebugConfig ensureInitializedHelper(OptionValues options, boolean forceInit, Object... capabilities) { if (!Debug.isEnabled()) { - log.println("WARNING: Scope debugging needs to be enabled with -esa"); return null; } - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Count.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), Verify.getValue(), MethodFilter.getValue(), - MethodMeter.getValue(), - log, dumpHandlers, verifyHandlers); + GraalDebugConfig debugConfig = (GraalDebugConfig) DebugScope.getConfig(); + if (debugConfig == null || forceInit) { + // Initialize JVMCI before loading class Debug + JVMCI.initialize(); + List dumpHandlers = new ArrayList<>(); + List verifyHandlers = new ArrayList<>(); + debugConfig = new GraalDebugConfig( + options, + Log.getValue(options), + Count.getValue(options), + TrackMemUse.getValue(options), + Time.getValue(options), + Dump.getValue(options), + Verify.getValue(options), + MethodFilter.getValue(options), + MethodMeter.getValue(options), + TTY.out, dumpHandlers, verifyHandlers); - for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { - customizer.customize(debugConfig, extraArgs); + for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { + customizer.customize(debugConfig); + } + + Debug.setConfig(debugConfig); + } + if (capabilities != null) { + for (Object o : capabilities) { + for (DebugDumpHandler handler : debugConfig.dumpHandlers()) { + handler.addCapability(o); + } + } } - - Debug.setConfig(debugConfig); return debugConfig; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java index ac336ae9ba7..4c08b6d2ff1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java @@ -28,6 +28,7 @@ import java.util.EnumMap; import java.util.Map; import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.options.OptionValues; public class DelegatingDebugConfig implements DebugConfig { @@ -131,6 +132,11 @@ public class DelegatingDebugConfig implements DebugConfig { return this; } + @Override + public OptionValues getOptions() { + return delegate.getOptions(); + } + @Override public int getLogLevel() { Integer ls = levelState.get(Level.LOG); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java index 367d0ddfb04..69126c95ac8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.debug; +import static org.graalvm.compiler.debug.Debug.DEBUG_OPTIONS; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,7 +31,7 @@ import java.util.List; import java.util.stream.Collectors; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Facility for fingerprinting execution. @@ -38,19 +40,19 @@ public class Fingerprint implements AutoCloseable { public static class Options { @Option(help = "Enables execution fingerprinting.")// - public static final OptionValue UseFingerprinting = new OptionValue<>(false); + public static final OptionKey UseFingerprinting = new OptionKey<>(false); @Option(help = "Limit number of events shown in fingerprinting error message.")// - public static final OptionValue FingerprintErrorEventTailLength = new OptionValue<>(50); + public static final OptionKey FingerprintErrorEventTailLength = new OptionKey<>(50); @Option(help = "Fingerprinting event at which to execute breakpointable code.")// - public static final OptionValue FingerprintingBreakpointEvent = new OptionValue<>(-1); + public static final OptionKey FingerprintingBreakpointEvent = new OptionKey<>(-1); } /** * Determines whether fingerprinting is enabled. */ - public static final boolean ENABLED = Options.UseFingerprinting.getValue(); + public static final boolean ENABLED = Options.UseFingerprinting.getValue(DEBUG_OPTIONS); private static final ThreadLocal current = ENABLED ? new ThreadLocal<>() : null; @@ -112,7 +114,7 @@ public class Fingerprint implements AutoCloseable { } } - private static final int BREAKPOINT_EVENT = Options.FingerprintingBreakpointEvent.getValue(); + private static final int BREAKPOINT_EVENT = Options.FingerprintingBreakpointEvent.getValue(DEBUG_OPTIONS); /** * Submits an execution event for the purpose of recording or verifying a fingerprint. This must @@ -136,7 +138,7 @@ public class Fingerprint implements AutoCloseable { return index == -1 ? events.size() : index; } - private static final int MAX_EVENT_TAIL_IN_ERROR_MESSAGE = Options.FingerprintErrorEventTailLength.getValue(); + private static final int MAX_EVENT_TAIL_IN_ERROR_MESSAGE = Options.FingerprintErrorEventTailLength.getValue(DEBUG_OPTIONS); private String tail() { int start = Math.max(index - MAX_EVENT_TAIL_IN_ERROR_MESSAGE, 0); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java index 69c6e466aab..efe371a6a42 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java @@ -32,119 +32,113 @@ import java.util.Map; import java.util.Set; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.JavaMethod; public class GraalDebugConfig implements DebugConfig { - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } public static class Options { // @formatter:off @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) - public static final OptionValue Dump = new OptionValue<>(null); + public static final OptionKey Dump = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all counters unconditionally.", type = OptionType.Debug) - public static final OptionValue Count = new OptionValue<>(null); + public static final OptionKey Count = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) - public static final OptionValue Verify = new OptionValue() { - @Override - protected String defaultValue() { - return assertionsEnabled() ? "" : null; - } - }; + public static final OptionKey Verify = new OptionKey<>(Assertions.ENABLED ? "" : null); @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) - public static final OptionValue TrackMemUse = new OptionValue<>(null); + public static final OptionKey TrackMemUse = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + "An empty value enables all timers unconditionally.", type = OptionType.Debug) - public static final OptionValue Time = new OptionValue<>(null); + public static final OptionKey Time = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) - public static final OptionValue Log = new OptionValue<>(null); + public static final OptionKey Log = new OptionKey<>(null); @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) - public static final OptionValue MethodFilter = new OptionValue<>(null); + public static final OptionKey MethodFilter = new OptionKey<>(null); @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) - public static final OptionValue MethodFilterRootOnly = new OptionValue<>(false); + public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); @Option(help = "How to print counters and timing values:%n" + "Name - aggregate by unqualified name%n" + "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + "Complete - aggregate by qualified name%n" + "Thread - aggregate by qualified name and thread", type = OptionType.Debug) - public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); + public static final OptionKey DebugValueSummary = new OptionKey<>("Name"); @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionValue DebugValueHumanReadable = new OptionValue<>(true); + public static final OptionKey DebugValueHumanReadable = new OptionKey<>(true); @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(true); + public static final OptionKey SuppressZeroDebugValues = new OptionKey<>(true); @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) - public static final OptionValue DebugValueThreadFilter = new OptionValue<>(null); + public static final OptionKey DebugValueThreadFilter = new OptionKey<>(null); @Option(help = "Write debug values into a file instead of the terminal. " + "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) - public static final OptionValue DebugValueFile = new OptionValue<>(null); + public static final OptionKey DebugValueFile = new OptionKey<>(null); @Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug) - public static final OptionValue DumpOnError = new OptionValue<>(false); + public static final OptionKey DumpOnError = new OptionKey<>(false); @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionValue InterceptBailout = new OptionValue<>(false); + public static final OptionKey InterceptBailout = new OptionKey<>(false); @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionValue LogVerbose = new OptionValue<>(false); + public static final OptionKey LogVerbose = new OptionKey<>(false); @Option(help = "The directory where various Graal dump files are written.") - public static final OptionValue DumpPath = new OptionValue<>("."); + public static final OptionKey DumpPath = new OptionKey<>("."); @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) - public static final OptionValue PrintCFG = new OptionValue<>(false); + public static final OptionKey PrintCFG = new OptionKey<>(false); @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) - public static final OptionValue PrintBackendCFG = new OptionValue<>(true); + public static final OptionKey PrintBackendCFG = new OptionKey<>(true); @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - public static final OptionValue PrintCFGFileName = new OptionValue<>("compilations"); + public static final OptionKey PrintCFGFileName = new OptionKey<>("compilations"); - @Option(help = "Output probabilities for fixed nodes during binary graph dumping", type = OptionType.Debug) - public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); + @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) + public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraph = new OptionValue<>(true); - @Option(help = "Dump IdealGraphVisualizer output in binary format", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Print Ideal graphs as opposed to sending them over the network.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "Base filename when dumping Ideal graphs to files.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFileName = new OptionValue<>("runtime-graphs"); + public static final OptionKey PrintGraph = new OptionKey<>(true); + @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); + @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) + public static final OptionKey PrintGraphFile = new OptionKey<>(false); + @Option(help = "Base filename when dumping graphs to files.", type = OptionType.Debug) + public static final OptionKey PrintGraphFileName = new OptionKey<>("runtime-graphs"); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphSchedule = new OptionValue<>(false); + @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphHost = new OptionKey<>("127.0.0.1"); + @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug) + public static final OptionKey PrintXmlGraphPort = new OptionKey<>(4444); + @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); + @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintTruffleTrees = new OptionValue<>(true); + public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); + + @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) + public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStrings = new OptionValue<>(false); + public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringsDirectory = new OptionValue<>("graph-strings"); + public static final OptionKey PrintCanonicalGraphStringsDirectory = new OptionKey<>("graph-strings"); @Option(help = "Choose format used when dumping canonical text for graphs: " + "0 gives a scheduled graph (better for spotting changes involving the schedule)" + "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringFlavor = new OptionValue<>(0); + public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsExcludeVirtuals = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsCheckConstants = new OptionValue<>(false); + public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsRemoveIdentities = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); @Option(help = "Enable per method metrics that are collected across all compilations of a method." + "Pattern for scope(s) in which method metering is enabled (see DebugFilter and Debug.metric).", type = OptionType.Debug) - public static final OptionValue MethodMeter = new OptionValue<>(null); + public static final OptionKey MethodMeter = new OptionKey<>(null); @Option(help = "If a global metric (DebugTimer, DebugCounter or DebugMemUseTracker) is enabled in the same scope as a method metric, " + "use the global metric to update the method metric for the current compilation. " + "This option enables the re-use of global metrics on per-compilation basis. " + @@ -152,36 +146,70 @@ public class GraalDebugConfig implements DebugConfig { "as the global metric. " + "This option incurs a small but constant overhead due to the context method lookup at each metric update. " + "Format to specify GlobalMetric interception:(Timers|Counters|MemUseTrackers)(,Timers|,Counters|,MemUseTrackers)*", type = OptionType.Debug) - public static final OptionValue GlobalMetricsInterceptedByMethodMetrics = new OptionValue<>(null); + public static final OptionKey GlobalMetricsInterceptedByMethodMetrics = new OptionKey<>(null); @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionValue ForceDebugEnable = new OptionValue<>(false); + public static final OptionKey ForceDebugEnable = new OptionKey<>(false); @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - public static final OptionValue ClearMetricsAfterBootstrap = new OptionValue<>(false); + public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) - public static final OptionValue BootstrapInitializeOnly = new OptionValue<>(false); + public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); + + // These + @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphAddress = new DeprecatedOptionKey<>(PrintGraphHost); + @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphSchedule = new DeprecatedOptionKey<>(PrintGraphWithSchedule); + @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraph = new DeprecatedOptionKey<>(PrintGraph); + @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFile = new DeprecatedOptionKey<>(PrintGraphFile); + @Option(help = "Deprecated - use PrintGraphFileName instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFileName = new DeprecatedOptionKey<>(PrintGraphFileName); + @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphPort = new DeprecatedOptionKey<>(PrintXmlGraphPort); // @formatter:on } - public static boolean isNotEmpty(OptionValue option) { - return option.getValue() != null && !option.getValue().isEmpty(); + static class DeprecatedOptionKey extends OptionKey { + private final OptionKey replacement; + + DeprecatedOptionKey(OptionKey replacement) { + super(replacement.getDefaultValue()); + this.replacement = replacement; + } + + @Override + protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { + // Ideally we'd use TTY here but it may not yet be initialized. + System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); + replacement.update(values, newValue); + } } - public static boolean areDebugScopePatternsEnabled() { - return Options.DumpOnError.getValue() || Options.Dump.getValue() != null || Options.Log.getValue() != null || areScopedGlobalMetricsEnabled(); + public static boolean isNotEmpty(OptionKey option, OptionValues options) { + return option.getValue(options) != null && !option.getValue(options).isEmpty(); } - public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled() { - return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics); + public static boolean areDebugScopePatternsEnabled(OptionValues options) { + return Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null || Options.Log.getValue(options) != null || areScopedGlobalMetricsEnabled(options); + } + + public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics, options); } /** * Determines if any of {@link Options#Count}, {@link Options#Time} or * {@link Options#TrackMemUse} has a non-null, non-empty value. + * + * @param options */ - public static boolean areScopedGlobalMetricsEnabled() { - return isNotEmpty(Options.Count) || isNotEmpty(Options.Time) || isNotEmpty(Options.TrackMemUse) || isNotEmpty(Options.MethodMeter); + public static boolean areScopedGlobalMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.Count, options) || isNotEmpty(Options.Time, options) || isNotEmpty(Options.TrackMemUse, options) || isNotEmpty(Options.MethodMeter, options); } + private final OptionValues options; + private final DebugFilter countFilter; private final DebugFilter logFilter; private final DebugFilter methodMetricsFilter; @@ -197,8 +225,9 @@ public class GraalDebugConfig implements DebugConfig { // Use an identity set to handle context objects that don't support hashCode(). private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - public GraalDebugConfig(String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, + public GraalDebugConfig(OptionValues options, String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, String methodMetricsFilter, PrintStream output, List dumpHandlers, List verifyHandlers) { + this.options = options; this.logFilter = DebugFilter.parse(logFilter); this.countFilter = DebugFilter.parse(countFilter); this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); @@ -212,15 +241,16 @@ public class GraalDebugConfig implements DebugConfig { this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); } - // Report the filters that have been configured so the user can verify it's what they expect - if (logFilter != null || countFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { - // TTY.println(Thread.currentThread().getName() + ": " + toString()); - } this.dumpHandlers = dumpHandlers; this.verifyHandlers = verifyHandlers; this.output = output; } + @Override + public OptionValues getOptions() { + return options; + } + @Override public int getLogLevel() { return getLevel(logFilter); @@ -323,7 +353,7 @@ public class GraalDebugConfig implements DebugConfig { } else if (methodFilter != null) { JavaMethod method = asJavaMethod(o); if (method != null) { - if (!Options.MethodFilterRootOnly.getValue()) { + if (!Options.MethodFilterRootOnly.getValue(options)) { if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { return true; } @@ -373,17 +403,17 @@ public class GraalDebugConfig implements DebugConfig { @Override public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue()) { + if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { return null; } - Debug.setConfig(Debug.fixedConfig(Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); + Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); Debug.log("Exception occurred in scope: %s", Debug.currentScope()); Map firstSeen = new IdentityHashMap<>(); for (Object o : Debug.context()) { // Only dump a context object once. if (!firstSeen.containsKey(o)) { firstSeen.put(o, o); - if (Options.DumpOnError.getValue()) { + if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) { Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e); } else { Debug.log("Context obj %s", o); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java index f7bc3d7bd74..87caf09f237 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java @@ -42,7 +42,7 @@ public class TTY { /** * Support for thread-local suppression of {@link TTY}. */ - public static class Filter { + public static class Filter implements AutoCloseable { private LogStream previous; private final Thread thread = Thread.currentThread(); @@ -87,6 +87,16 @@ public class TTY { log.set(LogStream.SINK); } + /** + * Creates an object that will overwrite {@link TTY} for the current thread with a custom + * log stream. To revert the overwritten state to how it was before this call, the + * {@link #remove()} method must be called on this filter object. + */ + public Filter(LogStream newStream) { + previous = out(); + log.set(newStream); + } + /** * Reverts the suppression state of {@link TTY} to how it was before this object was * constructed. @@ -97,6 +107,11 @@ public class TTY { log.set(previous); } } + + @Override + public void close() { + remove(); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java index 35261253c3c..43082c4d140 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java @@ -403,21 +403,27 @@ public final class DebugScope implements Debug.Scope { public RuntimeException handle(Throwable e) { DebugScope lastClosed = lastClosedTL.get(); - assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...)"; - if (e != lastExceptionThrownTL.get()) { - RuntimeException newException = null; - instanceTL.set(lastClosed); - try (DebugScope s = lastClosed) { - newException = s.interceptException(e); - } - assert instanceTL.get() == this; - assert lastClosed == lastClosedTL.get(); - if (newException == null) { - lastExceptionThrownTL.set(e); - } else { - lastExceptionThrownTL.set(newException); - throw newException; + try { + assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...) " + + "or an exception occurred while opening a scope"; + if (e != lastExceptionThrownTL.get()) { + RuntimeException newException = null; + instanceTL.set(lastClosed); + try (DebugScope s = lastClosed) { + newException = s.interceptException(e); + } + assert instanceTL.get() == this; + assert lastClosed == lastClosedTL.get(); + if (newException == null) { + lastExceptionThrownTL.set(e); + } else { + lastExceptionThrownTL.set(newException); + throw newException; + } } + } catch (Throwable t) { + t.initCause(e); + throw t; } if (e instanceof Error) { throw (Error) e; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java index 90af22bf09d..bd3812ce2f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java @@ -35,7 +35,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.graalvm.compiler.debug.CSVUtil; import org.graalvm.compiler.debug.GraalError; @@ -43,6 +42,8 @@ import org.graalvm.compiler.debug.LogStream; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.CollectionsUtil; /** * Facility for printing the {@linkplain KeyRegistry#getDebugValues() values} collected across all @@ -61,7 +62,7 @@ public class DebugValuesPrinter { this.mmPrinter = mmPrinter; } - public void printDebugValues() throws GraalError { + public void printDebugValues(OptionValues options) throws GraalError { TTY.println(); TTY.println(""); List topLevelMaps = DebugValueMap.getTopLevelMaps(); @@ -71,20 +72,20 @@ public class DebugValuesPrinter { ArrayList sortedValues = new ArrayList<>(debugValues); Collections.sort(sortedValues); - String summary = DebugValueSummary.getValue(); + String summary = DebugValueSummary.getValue(options); if (summary == null) { summary = "Complete"; } - if (DebugValueThreadFilter.getValue() != null && topLevelMaps.size() != 0) { - topLevelMaps = topLevelMaps.stream().filter(map -> Pattern.compile(DebugValueThreadFilter.getValue()).matcher(map.getName()).find()).collect(Collectors.toList()); + if (DebugValueThreadFilter.getValue(options) != null && topLevelMaps.size() != 0) { + topLevelMaps = CollectionsUtil.filterToList(topLevelMaps, map -> Pattern.compile(DebugValueThreadFilter.getValue(options)).matcher(map.getName()).find()); if (topLevelMaps.size() == 0) { - TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue()); + TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue(options)); } } switch (summary) { case "Name": { - LogStream log = getLogStream(); - printSummary(log, topLevelMaps, sortedValues); + LogStream log = getLogStream(options); + printSummary(options, log, topLevelMaps, sortedValues); break; } case "Partial": { @@ -93,8 +94,8 @@ public class DebugValuesPrinter { flattenChildren(map, globalMap); } globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); + LogStream log = getLogStream(options); + printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); break; } case "Complete": { @@ -104,8 +105,8 @@ public class DebugValuesPrinter { } globalMap.group(); globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); + LogStream log = getLogStream(options); + printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); break; } case "Thread": @@ -113,8 +114,8 @@ public class DebugValuesPrinter { TTY.println("Showing the results for thread: " + map.getName()); map.group(); map.normalize(); - LogStream log = getLogStream(map.getName().replace(' ', '_')); - printMap(log, new DebugValueScope(null, map), sortedValues); + LogStream log = getLogStream(options, map.getName().replace(' ', '_')); + printMap(options, log, new DebugValueScope(null, map), sortedValues); } break; default: @@ -136,12 +137,12 @@ public class DebugValuesPrinter { TTY.println(""); } - private static LogStream getLogStream() { - return getLogStream(null); + private static LogStream getLogStream(OptionValues options) { + return getLogStream(options, null); } - private static LogStream getLogStream(String prefix) { - String debugValueFile = DebugValueFile.getValue(); + private static LogStream getLogStream(OptionValues options, String prefix) { + String debugValueFile = DebugValueFile.getValue(options); if (debugValueFile != null) { try { final String fileName; @@ -168,7 +169,7 @@ public class DebugValuesPrinter { map.clearChildren(); } - private void printSummary(LogStream log, List topLevelMaps, List debugValues) { + private void printSummary(OptionValues options, LogStream log, List topLevelMaps, List debugValues) { DebugValueMap result = new DebugValueMap("Summary"); for (int i = debugValues.size() - 1; i >= 0; i--) { DebugValue debugValue = debugValues.get(i); @@ -176,7 +177,7 @@ public class DebugValuesPrinter { long total = collectTotal(topLevelMaps, index); result.setCurrentValue(index, total); } - printMap(log, new DebugValueScope(null, result), debugValues); + printMap(options, log, new DebugValueScope(null, result), debugValues); } private long collectTotal(List maps, int index) { @@ -228,19 +229,19 @@ public class DebugValuesPrinter { } - private void printMap(LogStream log, DebugValueScope scope, List debugValues) { - if (DebugValueHumanReadable.getValue()) { - printMapHumanReadable(log, scope, debugValues); + private void printMap(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { + if (DebugValueHumanReadable.getValue(options)) { + printMapHumanReadable(options, log, scope, debugValues); } else { - printMapComputerReadable(log, scope, debugValues); + printMapComputerReadable(options, log, scope, debugValues); } } - private void printMapComputerReadable(LogStream log, DebugValueScope scope, List debugValues) { + private void printMapComputerReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { for (DebugValue value : debugValues) { long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { + if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { CSVUtil.Escape.println(log, COMPUTER_READABLE_FMT, scope.toRawString(), value.getName(), value.toRawString(l), value.rawUnit()); } } @@ -248,15 +249,15 @@ public class DebugValuesPrinter { List children = scope.map.getChildren(); for (int i = 0; i < children.size(); i++) { DebugValueMap child = children.get(i); - printMapComputerReadable(log, new DebugValueScope(scope, child), debugValues); + printMapComputerReadable(options, log, new DebugValueScope(scope, child), debugValues); } } - private void printMapHumanReadable(LogStream log, DebugValueScope scope, List debugValues) { + private void printMapHumanReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { for (DebugValue value : debugValues) { long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { + if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { scope.print(log); printIndent(log, scope.level + 1); log.println(value.getName() + "=" + value.toString(l)); @@ -266,7 +267,7 @@ public class DebugValuesPrinter { List children = scope.map.getChildren(); for (int i = 0; i < children.size(); i++) { DebugValueMap child = children.get(i); - printMapHumanReadable(log, new DebugValueScope(scope, child), debugValues); + printMapHumanReadable(options, log, new DebugValueScope(scope, child), debugValues); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java index de653cac885..5f683f36778 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java @@ -201,7 +201,7 @@ public class MethodMetricsImpl implements DebugMethodMetrics { if (threadCache == null) { // this branch will only be executed once for each compiler thread on the first request // of a method metric - threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue() == null ? 128 : 16); + threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue(DebugScope.getConfig().getOptions()) == null ? 128 : 16); threadEntries.set(threadCache); addThreadCompilationData(threadCache); } @@ -334,7 +334,7 @@ public class MethodMetricsImpl implements DebugMethodMetrics { Set methods = new HashSet<>(); // gather all methods we found - threadMaps.stream().forEach(x -> { + threadMaps.forEach(x -> { // snapshot the current compilations to only capture all methods compiled until now HashMap snapShot = new HashMap<>(x); snapShot.keySet().forEach(y -> methods.add(y)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java index 11f82ab49e9..2d882d21d3b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.debug.internal.method; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -34,15 +35,15 @@ public class MethodMetricsInlineeScopeInfo extends MethodMetricsRootScopeInfo { super(rootMethod); } - public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod) { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod, OptionValues options) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { return new MethodMetricsInlineeScopeInfo(rootMethod); } return null; } - public static MethodMetricsInlineeScopeInfo create() { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + public static MethodMetricsInlineeScopeInfo create(OptionValues options) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { ExtraInfo rootInfo = DebugScope.getInstance().getExtraInfo(); if (rootInfo instanceof MethodMetricsRootScopeInfo) { return new MethodMetricsInlineeScopeInfo(((MethodMetricsRootScopeInfo) rootInfo).getRootMethod()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java index e74ed661861..3ebf04cfac4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java @@ -33,9 +33,11 @@ import java.util.List; import org.graalvm.compiler.debug.DebugMethodMetrics; import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; /** * Interface for printing a collection of method metrics (e.g. during shutdown). @@ -45,14 +47,14 @@ public interface MethodMetricsPrinter { class Options { // @formatter:off @Option(help = "Dump method metrics to stdout on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterPrintAscii = new OptionValue<>(false); + public static final OptionKey MethodMeterPrintAscii = new OptionKey<>(false); @Option(help = "Dump method metrics to the given file in CSV format on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterFile = new OptionValue<>(null); + public static final OptionKey MethodMeterFile = new OptionKey<>(null); // @formatter:on } - static boolean methodMetricsDumpingEnabled() { - return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() || MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null; + static boolean methodMetricsDumpingEnabled(OptionValues options) { + return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) || MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null; } /** @@ -110,9 +112,9 @@ public interface MethodMetricsPrinter { public MethodMetricsCSVFilePrinter() { try { - fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue())); + fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()))); } catch (IOException e) { - TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(), e); + TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()), e); throw new Error(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java index fd8b18d23d5..8667b1b86b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java @@ -54,11 +54,16 @@ public class MethodMetricsRootScopeInfo implements ExtraInfo { * is already an existing one on the scope */ public static Debug.Scope createRootScopeIfAbsent(ResolvedJavaMethod method) { - /* - * if the current compilation is not triggered from JVMCI we need a valid context root - * method for method metrics - */ - return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); + if (Debug.isEnabled()) { + /* + * if the current compilation is not triggered from JVMCI we need a valid context root + * method for method metrics + */ + return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null + : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); + } else { + return null; + } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/DumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java similarity index 74% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/DumpHandler.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java index 2ef16a8791f..a064c75de60 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/DumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,12 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.handler; +package org.graalvm.compiler.graph.test; -import java.io.Closeable; -import java.io.IOException; +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.options.OptionValues; -public interface DumpHandler extends Closeable, AutoCloseable { +public abstract class GraphTest { - void dump(Object obj, String msg) throws IOException; + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java index 8d23f55727f..265cf9550f2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java @@ -31,13 +31,14 @@ import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeMapTest { +public class NodeMapTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node { @@ -57,7 +58,7 @@ public class NodeMapTest { // Need to initialize HotSpotGraalRuntime before any Node class is initialized. Graal.getRuntime(); - graph = new Graph(); + graph = new Graph(getOptions()); for (int i = 0; i < nodes.length; i++) { nodes[i] = graph.add(new TestNode()); } @@ -107,13 +108,6 @@ public class NodeMapTest { } } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } - @Test public void testNewGet() { /* @@ -123,7 +117,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.get(newNode); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { @@ -140,7 +134,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.set(newNode, 1); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java index 2f8f34f82b0..35629047a0d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java @@ -37,7 +37,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeUsagesTests { +public class NodeUsagesTests extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class Def extends Node { @@ -66,7 +66,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsages() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -95,7 +95,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateAll() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -124,7 +124,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateNone() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -153,7 +153,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate1() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -184,7 +184,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate2() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -215,7 +215,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate0() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -246,7 +246,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate02() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -277,7 +277,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate023() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -311,7 +311,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate013() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -345,7 +345,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate203() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -379,7 +379,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate01() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -410,7 +410,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate12() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java index 18d822d34ec..effdd7df305 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java @@ -33,7 +33,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeValidationChecksTest { +public class NodeValidationChecksTest extends GraphTest { @NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) static final class TestNode extends Node { @@ -51,7 +51,7 @@ public class NodeValidationChecksTest { @Test public void testInputNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(node, null)); @@ -64,7 +64,7 @@ public class NodeValidationChecksTest { @Test public void testSuccessorNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(null, node)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java index 269143bbe33..8e34b5b65b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java @@ -33,14 +33,15 @@ import static org.junit.Assert.fail; import java.util.Iterator; import org.junit.Test; - +import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; -public class TypedNodeIteratorTest { +public class TypedNodeIteratorTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node implements IterableNodeType, TestNodeInterface { @@ -61,16 +62,21 @@ public class TypedNodeIteratorTest { @Test public void singleNodeTest() { - Graph graph = new Graph(); + getOptions(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); assertTrue(graph.hasNode(TestNode.TYPE)); assertEquals("a", toString(graph.getNodes(TestNode.TYPE))); } + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + @Test public void deletingNodeTest() { TestNode testNode = new TestNode("a"); - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(testNode); testNode.safeDelete(); assertEquals("", toString(graph.getNodes(TestNode.TYPE))); @@ -79,7 +85,7 @@ public class TypedNodeIteratorTest { @Test public void deleteAndAddTest() { TestNode testNode = new TestNode("b"); - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); graph.add(testNode); testNode.safeDelete(); @@ -90,7 +96,7 @@ public class TypedNodeIteratorTest { @Test public void iteratorBehaviorTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); Iterator iterator = graph.getNodes(TestNode.TYPE).iterator(); assertTrue(iterator.hasNext()); @@ -109,7 +115,7 @@ public class TypedNodeIteratorTest { @Test public void complicatedIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); for (TestNode tn : graph.getNodes(TestNode.TYPE)) { String name = tn.getName(); @@ -148,7 +154,7 @@ public class TypedNodeIteratorTest { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); StringBuilder sb = new StringBuilder(); int z = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java index c56b19c4b70..526a028fe56 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class TypedNodeIteratorTest2 { +public class TypedNodeIteratorTest2 extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static class NodeA extends Node implements TestNodeInterface { @@ -99,7 +99,7 @@ public class TypedNodeIteratorTest2 { @Test public void simpleSubclassTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new NodeB("b")); graph.add(new NodeD("d")); @@ -109,7 +109,7 @@ public class TypedNodeIteratorTest2 { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new NodeB("b1")); NodeD d1 = graph.add(new NodeD("d1")); StringBuilder sb = new StringBuilder(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java index 42122975c5d..6d7b7468d5d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java @@ -22,9 +22,10 @@ */ package org.graalvm.compiler.graph; -import java.util.Map; import java.util.function.Consumer; +import org.graalvm.util.UnmodifiableEconomicMap; + /** * This class is a container of a graph that needs to be readonly and optionally a lazily created * mutable copy of the graph. @@ -59,7 +60,7 @@ public final class CachedGraph { } @SuppressWarnings("unchecked") - public G getMutableCopy(Consumer> duplicationMapCallback) { + public G getMutableCopy(Consumer> duplicationMapCallback) { if (!hasMutableCopy()) { mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java deleted file mode 100644 index 70da681313f..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.DefaultCollectionsProvider; - -/** - * A default implementation of {@link NodeCollectionsProvider} that creates standard JDK collection - * class objects. - */ -public class DefaultNodeCollectionsProvider extends DefaultCollectionsProvider implements NodeCollectionsProvider { - - @Override - public Set newNodeIdentitySet() { - return Collections.newSetFromMap(newNodeIdentityMap()); - } - - @Override - public Map newNodeIdentityMap() { - return new IdentityHashMap<>(); - } - - @Override - public Map newNodeIdentityMap(int expectedMaxSize) { - return new IdentityHashMap<>(expectedMaxSize); - } - - @Override - public Map newNodeIdentityMap(Map initFrom) { - return new IdentityHashMap<>(initFrom); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java index 4c36413e06c..0e7edffcec6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java @@ -71,11 +71,11 @@ public abstract class Edges extends Fields { return (NodeList) UNSAFE.getObject(node, offset); } - private static void putNodeUnsafe(Node node, long offset, Node value) { + public static void putNodeUnsafe(Node node, long offset, Node value) { UNSAFE.putObject(node, offset, value); } - private static void putNodeListUnsafe(Node node, long offset, NodeList value) { + public static void putNodeListUnsafe(Node node, long offset, NodeList value) { UNSAFE.putObject(node, offset, value); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java index 8e99606de1d..391b318e209 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,9 @@ package org.graalvm.compiler.graph; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.function.Consumer; -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; @@ -39,8 +36,12 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ValueNumberable; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.util.UnmodifiableEconomicMap; /** * This class is a graph container, it contains the set of nodes that belong to this graph. @@ -49,13 +50,17 @@ public class Graph { public static class Options { @Option(help = "Verify graphs often during compilation when assertions are turned on", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphs = new OptionValue<>(true); + public static final OptionKey VerifyGraalGraphs = new OptionKey<>(true); @Option(help = "Perform expensive verification of graph inputs, usages, successors and predecessors", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphEdges = new OptionValue<>(false); + public static final OptionKey VerifyGraalGraphEdges = new OptionKey<>(false); @Option(help = "Graal graph compression is performed when percent of live nodes falls below this value", type = OptionType.Debug)// - public static final OptionValue GraphCompressionThreshold = new OptionValue<>(70); - @Option(help = "Use Unsafe to clone graph nodes thus avoiding copying fields that will be re-initialized anyway", type = OptionType.Debug)// - public static final OptionValue CloneNodesWithUnsafe = new OptionValue<>(true); + public static final OptionKey GraphCompressionThreshold = new OptionKey<>(70); + } + + private enum FreezeState { + Unfrozen, + TemporaryFreeze, + DeepFreeze } public final String name; @@ -109,51 +114,36 @@ public class Graph { * Used to global value number {@link ValueNumberable} {@linkplain NodeClass#isLeafNode() leaf} * nodes. */ - private final HashMap cachedLeafNodes = CollectionsFactory.newMap(); + private EconomicMap[] cachedLeafNodes; - /* - * Indicates that the graph should no longer be modified. Frozen graphs can be used my multiple - * threads so it's only safe to read them. - */ - private boolean isFrozen = false; - - /** - * Entry in {@link Graph#cachedLeafNodes}. - */ - private static final class CacheEntry { - - private final Node node; - - CacheEntry(Node node) { - assert node.getNodeClass().valueNumberable(); - assert node.getNodeClass().isLeafNode(); - this.node = node; - } + private static final Equivalence NODE_VALUE_COMPARE = new Equivalence() { @Override - public int hashCode() { - return node.getNodeClass().valueNumber(node); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { + public boolean equals(Object a, Object b) { + if (a == b) { return true; } - if (obj instanceof CacheEntry) { - CacheEntry other = (CacheEntry) obj; - if (other.node.getClass() == node.getClass()) { - return node.valueEquals(other.node); - } - } - return false; + + assert a.getClass() == b.getClass(); + return ((Node) a).valueEquals((Node) b); } @Override - public String toString() { - return node.toString(); + public int hashCode(Object k) { + return ((Node) k).getNodeClass().valueNumber((Node) k); } - } + }; + + /** + * Indicates that the graph should no longer be modified. Frozen graphs can be used by multiple + * threads so it's only safe to read them. + */ + private FreezeState freezeState = FreezeState.Unfrozen; + + /** + * The option values used while compiling this graph. + */ + private final OptionValues options; private class NodeSourcePositionScope implements DebugCloseable { private final NodeSourcePosition previous; @@ -225,8 +215,8 @@ public class Graph { /** * Creates an empty Graph with no name. */ - public Graph() { - this(null); + public Graph(OptionValues options) { + this(null, options); } /** @@ -247,11 +237,13 @@ public class Graph { * * @param name the name of the graph, used for debugging purposes */ - public Graph(String name) { + public Graph(String name, OptionValues options) { nodes = new Node[INITIAL_NODES_SIZE]; iterableNodesFirst = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); this.name = name; + this.options = options; + if (isModificationCountsEnabled()) { nodeModCounts = new int[INITIAL_NODES_SIZE]; nodeUsageModCounts = new int[INITIAL_NODES_SIZE]; @@ -318,7 +310,7 @@ public class Graph { * * @param duplicationMapCallback consumer of the duplication map created during the copying */ - public final Graph copy(Consumer> duplicationMapCallback) { + public final Graph copy(Consumer> duplicationMapCallback) { return copy(name, duplicationMapCallback); } @@ -337,15 +329,19 @@ public class Graph { * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying */ - protected Graph copy(String newName, Consumer> duplicationMapCallback) { - Graph copy = new Graph(newName); - Map duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (Map) null); + protected Graph copy(String newName, Consumer> duplicationMapCallback) { + Graph copy = new Graph(newName, options); + UnmodifiableEconomicMap duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (EconomicMap) null); if (duplicationMapCallback != null) { duplicationMapCallback.accept(duplicates); } return copy; } + public final OptionValues getOptions() { + return options; + } + @Override public String toString() { return name == null ? super.toString() : "Graph " + name; @@ -404,22 +400,23 @@ public class Graph { public T addOrUnique(T node) { if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + return uniqueHelper(node); } return add(node); } - public T addWithoutUniqueWithInputs(T node) { - addInputs(node); - return addHelper(node); - } - public T addOrUniqueWithInputs(T node) { - addInputs(node); - if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + if (node.isAlive()) { + assert node.graph() == this; + return node; + } else { + assert node.isUnregistered(); + addInputs(node); + if (node.getNodeClass().valueNumberable()) { + return uniqueHelper(node); + } + return add(node); } - return add(node); } private final class AddInputsFilter extends Node.EdgeVisitor { @@ -583,16 +580,16 @@ public class Graph { * @return a node similar to {@code node} if one exists, otherwise {@code node} */ public T unique(T node) { - return uniqueHelper(node, true); + return uniqueHelper(node); } - T uniqueHelper(T node, boolean addIfMissing) { + T uniqueHelper(T node) { assert node.getNodeClass().valueNumberable(); T other = this.findDuplicate(node); if (other != null) { return other; } else { - T result = addIfMissing ? addHelper(node) : node; + T result = addHelper(node); if (node.getNodeClass().isLeafNode()) { putNodeIntoCache(result); } @@ -600,21 +597,47 @@ public class Graph { } } + void removeNodeFromCache(Node node) { + assert node.graph() == this || node.graph() == null; + assert node.getNodeClass().valueNumberable(); + assert node.getNodeClass().isLeafNode() : node.getClass(); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes != null && cachedLeafNodes.length > leafId && cachedLeafNodes[leafId] != null) { + cachedLeafNodes[leafId].removeKey(node); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) void putNodeIntoCache(Node node) { assert node.graph() == this || node.graph() == null; assert node.getNodeClass().valueNumberable(); assert node.getNodeClass().isLeafNode() : node.getClass(); - CacheEntry entry = new CacheEntry(node); - cachedLeafNodes.put(entry, node); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId) { + EconomicMap[] newLeafNodes = new EconomicMap[leafId + 1]; + if (cachedLeafNodes != null) { + System.arraycopy(cachedLeafNodes, 0, newLeafNodes, 0, cachedLeafNodes.length); + } + cachedLeafNodes = newLeafNodes; + } + + if (cachedLeafNodes[leafId] == null) { + cachedLeafNodes[leafId] = EconomicMap.create(NODE_VALUE_COMPARE); + } + + cachedLeafNodes[leafId].put(node, node); } Node findNodeInCache(Node node) { - CacheEntry key = new CacheEntry(node); - Node result = cachedLeafNodes.get(key); - if (result != null && result.isDeleted()) { - cachedLeafNodes.remove(key); + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId || cachedLeafNodes[leafId] == null) { return null; } + + Node result = cachedLeafNodes[leafId].get(node); + assert result == null || result.isAlive() : result; return result; } @@ -774,16 +797,12 @@ public class Graph { } - static final Node PLACE_HOLDER = new PlaceHolderNode(); - - public static final int COMPRESSION_THRESHOLD = Options.GraphCompressionThreshold.getValue(); - private static final DebugCounter GraphCompressions = Debug.counter("GraphCompressions"); /** - * If the {@linkplain #COMPRESSION_THRESHOLD compression threshold} is met, the list of nodes is - * compressed such that all non-null entries precede all null entries while preserving the - * ordering between the nodes within the list. + * If the {@linkplain Options#GraphCompressionThreshold compression threshold} is met, the list + * of nodes is compressed such that all non-null entries precede all null entries while + * preserving the ordering between the nodes within the list. */ public boolean maybeCompress() { if (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()) { @@ -791,7 +810,8 @@ public class Graph { } int liveNodeCount = getNodeCount(); int liveNodePercent = liveNodeCount * 100 / nodesSize; - if (COMPRESSION_THRESHOLD == 0 || liveNodePercent >= COMPRESSION_THRESHOLD) { + int compressionThreshold = Options.GraphCompressionThreshold.getValue(options); + if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) { return false; } GraphCompressions.increment(); @@ -937,31 +957,36 @@ public class Graph { assert !isFrozen(); assert node.id() == Node.INITIAL_ID; if (nodes.length == nodesSize) { - Node[] newNodes = new Node[(nodesSize * 2) + 1]; - System.arraycopy(nodes, 0, newNodes, 0, nodesSize); - nodes = newNodes; + grow(); } - int id = nodesSize; + int id = nodesSize++; nodes[id] = node; + node.id = id; if (currentNodeSourcePosition != null) { node.setNodeSourcePosition(currentNodeSourcePosition); - } else if (!seenNodeSourcePosition && node.getNodeSourcePosition() != null) { - seenNodeSourcePosition = true; } - nodesSize++; + seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null; updateNodeCaches(node); - node.id = id; if (nodeEventListener != null) { nodeEventListener.nodeAdded(node); } - if (!seenNodeSourcePosition && node.sourcePosition != null) { - seenNodeSourcePosition = true; - } if (Fingerprint.ENABLED) { Fingerprint.submit("%s: %s", NodeEvent.NODE_ADDED, node); } + afterRegister(node); + } + + private void grow() { + Node[] newNodes = new Node[(nodesSize * 2) + 1]; + System.arraycopy(nodes, 0, newNodes, 0, nodesSize); + nodes = newNodes; + } + + @SuppressWarnings("unused") + protected void afterRegister(Node node) { + } @SuppressWarnings("unused") @@ -1003,7 +1028,10 @@ public class Graph { void unregister(Node node) { assert !isFrozen(); - assert !node.isDeleted() : "cannot delete a node twice! node=" + node; + assert !node.isDeleted() : node; + if (node.getNodeClass().isLeafNode() && node.getNodeClass().valueNumberable()) { + removeNodeFromCache(node); + } nodes[node.id] = null; nodesDeletedSinceLastCompression++; @@ -1011,7 +1039,7 @@ public class Graph { } public boolean verify() { - if (Options.VerifyGraalGraphs.getValue()) { + if (Options.VerifyGraalGraphs.getValue(options)) { for (Node node : getNodes()) { try { try { @@ -1053,7 +1081,7 @@ public class Graph { * @param replacementsMap the replacement map (can be null if no replacement is to be performed) * @return a map which associates the original nodes from {@code nodes} to their duplicates */ - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, Map replacementsMap) { + public UnmodifiableEconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, EconomicMap replacementsMap) { DuplicationReplacement replacements; if (replacementsMap == null) { replacements = null; @@ -1070,9 +1098,9 @@ public class Graph { private static final class MapReplacement implements DuplicationReplacement { - private final Map map; + private final EconomicMap map; - MapReplacement(Map map) { + MapReplacement(EconomicMap map) { this.map = map; } @@ -1087,27 +1115,31 @@ public class Graph { private static final DebugTimer DuplicateGraph = Debug.timer("DuplicateGraph"); @SuppressWarnings({"all", "try"}) - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { + public EconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { try (DebugCloseable s = DuplicateGraph.start()) { return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements); } } - /** - * Reverses the usage orders of all nodes. This is used for debugging to make sure an unorthodox - * usage order does not trigger bugs in the compiler. - */ - public void reverseUsageOrder() { - for (Node n : getNodes()) { - n.reverseUsageOrder(); - } - } - public boolean isFrozen() { - return isFrozen; + return freezeState != FreezeState.Unfrozen; } public void freeze() { - this.isFrozen = true; + this.freezeState = FreezeState.DeepFreeze; + } + + public void temporaryFreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.TemporaryFreeze; + } + + public void unfreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.Unfrozen; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 14ebbd82f08..3c91971a9bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -29,20 +29,16 @@ import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; -import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.function.Predicate; -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.Fingerprint; @@ -56,6 +52,7 @@ import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.options.OptionValues; import sun.misc.Unsafe; @@ -71,21 +68,6 @@ import sun.misc.Unsafe; *

    * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. * - *

    Replay Compilation

    - * - * To enable deterministic replay compilation, node sets and node maps should be instantiated with - * the following methods: - *
      - *
    • {@link #newSet()}
    • - *
    • {@link #newSet(Collection)}
    • - *
    • {@link #newMap()}
    • - *
    • {@link #newMap(int)}
    • - *
    • {@link #newMap(Map)}
    • - *
    • {@link #newIdentityMap()}
    • - *
    • {@link #newIdentityMap(int)}
    • - *
    • {@link #newIdentityMap(Map)}
    • - *
    - * *

    Assertions and Verification

    * * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and @@ -98,7 +80,7 @@ import sun.misc.Unsafe; public abstract class Node implements Cloneable, Formattable, NodeInterface { public static final NodeClass TYPE = null; - public static final boolean USE_UNSAFE_TO_CLONE = Graph.Options.CloneNodesWithUnsafe.getValue(); + public static final boolean USE_UNSAFE_TO_CLONE = true; static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; @@ -257,56 +239,6 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this; } - /** - * @see CollectionsFactory#newSet() - */ - public static Set newSet() { - return CollectionsFactory.newSet(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.newSet(c); - } - - public static Map newMap() { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(); - } - - public static Map newMap(Map m) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(m); - } - - public static Map newMap(int expectedMaxSize) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(expectedMaxSize); - } - - public static Map newIdentityMap() { - return CollectionsFactory.newIdentityMap(); - } - - public static Map newIdentityMap(Map m) { - return CollectionsFactory.newIdentityMap(m); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return CollectionsFactory.newIdentityMap(expectedMaxSize); - } - /** * Gets the graph context of this node. */ @@ -314,6 +246,13 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return graph; } + /** + * Gets the option values associated with this node's graph. + */ + public final OptionValues getOptions() { + return graph == null ? null : graph.getOptions(); + } + /** * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input * edges of this node. @@ -413,15 +352,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this.usage0 != null; } - void reverseUsageOrder() { - List snapshot = this.usages().snapshot(); - for (Node n : snapshot) { - this.removeUsage(n); - } - Collections.reverse(snapshot); - for (Node n : snapshot) { - this.addUsage(n); - } + /** + * Checks whether this node has more than one usages. + */ + public final boolean hasMoreThanOneUsage() { + return this.usage1 != null; + } + + /** + * Checks whether this node has exactly one usgae. + */ + public final boolean hasExactlyOneUsage() { + return hasUsages() && !hasMoreThanOneUsage(); } /** @@ -533,14 +475,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } } - public boolean isDeleted() { + public final boolean isDeleted() { return id <= DELETED_ID_START; } - public boolean isAlive() { + public final boolean isAlive() { return id >= ALIVE_ID_START; } + public final boolean isUnregistered() { + return id == INITIAL_ID; + } + /** * Updates the usages sets of the given nodes after an input slot is changed from * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and @@ -761,7 +707,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { public void replaceAndDelete(Node other) { assert checkReplaceWith(other); assert other != null; - replaceAtUsages(other); + if (this.hasUsages()) { + replaceAtUsages(other); + } replaceAtPredecessor(other); this.safeDelete(); } @@ -852,12 +800,8 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (edgesToCopy.contains(type)) { getNodeClass().getEdges(type).copy(this, newNode); } else { - if (USE_UNSAFE_TO_CLONE) { - // The direct edges are already null - getNodeClass().getEdges(type).initializeLists(newNode, this); - } else { - getNodeClass().getEdges(type).clear(newNode); - } + // The direct edges are already null + getNodeClass().getEdges(type).initializeLists(newNode, this); } } @@ -891,22 +835,11 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { Node newNode = null; try { - if (USE_UNSAFE_TO_CLONE) { - newNode = (Node) UNSAFE.allocateInstance(getClass()); - newNode.nodeClass = nodeClassTmp; - nodeClassTmp.getData().copy(this, newNode); - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } else { - newNode = (Node) this.clone(); - newNode.typeCacheNext = null; - newNode.usage0 = null; - newNode.usage1 = null; - newNode.predecessor = null; - newNode.extraUsagesCount = 0; - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } + newNode = (Node) UNSAFE.allocateInstance(getClass()); + newNode.nodeClass = nodeClassTmp; + nodeClassTmp.getData().copy(this, newNode); + copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); + copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); } catch (Exception e) { throw new GraalGraphError(e).addContext(this); } @@ -936,7 +869,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (input == null) { assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); } else { - assertFalse(input.isDeleted(), "input was deleted"); + assertFalse(input.isDeleted(), "input was deleted %s", input); assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); } @@ -948,7 +881,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); verifyInputs(); - if (Options.VerifyGraalGraphEdges.getValue()) { + if (Options.VerifyGraalGraphEdges.getValue(getOptions())) { verifyEdges(); } return true; @@ -1028,20 +961,23 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } /** - * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. + * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same + * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in + * the same set. */ @Override public final int hashCode() { - return System.identityHashCode(this); + assert !this.isUnregistered() : "node not yet constructed"; + if (this.isDeleted()) { + return -id + DELETED_ID_START; + } + return id; } /** - * Equality tests must rely solely on identity. + * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely + * on identity. */ - @Override - public final boolean equals(Object obj) { - return super.equals(obj); - } /** * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index b802b321e79..6138d2005a5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -28,7 +28,6 @@ import static org.graalvm.compiler.graph.Edges.translateInto; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.Node.WithAllEdges; -import static org.graalvm.compiler.graph.Node.newIdentityMap; import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.Annotation; @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.Iterator; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; @@ -68,9 +66,8 @@ import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Metadata for every {@link Node} type. The metadata includes: @@ -82,13 +79,6 @@ import org.graalvm.compiler.options.StableOptionValue; */ public final class NodeClass extends FieldIntrospection { - public static class Options { - // @formatter:off - @Option(help = "Verifies that receivers of NodeInfo#size() and NodeInfo#cycles() do not have UNSET values.") - public static final OptionValue VerifyNodeCostOnAccess = new StableOptionValue<>(false); - // @formatter:on - } - // Timers for creation of a NodeClass instance private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); @@ -140,6 +130,7 @@ public final class NodeClass extends FieldIntrospection { private static final Class SUCCESSOR_LIST_CLASS = NodeSuccessorList.class; private static AtomicInteger nextIterableId = new AtomicInteger(); + private static AtomicInteger nextLeafId = new AtomicInteger(); private final InputEdges inputs; private final SuccessorEdges successors; @@ -173,6 +164,8 @@ public final class NodeClass extends FieldIntrospection { private final boolean isSimplifiable; private final boolean isLeafNode; + private final int leafId; + public NodeClass(Class clazz, NodeClass superNodeClass) { this(clazz, superNodeClass, new FieldsScanner.DefaultCalcOffset(), null, 0); } @@ -207,6 +200,11 @@ public final class NodeClass extends FieldIntrospection { } isLeafNode = inputs.getCount() + successors.getCount() == 0; + if (isLeafNode) { + this.leafId = nextLeafId.getAndIncrement(); + } else { + this.leafId = -1; + } canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.getName().hashCode(); @@ -277,16 +275,10 @@ public final class NodeClass extends FieldIntrospection { private final NodeSize size; public NodeCycles cycles() { - if (Options.VerifyNodeCostOnAccess.getValue() && cycles == NodeCycles.CYCLES_UNSET) { - throw new GraalError("Missing NodeCycles specification in the @NodeInfo annotation of the node %s", this); - } return cycles; } public NodeSize size() { - if (Options.VerifyNodeCostOnAccess.getValue() && size == NodeSize.SIZE_UNSET) { - throw new GraalError("Missing NodeSize specification in the @NodeInfo annotation of the node %s", this); - } return size; } @@ -532,7 +524,11 @@ public final class NodeClass extends FieldIntrospection { } private static int deepHashCode0(Object o) { - if (o instanceof Object[]) { + if (o == null) { + return 0; + } else if (!o.getClass().isArray()) { + return o.hashCode(); + } else if (o instanceof Object[]) { return Arrays.deepHashCode((Object[]) o); } else if (o instanceof byte[]) { return Arrays.hashCode((byte[]) o); @@ -550,10 +546,8 @@ public final class NodeClass extends FieldIntrospection { return Arrays.hashCode((double[]) o); } else if (o instanceof boolean[]) { return Arrays.hashCode((boolean[]) o); - } else if (o != null) { - return o.hashCode(); } else { - return 0; + throw shouldNotReachHere(); } } @@ -606,29 +600,31 @@ public final class NodeClass extends FieldIntrospection { private static boolean deepEquals0(Object e1, Object e2) { assert e1 != null; - boolean eq; - if (e1 instanceof Object[] && e2 instanceof Object[]) { - eq = Arrays.deepEquals((Object[]) e1, (Object[]) e2); - } else if (e1 instanceof byte[] && e2 instanceof byte[]) { - eq = Arrays.equals((byte[]) e1, (byte[]) e2); - } else if (e1 instanceof short[] && e2 instanceof short[]) { - eq = Arrays.equals((short[]) e1, (short[]) e2); - } else if (e1 instanceof int[] && e2 instanceof int[]) { - eq = Arrays.equals((int[]) e1, (int[]) e2); - } else if (e1 instanceof long[] && e2 instanceof long[]) { - eq = Arrays.equals((long[]) e1, (long[]) e2); - } else if (e1 instanceof char[] && e2 instanceof char[]) { - eq = Arrays.equals((char[]) e1, (char[]) e2); - } else if (e1 instanceof float[] && e2 instanceof float[]) { - eq = Arrays.equals((float[]) e1, (float[]) e2); - } else if (e1 instanceof double[] && e2 instanceof double[]) { - eq = Arrays.equals((double[]) e1, (double[]) e2); - } else if (e1 instanceof boolean[] && e2 instanceof boolean[]) { - eq = Arrays.equals((boolean[]) e1, (boolean[]) e2); + if (e2 == null) { + return false; + } else if (e1 instanceof Object[] && e2 instanceof Object[]) { + return Arrays.deepEquals((Object[]) e1, (Object[]) e2); + } else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) { + return e1.equals(e2); + } else if (e1 instanceof byte[]) { + return Arrays.equals((byte[]) e1, (byte[]) e2); + } else if (e1 instanceof short[]) { + return Arrays.equals((short[]) e1, (short[]) e2); + } else if (e1 instanceof int[]) { + return Arrays.equals((int[]) e1, (int[]) e2); + } else if (e1 instanceof long[]) { + return Arrays.equals((long[]) e1, (long[]) e2); + } else if (e1 instanceof char[]) { + return Arrays.equals((char[]) e1, (char[]) e2); + } else if (e1 instanceof float[]) { + return Arrays.equals((float[]) e1, (float[]) e2); + } else if (e1 instanceof double[]) { + return Arrays.equals((double[]) e1, (double[]) e2); + } else if (e1 instanceof boolean[]) { + return Arrays.equals((boolean[]) e1, (boolean[]) e2); } else { - eq = e1.equals(e2); + throw shouldNotReachHere(); } - return eq; } public boolean dataEquals(Node a, Node b) { @@ -810,15 +806,15 @@ public final class NodeClass extends FieldIntrospection { Node replacement(Node node, Edges.Type type); } - static Map addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { - final Map newNodes; + static EconomicMap addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { + final EconomicMap newNodes; int denseThreshold = oldGraph.getNodeCount() + oldGraph.getNodesDeletedSinceLastCompression() >> 4; if (estimatedNodeCount > denseThreshold) { // Use dense map - newNodes = new NodeNodeMap(oldGraph); + newNodes = new NodeMap<>(oldGraph); } else { // Use sparse map - newNodes = newIdentityMap(); + newNodes = EconomicMap.create(Equivalence.IDENTITY); } createNodeDuplicates(graph, nodes, replacements, newNodes); @@ -859,7 +855,7 @@ public final class NodeClass extends FieldIntrospection { return newNodes; } - private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final Map newNodes) { + private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final EconomicMap newNodes) { for (Node node : nodes) { if (node != null) { assert !node.isDeleted() : "trying to duplicate deleted node: " + node; @@ -886,12 +882,12 @@ public final class NodeClass extends FieldIntrospection { } } - private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node) { + private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node) { transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Inputs); transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Successors); } - private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node, Edges.Type type) { + private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node, Edges.Type type) { NodeClass nodeClass = node.getNodeClass(); NodeClass oldNodeClass = oldNode.getNodeClass(); Edges oldEdges = oldNodeClass.getEdges(type); @@ -926,6 +922,10 @@ public final class NodeClass extends FieldIntrospection { return isLeafNode; } + public int getLeafId() { + return this.leafId; + } + public long inputsIteration() { return inputsIteration; } @@ -1086,6 +1086,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("succs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1101,6 +1120,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("inputs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1117,13 +1155,15 @@ public final class NodeClass extends FieldIntrospection { assert other.getNodeClass() == this; while (myMask != 0) { long offset = (myMask & OFFSET_MASK); - Object v1 = UNSAFE.getObject(node, offset); - Object v2 = UNSAFE.getObject(other, offset); if ((myMask & LIST_MASK) == 0) { + Object v1 = Edges.getNodeUnsafe(node, offset); + Object v2 = Edges.getNodeUnsafe(other, offset); if (v1 != v2) { return false; } } else { + Object v1 = Edges.getNodeListUnsafe(node, offset); + Object v2 = Edges.getNodeListUnsafe(other, offset); if (!Objects.equals(v1, v2)) { return false; } @@ -1178,7 +1218,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode != null) { Node newNode = consumer.apply(node, curNode); if (newNode != curNode) { - UNSAFE.putObject(node, offset, newNode); + Edges.putNodeUnsafe(node, offset, newNode); } } } else { @@ -1211,7 +1251,7 @@ public final class NodeClass extends FieldIntrospection { Node curNode = Edges.getNodeUnsafe(node, offset); if (curNode != null) { node.updatePredecessor(curNode, null); - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtSuccessorsAsPredecessorHelper(node, offset); @@ -1276,9 +1316,9 @@ public final class NodeClass extends FieldIntrospection { while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { - Object curNode = UNSAFE.getObject(node, offset); + Object curNode = Edges.getNodeUnsafe(node, offset); if (curNode == key) { - UNSAFE.putObject(node, offset, replacement); + Edges.putNodeUnsafe(node, offset, replacement); return true; } } else { @@ -1333,7 +1373,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode.hasNoUsages()) { node.maybeNotifyZeroUsages(curNode); } - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtInputsAsUsageHelper(node, offset); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java deleted file mode 100644 index 848c9efb041..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.CollectionsProvider; - -/** - * Extends {@link CollectionsProvider} with support for creating {@link Node} based collections. - */ -public interface NodeCollectionsProvider extends CollectionsProvider { - - /** - * Creates a set of {@link Node}s that uses reference-equality in place of object-equality when - * comparing entries. - */ - Set newNodeIdentitySet(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(int expectedMaxSize); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newNodeIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java index 32ab50d5b65..5b0edb8b39c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.graph; -import java.util.AbstractMap.SimpleEntry; import java.util.Arrays; import java.util.Iterator; -import java.util.Map.Entry; +import java.util.function.BiFunction; -public class NodeMap extends NodeIdAccessor { +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +public class NodeMap extends NodeIdAccessor implements EconomicMap { private static final int MIN_REALLOC_SIZE = 16; @@ -43,6 +45,7 @@ public class NodeMap extends NodeIdAccessor { this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); } + @Override @SuppressWarnings("unchecked") public T get(Node node) { assert check(node); @@ -62,16 +65,15 @@ public class NodeMap extends NodeIdAccessor { assert check(node); } + @Override public boolean isEmpty() { - return !entries().iterator().hasNext(); + throw new UnsupportedOperationException("isEmpty() is not supported for performance reasons"); } - public boolean containsKey(Object key) { - if (key instanceof Node) { - Node node = (Node) key; - if (node.graph() == graph()) { - return get(node) != null; - } + @Override + public boolean containsKey(Node node) { + if (node.graph() == graph()) { + return get(node) != null; } return false; } @@ -96,7 +98,7 @@ public class NodeMap extends NodeIdAccessor { public void setAndGrow(Node node, T value) { checkAndGrow(node); - values[getNodeId(node)] = value; + set(node, value); } /** @@ -107,12 +109,17 @@ public class NodeMap extends NodeIdAccessor { return graph.getNode(i); } + @Override public int size() { + throw new UnsupportedOperationException("size() is not supported for performance reasons"); + } + + public int capacity() { return values.length; } public boolean isNew(Node node) { - return getNodeId(node) >= size(); + return getNodeId(node) >= capacity(); } private boolean check(Node node) { @@ -121,16 +128,92 @@ public class NodeMap extends NodeIdAccessor { return true; } + @Override public void clear() { Arrays.fill(values, null); } - public Iterable> entries() { - return new Iterable>() { + @Override + public Iterable getKeys() { + return new Iterable() { @Override - public Iterator> iterator() { - return new Iterator>() { + public Iterator iterator() { + return new Iterator() { + + int i = 0; + + @Override + public boolean hasNext() { + forward(); + return i < NodeMap.this.values.length; + } + + @Override + public Node next() { + final int pos = i; + final Node key = NodeMap.this.getKey(pos); + i++; + forward(); + return key; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private void forward() { + while (i < NodeMap.this.values.length && (NodeMap.this.getKey(i) == null || NodeMap.this.values[i] == null)) { + i++; + } + } + }; + } + }; + } + + @Override + public MapCursor getEntries() { + return new MapCursor() { + + int current = -1; + + @Override + public boolean advance() { + current++; + while (current < NodeMap.this.values.length && (NodeMap.this.values[current] == null || NodeMap.this.getKey(current) == null)) { + current++; + } + return current < NodeMap.this.values.length; + } + + @Override + public Node getKey() { + return NodeMap.this.getKey(current); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() { + return (T) NodeMap.this.values[current]; + } + + @Override + public void remove() { + assert NodeMap.this.values[current] != null; + NodeMap.this.values[current] = null; + } + }; + } + + @Override + public Iterable getValues() { + return new Iterable() { + + @Override + public Iterator iterator() { + return new Iterator() { int i = 0; @@ -142,23 +225,12 @@ public class NodeMap extends NodeIdAccessor { @SuppressWarnings("unchecked") @Override - public Entry next() { + public T next() { final int pos = i; - Node key = NodeMap.this.getKey(pos); - T value = (T) NodeMap.this.values[pos]; + final T value = (T) NodeMap.this.values[pos]; i++; forward(); - return new SimpleEntry(key, value) { - - private static final long serialVersionUID = 7813842391085737738L; - - @Override - public T setValue(T v) { - T oldv = super.setValue(v); - NodeMap.this.values[pos] = v; - return oldv; - } - }; + return value; } @Override @@ -178,24 +250,42 @@ public class NodeMap extends NodeIdAccessor { @Override public String toString() { - Iterator> i = entries().iterator(); - if (!i.hasNext()) { + MapCursor i = getEntries(); + if (!i.advance()) { return "{}"; } StringBuilder sb = new StringBuilder(); sb.append('{'); while (true) { - Entry e = i.next(); - Node key = e.getKey(); - T value = e.getValue(); + Node key = i.getKey(); + T value = i.getValue(); sb.append(key); sb.append('='); sb.append(value); - if (!i.hasNext()) { + if (!i.advance()) { return sb.append('}').toString(); } sb.append(',').append(' '); } } + + @Override + public T put(Node key, T value) { + T result = get(key); + set(key, value); + return result; + } + + @Override + public T removeKey(Node key) { + return put(key, null); + } + + @Override + public void replaceAll(BiFunction function) { + for (Node n : getKeys()) { + put(n, function.apply(n, get(n))); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java deleted file mode 100644 index 31e4071d688..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public final class NodeNodeMap extends NodeMap implements Map { - - public NodeNodeMap(Graph graph) { - super(graph); - } - - public NodeNodeMap(NodeNodeMap copyFrom) { - super(copyFrom); - } - - @Override - public Node get(Object key) { - return super.get((Node) key); - } - - @Override - public Node put(Node key, Node value) { - Node oldValue = super.get(key); - super.set(key, value); - return oldValue; - } - - @Override - public Node remove(Object key) { - throw new UnsupportedOperationException("Cannot remove keys from this map"); - } - - @Override - public void putAll(Map m) { - for (Entry entry : m.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } - - @Override - public Set keySet() { - HashSet entries = new HashSet<>(); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - Node key = getKey(i); - if (key != null) { - entries.add(key); - } - } - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } - - @Override - public Collection values() { - ArrayList result = new ArrayList<>(this.size()); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - result.add((Node) v); - } - } - return result; - } - - @Override - public Set> entrySet() { - HashSet> entries = new HashSet<>(); - for (Map.Entry entry : entries()) { - entries.add(entry); - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java index 5e82577feaa..803b86aed43 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,10 @@ public final class NodeStack { values = new Node[INITIAL_SIZE]; } + public int size() { + return tos; + } + public void push(Node n) { int newIndex = tos++; int valuesLength = values.length; @@ -49,6 +53,10 @@ public final class NodeStack { values = newValues; } + public Node get(int index) { + return values[index]; + } + public Node pop() { assert tos > 0 : "stack must be non-empty"; return values[--tos]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java index b84fadadbf4..37f7a76629b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java @@ -24,6 +24,8 @@ package org.graalvm.compiler.graph; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; +import java.util.Iterator; + import org.graalvm.compiler.graph.iterators.NodeIterable; class NodeUsageIterable implements NodeIterable { @@ -62,4 +64,23 @@ class NodeUsageIterable implements NodeIterable { public int count() { return node.getUsageCount(); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("usages="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java index 335826d2cdf..c515f788b9b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java @@ -27,6 +27,8 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; +import org.graalvm.compiler.core.common.PermanentBailoutException; + public abstract class NodeWorkList implements Iterable { protected final Queue worklist; @@ -70,11 +72,12 @@ public abstract class NodeWorkList implements Iterable { } public static final class IterativeNodeWorkList extends NodeWorkList { - + private static final int HARD_ITERATION_LIMIT = 1_000_000; private static final int EXPLICIT_BITMAP_THRESHOLD = 10; protected NodeBitMap inQueue; - private int iterationLimit = Integer.MAX_VALUE; + private int iterationLimit; + private boolean hardLimit; private Node firstNoChange; private Node lastPull; private Node lastChain; @@ -82,7 +85,12 @@ public abstract class NodeWorkList implements Iterable { public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { super(graph, fill); if (iterationLimitPerNode > 0) { - iterationLimit = iterationLimitPerNode * graph.getNodeCount(); + long limit = (long) iterationLimitPerNode * graph.getNodeCount(); + iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); + hardLimit = false; + } else { + iterationLimit = HARD_ITERATION_LIMIT; + hardLimit = true; } } @@ -92,7 +100,14 @@ public abstract class NodeWorkList implements Iterable { @Override public boolean hasNext() { dropDeleted(); - return iterationLimit > 0 && !worklist.isEmpty(); + if (iterationLimit <= 0) { + if (hardLimit) { + throw new PermanentBailoutException("Iteration limit reached"); + } else { + return false; + } + } + return !worklist.isEmpty(); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java index e018065bbbe..a879bbe978b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.graph; -import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; @@ -40,7 +39,6 @@ class TypedGraphNodeIterator implements Iterator ids = clazz.iterableIds(); currentIdIndex = 0; current = new Node[ids.length]; - Arrays.fill(current, Graph.PLACE_HOLDER); needsForward = true; } @@ -67,7 +65,7 @@ class TypedGraphNodeIterator implements Iterator int startIdx = currentIdIndex; while (true) { Node next; - if (current() == Graph.PLACE_HOLDER) { + if (current() == null) { next = graph.getIterableNodeStart(ids[currentIdIndex]); } else { next = graph.getIterableNodeNext(current().typeCacheNext); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java index e7fc59fe646..e36f717b068 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java @@ -28,6 +28,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.options.OptionValues; public interface CanonicalizerTool { @@ -53,4 +54,6 @@ public interface CanonicalizerTool { * width. This check is used by canonicalizations that might introduce subword compares. */ boolean supportSubwordCompare(int bits); + + OptionValues getOptions(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index 8d3b056e404..ba1623af90a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -31,8 +31,6 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; @@ -66,6 +64,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -140,35 +139,39 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } crb.blockComment("[method prologue]"); - if (ZapStackOnMethodEntry.getValue()) { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - int intSize = 4; - AArch64Address address = AArch64Address.createPreIndexedImmediateAddress(scratch, -intSize); - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register value = sc2.getRegister(); - masm.mov(value, 0xC1C1C1C1); - for (int i = 0; i < frameSize; i += intSize) { - masm.str(32, value, address); - } - } - masm.mov(64, sp, scratch); - } - } else { - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { masm.sub(64, sp, sp, totalFrameSize); + masm.stp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); } else { - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register scratch2 = sc2.getRegister(); - masm.mov(scratch2, totalFrameSize); - masm.sub(64, sp, sp, scratch2); + masm.stp(64, fp, lr, AArch64Address.createPreIndexedImmediateAddress(sp, -2)); + if (frameSize < 1 << 12) { + masm.sub(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.sub(64, sp, sp, rscratch1); } } } + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + int longSize = 8; + masm.mov(64, scratch, sp); + AArch64Address address = AArch64Address.createPostIndexedImmediateAddress(scratch, longSize); + try (ScratchRegister sc2 = masm.getScratchRegister()) { + Register value = sc2.getRegister(); + masm.mov(value, 0xBADDECAFFC0FFEEL); + for (int i = 0; i < frameSize; i += longSize) { + masm.str(64, value, address); + } + } - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.stp(64, fp, lr, address2); - + } + } crb.blockComment("[code body]"); } @@ -176,23 +179,28 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { public void leave(CompilationResultBuilder crb) { AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; - final int frameSize = frameMap.frameSize(); final int totalFrameSize = frameMap.totalFrameSize(); crb.blockComment("[method epilogue]"); - - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.ldp(64, fp, lr, address2); - - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { - masm.add(64, sp, sp, totalFrameSize); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - masm.mov(scratch, totalFrameSize); - masm.add(64, sp, sp, scratch); + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + final int frameSize = frameMap.frameSize(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { + masm.ldp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); + masm.add(64, sp, sp, totalFrameSize); + } else { + if (frameSize < 1 << 12) { + masm.add(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.add(64, sp, sp, rscratch1); + } + masm.ldp(64, fp, lr, AArch64Address.createPostIndexedImmediateAddress(sp, 2)); } } + } @Override @@ -218,7 +226,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -227,7 +235,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } return crb; @@ -315,13 +323,13 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 64d47cb243d..c80af37d20c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -50,6 +50,7 @@ import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.NodeCostProvider; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins; @@ -137,7 +138,7 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); @@ -159,7 +160,7 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AArch64GraphBuilderPlugins.register(plugins, foreignCalls, replacements.getReplacementBytecodeProvider()); + AArch64GraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider()); return plugins; } @@ -171,8 +172,8 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java index d7aefd8293d..541b68af14d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.aarch64.AArch64.r0; import static jdk.vm.ci.aarch64.AArch64.r3; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -63,7 +62,7 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -76,16 +75,12 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - throw GraalError.unimplemented("PreferGraalStubs"); - } - // These stubs do callee saving if (config.useCRC32Intrinsics) { registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java index 52fbb28d51a..f2eb47b145a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java @@ -68,16 +68,19 @@ public class AArch64HotSpotJumpToExceptionHandlerInCallerOp extends AArch64HotSp public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { leaveFrame(crb, masm, /* emitSafepoint */false); - // Restore sp from fp if the exception PC is a method handle call site. - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false); - masm.ldr(32, scratch, address); - Label noRestore = new Label(); - masm.cbz(32, scratch, noRestore); - masm.mov(64, sp, fp); - masm.bind(noRestore); + if (System.getProperty("java.specification.version").compareTo("1.8") < 0) { + // Restore sp from fp if the exception PC is a method handle call site. + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false); + masm.ldr(32, scratch, address); + Label noRestore = new Label(); + masm.cbz(32, scratch, noRestore); + masm.mov(64, sp, fp); + masm.bind(noRestore); + } } + masm.jmp(asRegister(handlerInCallerPc)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index d8b03b30c85..a7bcd232c53 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -29,24 +29,24 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -58,9 +58,11 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.aarch64.AArch64CCall; import org.graalvm.compiler.lir.aarch64.AArch64Call; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; +import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -129,6 +131,19 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H } @Override + public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args) { + Value[] argLocations = new Value[args.length]; + getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); + for (int i = 0; i < args.length; i++) { + Value arg = args[i]; + AllocatableValue loc = nativeCallingConvention.getArgument(i); + emitMove(loc, arg); + argLocations[i] = loc; + } + Value ptr = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(address)); + append(new AArch64CCall(nativeCallingConvention.getReturn(), ptr, argLocations)); + } + public SaveRegistersOp emitSaveAllRegisters() { throw GraalError.unimplemented(); } @@ -193,8 +208,8 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -214,14 +229,25 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; } } + @Override + public void emitNullCheck(Value address, LIRFrameState state) { + if (address.getValueKind().getPlatformKind() == AArch64Kind.DWORD) { + CompressEncoding encoding = config.getOopEncoding(); + Value uncompressed = emitUncompress(address, encoding, false); + append(new AArch64Move.NullCheckOp(asAddressValue(uncompressed), state)); + } else { + super.emitNullCheck(address, state); + } + } + @Override public void emitPrefetchAllocate(Value address) { append(new AArch64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java index 8aa3a0483dc..63e7c07ce93 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.RemNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.aarch64.AArch64FloatArithmeticSnippets; import org.graalvm.compiler.replacements.aarch64.AArch64IntegerArithmeticSnippets; @@ -52,10 +53,10 @@ public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvid } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - super.initialize(providers, config); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + super.initialize(options, providers, config); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java index 89dc03de43e..5c470229ad1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java @@ -22,16 +22,17 @@ */ package org.graalvm.compiler.hotspot.aarch64; +import static jdk.vm.ci.aarch64.AArch64.zr; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; -import static jdk.vm.ci.code.ValueUtil.asRegister; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -61,7 +62,7 @@ public class AArch64HotSpotMove { crb.recordInlineDataInCode(constant); if (constant.isCompressed()) { // masm.forceMov(asRegister(result), 0); - throw GraalError.unimplemented(); + masm.movNarrowAddress(asRegister(result), 0); } else { masm.movNativeAddress(asRegister(result), 0); } @@ -106,27 +107,24 @@ public class AArch64HotSpotMove { Register ptr = asRegister(input); Register base = asRegister(baseRegister); // result = (ptr - base) >> shift - if (encoding.base == 0) { - if (encoding.shift == 0) { - masm.movx(resultRegister, ptr); + if (!encoding.hasBase()) { + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, ptr, encoding.getShift()); } else { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, ptr, encoding.shift); + masm.movx(resultRegister, ptr); } } else if (nonNull) { masm.sub(64, resultRegister, ptr, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.shl(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.shl(64, resultRegister, resultRegister, encoding.getShift()); } } else { // if ptr is null it still has to be null after compression masm.cmp(64, ptr, 0); masm.cmov(64, resultRegister, ptr, base, AArch64Assembler.ConditionFlag.NE); masm.sub(64, resultRegister, resultRegister, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); } } } @@ -161,14 +159,19 @@ public class AArch64HotSpotMove { Register base = asRegister(baseRegister); // result = base + (ptr << shift) if (nonNull) { - assert encoding.shift == encoding.alignment; - masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.ASR, encoding.shift); + masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + } else if (!encoding.hasBase()) { + masm.add(64, resultRegister, zr, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); } else { // if ptr is null it has to be null after decompression - // masm.cmp(64, ); - throw GraalError.unimplemented(); + Label done = new Label(); + if (!resultRegister.equals(ptr)) { + masm.mov(32, resultRegister, ptr); + } + masm.cbz(32, resultRegister, done); + masm.add(64, resultRegister, base, resultRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + masm.bind(done); } - } } @@ -188,10 +191,8 @@ public class AArch64HotSpotMove { public static void decodeKlassPointer(AArch64MacroAssembler masm, Register result, Register ptr, Register klassBase, CompressEncoding encoding) { // result = klassBase + ptr << shift - if (encoding.shift != 0 || encoding.base != 0) { - // (shift != 0 -> shift == alignment) - assert (encoding.shift == 0 || encoding.shift == encoding.alignment) : "Decode algorithm is wrong: " + encoding; - masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.shift); + if (encoding.hasShift() || encoding.hasBase()) { + masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java index 641cf5d8bd3..162de6d0f33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java @@ -31,18 +31,18 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class AArch64HotSpotMoveFactory extends AArch64MoveFactory { @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java index 1352a913af2..d3d770d9e00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java @@ -39,13 +39,11 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64BreakpointOp; -import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -70,7 +68,6 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.Value; -import jdk.vm.ci.meta.ValueKind; /** * LIR generator specialized for AArch64 HotSpot. @@ -180,20 +177,6 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - ValueKind kind = cmpValue.getValueKind(); - assert kind.equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - Variable scratch = gen.newVariable(LIRKind.value(AArch64Kind.DWORD)); - append(new CompareAndSwapOp(result, cmpValue, newValue, address, scratch)); - setResult(x, result); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java index 5848b3bdda9..15e4e38ff8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java @@ -28,7 +28,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AArch64ExceptionCode; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -54,9 +53,9 @@ final class AArch64HotSpotPatchReturnAddressOp extends AArch64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { final int frameSize = crb.frameMap.frameSize(); - // XXX where is lr exactly? - AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, frameSize); - masm.brk(AArch64ExceptionCode.BREAKPOINT); // XXX + // LR is saved in the {fp, lr} pair above the frame + AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, + frameSize + crb.target.wordSize); masm.str(64, asRegister(address), lrAddress); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java index ac9b0967dc5..d4013c5974e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java @@ -109,8 +109,8 @@ public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationCo }; // @formatter:on - public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java index 02b2146c36a..a2023faf776 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -77,18 +77,18 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { } public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) { - int pos = masm.position(); if (isPollingPageFar(config)) { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); masm.movNativeAddress(scratch, config.safepointPollingAddress); + crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createBaseRegisterOnlyAddress(scratch)); } else { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_NEAR : config.MARKID_POLL_NEAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createPcLiteralAddress(0)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java new file mode 100644 index 00000000000..520f8b9c9f7 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; + +import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; +import org.graalvm.compiler.core.common.type.RawPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.hotspot.HotSpotCallingConventionType; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Value; + +@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_20) +public final class AArch64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AArch64RawNativeCallNode.class); + + protected final JavaConstant functionPointer; + @Input NodeInputList args; + + public AArch64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) { + super(TYPE, StampFactory.forKind(returnType)); + this.functionPointer = functionPointer; + this.args = new NodeInputList<>(this, args); + } + + private static class PointerType implements JavaType { + + @Override + public String getName() { + return "void*"; + } + + @Override + public JavaType getComponentType() { + return null; + } + + @Override + public JavaType getArrayClass() { + return null; + } + + @Override + public JavaKind getJavaKind() { + // native pointers and java objects use the same registers in the calling convention + return JavaKind.Object; + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return null; + } + } + + private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) { + if (stamp instanceof RawPointerStamp) { + return new PointerType(); + } else { + return stamp.javaType(metaAccess); + } + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + AArch64NodeLIRBuilder gen = (AArch64NodeLIRBuilder) generator; + Value[] parameter = new Value[args.count()]; + JavaType[] parameterTypes = new JavaType[args.count()]; + for (int i = 0; i < args.count(); i++) { + parameter[i] = generator.operand(args.get(i)); + parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + } + JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes, + generator.getLIRGeneratorTool()); + gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter); + if (this.getStackKind() != JavaKind.Void) { + generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java index 31b67987d9e..706b1fd36d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java @@ -22,19 +22,13 @@ */ package org.graalvm.compiler.hotspot.amd64.test; -import org.junit.Assert; +import static org.graalvm.compiler.core.common.GraalOptions.OptImplicitNullChecks; + +import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; +import org.graalvm.compiler.options.OptionValues; import org.junit.Assume; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -57,16 +51,15 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); - Result expect = executeExpected(method, null, c); + ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); + Result expect = executeExpected(method, null, c); - // make sure we don't get a profile that removes the implicit null check - method.reprofile(); + // make sure we don't get a profile that removes the implicit null check + method.reprofile(); - Result actual = executeActual(method, null, c); - assertEquals(expect, actual); - } + OptionValues options = new OptionValues(getInitialOptions(), OptImplicitNullChecks, true); + Result actual = executeActual(options, method, null, c); + assertEquals(expect, actual); } @SuppressWarnings("try") @@ -76,9 +69,7 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, false)) { - test("testSnippet", c); - } + test(new OptionValues(getInitialOptions(), OptImplicitNullChecks, false), "testSnippet", c); } @Test @@ -100,18 +91,4 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { public void explicitNull() { testExplicit(null); } - - @Override - protected boolean checkMidTierGraph(StructuredGraph graph) { - int count = 0; - for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { - ValueNode value = isNull.getValue(); - if (value instanceof CompressionNode) { - count++; - isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); - } - } - Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); - return super.checkMidTierGraph(graph); - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java index b7b473b8b47..b72925f67eb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java @@ -25,13 +25,10 @@ package org.graalvm.compiler.hotspot.amd64.test; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.DataPointerConstant; @@ -52,6 +49,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; @@ -59,6 +62,7 @@ import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -163,13 +167,20 @@ public class StubAVXTest extends LIRTest { private static class TestStub extends SnippetStub { - TestStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("testStub", providers, linkage); + TestStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("testStub", options, providers, linkage); } @Snippet static void testStub() { } + + @Override + protected BytecodeProvider getReplacementsBytecodeProvider() { + ReplacementsImpl d = (ReplacementsImpl) providers.getReplacements(); + MetaAccessProvider metaAccess = d.providers.getMetaAccess(); + return new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader()); + } } public static final ForeignCallDescriptor TEST_STUB = new ForeignCallDescriptor("test_stub", void.class); @@ -208,7 +219,7 @@ public class StubAVXTest extends LIRTest { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls(); HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, true, HotSpotForeignCallLinkage.Transition.LEAF_NOFP); - linkage.setCompiledStub(new TestStub(providers, linkage)); + linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage)); runTest("testStub"); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java deleted file mode 100644 index d0d77efd99b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64DeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - registerConfig = new AMD64HotSpotRegisterConfig(target, new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14), config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index d8c5cd6227a..21ebab830cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,17 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64AddressLowering; import org.graalvm.compiler.core.amd64.AMD64AddressNode; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; @@ -46,15 +48,19 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { + private static final DebugCounter counterFoldedUncompressDuringAddressLowering = Debug.counter("FoldedUncompressDuringAddressLowering"); + private final long heapBase; private final Register heapBaseRegister; private final GraalHotSpotVMConfig config; + private final boolean generatePIC; @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public static class HeapBaseNode extends FloatingNode implements LIRLowerable { @@ -75,10 +81,11 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } } - public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister) { - this.heapBase = config.getOopEncoding().base; + public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) { + this.heapBase = config.getOopEncoding().getBase(); this.config = config; - if (heapBase == 0 && !GeneratePIC.getValue()) { + this.generatePIC = GeneratePIC.getValue(options); + if (heapBase == 0 && !generatePIC) { this.heapBaseRegister = null; } else { this.heapBaseRegister = heapBaseRegister; @@ -87,33 +94,42 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { @Override protected boolean improve(AMD64AddressNode addr) { + + boolean result = false; + + while (super.improve(addr)) { + result = true; + } + if (addr.getScale() == Scale.Times1) { - if (addr.getBase() == null && addr.getIndex() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getIndex())) { + if (addr.getIndex() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase())) { + counterFoldedUncompressDuringAddressLowering.increment(); return true; } } - if (addr.getIndex() == null && addr.getBase() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getBase())) { + if (addr.getBase() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex())) { + counterFoldedUncompressDuringAddressLowering.increment(); return true; } } } - return super.improve(addr); + return result; } - private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression) { + private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) { if (compression.getOp() == CompressionOp.Uncompress) { CompressEncoding encoding = compression.getEncoding(); - Scale scale = Scale.fromShift(encoding.shift); + Scale scale = Scale.fromShift(encoding.getShift()); if (scale == null) { return false; } - if (heapBaseRegister != null && encoding.base == heapBase) { - if (!GeneratePIC.getValue() || compression.stamp() instanceof ObjectStamp) { + if (heapBaseRegister != null && encoding.getBase() == heapBase) { + if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) { // With PIC it is only legal to do for oops since the base value may be // different at runtime. ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); @@ -121,21 +137,25 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } else { return false; } - } else if (encoding.base != 0 || (GeneratePIC.getValue() && compression.stamp() instanceof KlassPointerStamp)) { - if (GeneratePIC.getValue()) { - ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); - addr.setBase(base); + } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) { + if (generatePIC) { + if (other == null) { + ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); + addr.setBase(base); + } else { + return false; + } } else { - long disp = addr.getDisplacement() + encoding.base; + long disp = addr.getDisplacement() + encoding.getBase(); if (NumUtil.isInt(disp)) { addr.setDisplacement((int) disp); - addr.setBase(null); + addr.setBase(other); } else { return false; } } } else { - addr.setBase(null); + addr.setBase(other); } addr.setScale(scale); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java index b14f17795be..3e011324fd1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10; @@ -31,7 +32,6 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.Int import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.Variable; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import jdk.vm.ci.meta.Value; @@ -39,7 +39,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathLog(Value input, boolean base10) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathLog(input, base10); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -49,7 +49,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathCos(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathCos(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -59,7 +59,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathSin(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathSin(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -69,7 +69,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathTan(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathTan(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 7cb4b03b27e..ec145953af0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -30,8 +30,6 @@ import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -66,6 +64,8 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -170,7 +170,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } else { asm.decrementq(rsp, frameSize); } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); @@ -208,13 +208,14 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; - boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); + OptionValues options = lir.getOptions(); + boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -223,7 +224,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } @@ -268,7 +269,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { if (config.useCompressedClassPointers) { Register register = r10; AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS); } else { @@ -289,7 +290,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { asm.bind(verifiedEntry); crb.recordMark(config.MARKID_VERIFIED_ENTRY); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { // Check for method state HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { @@ -334,13 +335,13 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index 96f90d0d7fe..afe0540c26c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static jdk.vm.ci.common.InitTimer.timer; - +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import java.util.ArrayList; import java.util.List; @@ -52,6 +51,7 @@ import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins; @@ -90,6 +90,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotBackend host) { assert host == null; + OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); HotSpotProviders providers; @@ -138,14 +139,14 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements); + suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, snippetReflection, wordTypes, @@ -156,12 +157,12 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { } } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, + protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AMD64GraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue()); + AMD64GraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options)); return plugins; } @@ -173,8 +174,8 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, @@ -186,8 +187,9 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { * @param replacements */ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, - HotSpotRegistersProvider registers, Replacements replacements) { - return new HotSpotSuitesProvider(new AMD64HotSpotSuitesProvider(compilerConfiguration, plugins), config, runtime, new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister())); + HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) { + return new HotSpotSuitesProvider(new AMD64HotSpotSuitesProvider(compilerConfiguration, plugins), config, runtime, + new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 30c8a7f07ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.amd64.AMD64.rax; -import static jdk.vm.ci.amd64.AMD64.rbp; -import static jdk.vm.ci.amd64.AMD64.rip; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Alive(REG) AllocatableValue senderFp; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotEnterUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, - AllocatableValue senderSp, AllocatableValue senderFp, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - final int totalFrameSize = frameMap.totalFrameSize(); - - // Push return address. - masm.push(asRegister(framePc)); - - // Push base pointer. - masm.push(asRegister(senderFp)); - masm.movq(rbp, stackPointerRegister); - - /* - * Allocate a full sized frame. Since return address and base pointer are already in place - * (see above) we allocate two words less. - */ - masm.decrementq(stackPointerRegister, totalFrameSize - 2 * crb.target.wordSize); - - // Save return registers after moving the frame. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize), integerResultRegister); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize), floatResultRegister); - - // Set up last Java values. - masm.movq(new AMD64Address(threadRegister, threadLastJavaSpOffset), stackPointerRegister); - - /* - * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned - * SP. Don't need the precise return PC here, just precise enough to point into this code - * blob. - */ - masm.leaq(rax, new AMD64Address(rip, 0)); - masm.movq(new AMD64Address(threadRegister, threadLastJavaPcOffset), rax); - - // Use BP because the frames look interpreted now. - masm.movq(new AMD64Address(threadRegister, threadLastJavaFpOffset), rbp); - - // Align the stack for the following unpackFrames call. - masm.andq(stackPointerRegister, -(crb.target.stackAlignment)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java index 3f9f2cded39..c681fc2b26e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java @@ -22,21 +22,18 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rdx; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -45,6 +42,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -75,7 +73,7 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -89,24 +87,20 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new AMD64DeoptimizationStub(providers, target, config, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64UncommonTrapStub(providers, target, config, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - link(new AMD64MathStub(ARITHMETIC_LOG_STUB, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_SIN_STUB, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_COS_STUB, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_TAN_STUB, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_EXP_STUB, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_POW_STUB, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index bd87349a2d4..d96b5c3fbb7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -22,29 +22,26 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static jdk.vm.ci.amd64.AMD64.rbp; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static jdk.vm.ci.amd64.AMD64.rbp; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; @@ -63,7 +60,6 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.StandardOp.NoOp; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; @@ -81,6 +77,7 @@ import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -294,34 +291,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp super.emitForeignCallOp(linkage, result, arguments, temps, info); } - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new AMD64HotSpotLeaveCurrentStackFrameOp(saveRegisterOp)); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable)); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable senderFpVariable = load(senderFp); - append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable, - senderSpVariable, senderFpVariable, saveRegisterOp)); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), saveRegisterOp)); - } - /** * @param savedRegisters the registers saved by this operation which may be subject to pruning * @param savedRegisterLocations the slots to which the registers are saved @@ -359,13 +328,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We are saving all registers. - // TODO Save upper half of YMM registers. - return emitSaveAllRegisters(target().arch.getAvailableValueRegisters().toArray(), false); - } - protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } @@ -421,8 +383,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (stub != null) { if (stub.preservesRegisters()) { HotSpotLIRGenerationResult generationResult = getResult(); - assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); - generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save); + LIRFrameState key = currentRuntimeCallInfo; + if (key == null) { + key = LIRFrameState.NO_STATE; + } + assert !generationResult.getCalleeSaveInfo().containsKey(key); + generationResult.getCalleeSaveInfo().put(key, save); emitRestoreRegisters(save); } } @@ -510,38 +476,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitMove(timestamp.getLowResult()); } - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), trapRequest, mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); @@ -621,21 +555,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp LIRInstruction op = getOrInitRescueSlotOp(); // insert dummy instruction into the start block LIR lir = getResult().getLIR(); - List instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); + ArrayList instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); instructions.add(1, op); Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op"); } } - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable, config)); - } - @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { LIRKind inputKind = pointer.getValueKind(LIRKind.class); @@ -649,14 +574,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -677,14 +603,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -697,9 +624,10 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (address.getValueKind().getPlatformKind() == AMD64Kind.DWORD) { CompressEncoding encoding = config.getOopEncoding(); Value uncompressed; - if (encoding.shift <= 3) { + if (encoding.getShift() <= 3) { LIRKind wordKind = LIRKind.unknownReference(target().arch.getWordKind()); - uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.shift), 0); + uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.getShift()), + 0); } else { uncompressed = emitUncompress(address, encoding, false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 40155af38f3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - - // Restore stack pointer. - masm.movq(stackPointerRegister, new AMD64Address(threadRegister, threadLastJavaSpOffset)); - - // Clear last Java frame values. - masm.movslq(new AMD64Address(threadRegister, threadLastJavaSpOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaPcOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaFpOffset), 0); - - // Restore return values. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(integerResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize)); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(floatResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java index 24b11237bda..ae36c40fbdc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java @@ -51,7 +51,7 @@ public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { AMD64Kind kind = (AMD64Kind) result.getPlatformKind(); Register reg = asRegister(result); AMD64Address placeholder = masm.getPlaceholder(-1); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 36292b06fc3..e51d142569e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -27,8 +27,8 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvide import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -43,6 +43,7 @@ import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; @@ -62,10 +63,11 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue() ? new ProbabilisticProfileSnippets.Templates(providers, providers.getCodeCache().getTarget()) : null; - super.initialize(providers, config); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + convertSnippets = new AMD64ConvertSnippets.Templates(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) + ? new ProbabilisticProfileSnippets.Templates(options, providers, providers.getCodeCache().getTarget()) : null; + super.initialize(options, providers, config); } @Override @@ -81,7 +83,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case LOG: return ARITHMETIC_LOG_STUB; @@ -105,7 +107,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case POW: return ARITHMETIC_POW_STUB; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java index 168282ebcbf..a5c75f5958b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java @@ -34,9 +34,9 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; @@ -67,7 +67,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -146,7 +146,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -204,7 +204,7 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.QWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.testq(resReg, resReg); @@ -213,8 +213,8 @@ public class AMD64HotSpotMove { masm.subq(resReg, baseReg); } - if (encoding.shift != 0) { - masm.shrq(resReg, encoding.shift); + if (encoding.hasShift()) { + masm.shrq(resReg, encoding.getShift()); } } } @@ -243,15 +243,15 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.DWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.shift != 0) { - masm.shlq(resReg, encoding.shift); + if (encoding.getShift() != 0) { + masm.shlq(resReg, encoding.getShift()); } - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { if (nonNull) { masm.addq(resReg, asRegister(baseRegister)); } else { - if (encoding.shift == 0) { + if (!encoding.hasShift()) { // if encoding.shift != 0, the flags are already set by the shlq masm.testq(resReg, resReg); } @@ -268,17 +268,17 @@ public class AMD64HotSpotMove { public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { CompressEncoding encoding = config.getKlassEncoding(); masm.movl(register, address); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Decode algorithm is wrong"; - masm.shlq(register, encoding.alignment); + if (encoding.getShift() != 0) { + masm.shlq(register, encoding.getShift()); } - if (GeneratePIC.getValue() || encoding.base != 0) { - if (GeneratePIC.getValue()) { + boolean pic = GeneratePIC.getValue(crb.getOptions()); + if (pic || encoding.hasBase()) { + if (pic) { masm.movq(scratch, masm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); } else { - assert encoding.base != 0; - masm.movq(scratch, encoding.base); + assert encoding.getBase() != 0; + masm.movq(scratch, encoding.getBase()); } masm.addq(register, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java index 893a35263f8..45ea897cd95 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java @@ -40,11 +40,13 @@ public class AMD64HotSpotMoveFactory extends AMD64MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; } else if (c instanceof HotSpotObjectConstant) { return ((HotSpotObjectConstant) c).isCompressed(); + } else if (c instanceof HotSpotMetaspaceConstant) { + return ((HotSpotMetaspaceConstant) c).isCompressed(); } else { return super.canInlineConstant(c); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java index 09a6d98ba9c..b6e0f10fb2a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java @@ -36,13 +36,11 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.amd64.AMD64BreakpointOp; -import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -185,19 +183,6 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Value expected = gen.loadNonConst(operand(x.expectedValue())); - Variable newVal = gen.load(operand(x.newValue())); - assert expected.getValueKind().equals(newVal.getValueKind()); - - RegisterValue raxLocal = AMD64.rax.asValue(expected.getValueKind()); - gen.emitMove(raxLocal, expected); - append(new CompareAndSwapOp((AMD64Kind) expected.getPlatformKind(), raxLocal, getGen().asAddressValue(operand(x.getAddress())), raxLocal, newVal)); - - setResult(x, gen.emitMove(raxLocal)); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java index fd08e39b489..ce49590322e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java @@ -81,8 +81,8 @@ class AMD64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig { }; // @formatter:on - AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 10321188ab0..7a5ee813a89 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.asm.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isInt; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static jdk.vm.ci.amd64.AMD64.rax; @@ -63,7 +63,7 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { super(TYPE); this.state = state; this.config = config; - if (isPollingPageFar(config) || ImmutableCode.getValue()) { + if (isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind())); } else { // Don't waste a register if it's unneeded @@ -87,13 +87,13 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { assert !atReturn || state == null : "state is unneeded at return"; - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(crb.getOptions())) { JavaKind hostWordKind = JavaKind.Long; int alignment = hostWordKind.getBitCount() / Byte.SIZE; JavaConstant pollingPageAddress = JavaConstant.forIntegerKind(hostWordKind, config.safepointPollingAddress); // This move will be patched to load the safepoint page from a data segment // co-located with the immutable code. - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(scratch, asm.getPlaceholder(-1)); } else { asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java index 431d90ca4b9..a8073f1e428 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; public class AMD64HotSpotSuitesProvider extends AMD64SuitesProvider { @@ -36,9 +37,9 @@ public class AMD64HotSpotSuitesProvider extends AMD64SuitesProvider { } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (GraalOptions.DetailedAsserts.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (GraalOptions.DetailedAsserts.getValue(options)) { lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase()); } return lirSuites; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java index 15956d35052..39507dd2b63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.SnippetStub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; @@ -45,8 +46,8 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOpera */ public class AMD64MathStub extends SnippetStub { - public AMD64MathStub(ForeignCallDescriptor descriptor, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetName(descriptor), providers, linkage); + public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetName(descriptor), options, providers, linkage); } private static String snippetName(ForeignCallDescriptor descriptor) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java deleted file mode 100644 index a4ca9d352e4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64UncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - AMD64UncommonTrapStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - RegisterArray allocatable = new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14); - registerConfig = new AMD64HotSpotRegisterConfig(target, allocatable, config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java deleted file mode 100644 index eb8e69b27fc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCDeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java index abe2d0ba2d7..a1b6cdf856b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java @@ -22,13 +22,6 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; @@ -40,10 +33,16 @@ import static jdk.vm.ci.sparc.SPARC.l7; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o7; import static jdk.vm.ci.sparc.SPARC.sp; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import java.util.ArrayList; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -62,11 +61,11 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -92,6 +91,10 @@ import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate; import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -203,7 +206,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int slotSize = 8; for (int i = 0; i < frameSize / slotSize; ++i) { // 0xC1C1C1C1 @@ -235,7 +238,8 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { // On SPARC we always use stack frames. HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + OptionValues options = lir.getOptions(); + CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -245,8 +249,8 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { if (stub != null) { // Even on sparc we need to save floating point registers - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); - Map calleeSaveInfo = gen.getCalleeSaveInfo(); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicMap calleeSaveInfo = gen.getCalleeSaveInfo(); updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap); } assert registerSizePredictionValidator(crb); @@ -421,7 +425,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { * possible. */ private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase block) { - List instructions = l.getLIRforBlock(block); + ArrayList instructions = l.getLIRforBlock(block); if (instructions.size() >= 2) { LIRDependencyAccumulator acc = new LIRDependencyAccumulator(); SPARCDelayedControlTransfer delayedTransfer = null; @@ -497,14 +501,14 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull); + return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { - HashSet callerRegisters = new HashSet<>(calleeRegisters.size()); + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { + EconomicSet callerRegisters = EconomicSet.create(Equivalence.IDENTITY, calleeRegisters.size()); for (Register register : calleeRegisters) { if (l0.number <= register.number && register.number <= l7.number) { // do nothing diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java index 821348a75c3..04491c1f260 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java @@ -102,7 +102,7 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target); + HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target); Plugins plugins = createGraphBuilderPlugins(config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 418ea884fbe..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.STACK_BIAS; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.i1; -import static jdk.vm.ci.sparc.SPARC.i2; -import static jdk.vm.ci.sparc.SPARC.i3; -import static jdk.vm.ci.sparc.SPARC.i4; -import static jdk.vm.ci.sparc.SPARC.l7; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; -import static jdk.vm.ci.sparc.SPARC.o5; -import static jdk.vm.ci.sparc.SPARC.o7; -import static jdk.vm.ci.sparc.SPARC.sp; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.PlatformKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Temp(REG) AllocatableValue scratch; - @Temp(REG) AllocatableValue callerReturnPc; - - SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch, - PlatformKind wordKind) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.scratch = scratch; - callerReturnPc = o7.asValue(LIRKind.value(wordKind)); - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - final int totalFrameSize = crb.frameMap.totalFrameSize(); - Register framePcRegister = asRegister(framePc); - Register senderSpRegister = asRegister(senderSp); - Register scratchRegister = asRegister(scratch); - - // Save final sender SP to O5_savedSP. - masm.mov(senderSpRegister, o5); - - // Load final frame PC. - masm.mov(framePcRegister, asRegister(callerReturnPc)); - - // Allocate a full sized frame. - masm.save(sp, -totalFrameSize, sp); - - masm.mov(i0, o0); - masm.mov(i1, o1); - masm.mov(i2, o2); - masm.mov(i3, o3); - masm.mov(i4, o4); - - // Set up last Java values. - masm.add(sp, STACK_BIAS, scratchRegister); - masm.stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)); - - // Clear last Java PC. - masm.stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)); - - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(thread, l7); - } - - @Override - public boolean leavesRegisterWindow() { - return true; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java index 58a9bbe75c9..f601b3af9c8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java @@ -22,30 +22,27 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; import static jdk.vm.ci.sparc.SPARC.i0; import static jdk.vm.ci.sparc.SPARC.i1; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o1; +import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -69,7 +66,7 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -86,17 +83,12 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java index b6a2b520bc7..436c40d0544 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,51 +22,12 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; -import static jdk.vm.ci.sparc.SPARC.d32; -import static jdk.vm.ci.sparc.SPARC.d34; -import static jdk.vm.ci.sparc.SPARC.d36; -import static jdk.vm.ci.sparc.SPARC.d38; -import static jdk.vm.ci.sparc.SPARC.d40; -import static jdk.vm.ci.sparc.SPARC.d42; -import static jdk.vm.ci.sparc.SPARC.d44; -import static jdk.vm.ci.sparc.SPARC.d46; -import static jdk.vm.ci.sparc.SPARC.d48; -import static jdk.vm.ci.sparc.SPARC.d50; -import static jdk.vm.ci.sparc.SPARC.d52; -import static jdk.vm.ci.sparc.SPARC.d54; -import static jdk.vm.ci.sparc.SPARC.d56; -import static jdk.vm.ci.sparc.SPARC.d58; -import static jdk.vm.ci.sparc.SPARC.d60; -import static jdk.vm.ci.sparc.SPARC.d62; -import static jdk.vm.ci.sparc.SPARC.f0; -import static jdk.vm.ci.sparc.SPARC.f10; -import static jdk.vm.ci.sparc.SPARC.f12; -import static jdk.vm.ci.sparc.SPARC.f14; -import static jdk.vm.ci.sparc.SPARC.f16; -import static jdk.vm.ci.sparc.SPARC.f18; -import static jdk.vm.ci.sparc.SPARC.f2; -import static jdk.vm.ci.sparc.SPARC.f20; -import static jdk.vm.ci.sparc.SPARC.f22; -import static jdk.vm.ci.sparc.SPARC.f24; -import static jdk.vm.ci.sparc.SPARC.f26; -import static jdk.vm.ci.sparc.SPARC.f28; -import static jdk.vm.ci.sparc.SPARC.f30; -import static jdk.vm.ci.sparc.SPARC.f4; -import static jdk.vm.ci.sparc.SPARC.f6; -import static jdk.vm.ci.sparc.SPARC.f8; -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; -import java.util.Map; - +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; @@ -74,7 +35,6 @@ import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.sparc.SPARCArithmeticLIRGenerator; import org.graalvm.compiler.core.sparc.SPARCLIRGenerator; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; @@ -126,7 +86,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp final GraalHotSpotVMConfig config; private HotSpotDebugInfoBuilder debugInfoBuilder; - private LIRFrameState currentRuntimeCallInfo; public SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { this(providers, config, lirGenRes, new ConstantTableBaseProvider()); @@ -196,12 +155,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); } - @Override - protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { - currentRuntimeCallInfo = info; - super.emitForeignCallOp(linkage, result, arguments, temps, info); - } - @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; @@ -280,7 +233,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); SPARCKind memKind = (SPARCKind) kind.getPlatformKind(); @@ -289,6 +242,15 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return emitConditionalMove(memKind, expectedValue, result, Condition.EQ, true, trueValue, falseValue); } + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + Variable result = newVariable(newValue.getValueKind()); + append(new CompareAndSwapOp(result, asAllocatable(address), asAllocatable(expectedValue), asAllocatable(newValue))); + return result; + } + @Override public void emitPrefetchAllocate(Value address) { SPARCAddressValue addr = asAddressValue(address); @@ -349,8 +311,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(WORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -370,8 +332,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(XWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -389,108 +351,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return save; } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We save all registers that were not saved by the save instruction. - // @formatter:off - Register[] savedRegisters = { - // CPU - g1, g3, g4, g5, - // FPU, use only every second register as doubles are stored anyways - f0, /*f1, */ f2, /*f3, */ f4, /*f5, */ f6, /*f7, */ - f8, /*f9, */ f10, /*f11,*/ f12, /*f13,*/ f14, /*f15,*/ - f16, /*f17,*/ f18, /*f19,*/ f20, /*f21,*/ f22, /*f23,*/ - f24, /*f25,*/ f26, /*f27,*/ f28, /*f29,*/ f30, /*f31 */ - d32, d34, d36, d38, - d40, d42, d44, d46, - d48, d50, d52, d54, - d56, d58, d60, d62 - }; - // @formatter:on - AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; - for (int i = 0; i < savedRegisters.length; i++) { - PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); - VirtualStackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); - savedRegisterLocations[i] = spillSlot; - } - return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); - } - - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new SPARCHotSpotLeaveCurrentStackFrameOp()); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable scratchVariable = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable, - target().arch.getWordKind())); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); - } - - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); - } - - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), trapRequest, mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitNullCheck(Value address, LIRFrameState state) { PlatformKind kind = address.getPlatformKind(); @@ -527,7 +387,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 99f3826f361..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.l7; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; -import org.graalvm.compiler.lir.sparc.SPARCSaveRegistersOp; - -import jdk.vm.ci.code.Register; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadJavaFrameAnchorFlagsOffset; - - SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(l7, thread); - - SPARCAddress lastJavaPc = new SPARCAddress(thread, threadLastJavaPcOffset); - - // We borrow the threads lastJavaPC to transfer the value from float to i0 - masm.stdf(SPARCSaveRegistersOp.RETURN_REGISTER_STORAGE, lastJavaPc); - masm.ldx(lastJavaPc, i0); - - // Clear last Java frame values. - masm.stx(g0, lastJavaPc); - masm.stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)); - masm.stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java index 7b869c46b9d..d6f9bdffaea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -146,7 +146,7 @@ public class SPARCHotSpotMove { public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { Register inputRegister = asRegister(input); Register resReg = asRegister(result); - if (encoding.base != 0) { + if (encoding.hasBase()) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.cmp(inputRegister, baseReg); @@ -155,11 +155,11 @@ public class SPARCHotSpotMove { } else { masm.sub(inputRegister, baseReg, resReg); } - if (encoding.shift != 0) { - masm.srlx(resReg, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); } } else { - masm.srlx(inputRegister, encoding.shift, resReg); + masm.srlx(inputRegister, encoding.getShift(), resReg); } } } @@ -189,14 +189,14 @@ public class SPARCHotSpotMove { Register inputRegister = asRegister(input); Register resReg = asRegister(result); Register secondaryInput; - if (encoding.shift != 0) { - masm.sll(inputRegister, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.sll(inputRegister, encoding.getShift(), resReg); secondaryInput = resReg; } else { secondaryInput = inputRegister; } - if (encoding.base != 0) { + if (encoding.hasBase()) { if (nonNull) { masm.add(secondaryInput, asRegister(baseRegister), resReg); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java index 80545e36944..0be5caf20c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java @@ -32,10 +32,10 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { @@ -44,10 +44,10 @@ public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java index e16abf52bd2..8be13b7e173 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java @@ -36,14 +36,12 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp; -import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; @@ -90,18 +88,6 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - assert cmpValue.getValueKind().equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - append(new CompareAndSwapOp(result, address, cmpValue, newValue)); - setResult(x, result); - } - @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java index 85fd975a91d..0265525c17e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java @@ -112,8 +112,8 @@ public class SPARCHotSpotRegisterAllocationConfig extends RegisterAllocationConf }; // @formatter:on - public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java index fedd4a13673..f4e2c741782 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.INSTRUCTION_SIZE; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN; import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; @@ -40,6 +40,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.SwitchStrategy; +import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.sparc.SPARCControlFlow; import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer; @@ -54,7 +55,7 @@ import jdk.vm.ci.sparc.SPARC.CPUFeature; final class SPARCHotSpotStrategySwitchOp extends SPARCControlFlow.StrategySwitchOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotStrategySwitchOp.class); - SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, AllocatableValue key, Variable scratch) { super(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java deleted file mode 100644 index 3ef27516389..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCUncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - SPARCUncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java index ec528b1c6f9..a08edd079c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java @@ -22,39 +22,29 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.phases.tiers.SuitesProvider; -import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * use @@ -74,14 +64,19 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return AheadOfTimeCompilationTest.STATICFINALOBJECT; } + @Before + public void setUp() { + // Ignore on SPARC + Assume.assumeFalse("skipping on AArch64", getTarget().arch instanceof AArch64); + } + @Test public void testStaticFinalObjectAOT() { StructuredGraph result = compile("getStaticFinalObject", true); assertDeepEquals(1, getConstantNodes(result).count()); Stamp constantStamp = getConstantNodes(result).first().stamp(); Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -89,7 +84,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { StructuredGraph result = compile("getStaticFinalObject", false); assertDeepEquals(1, getConstantNodes(result).count()); assertDeepEquals(JavaKind.Object, getConstantNodes(result).first().getStackKind()); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -106,8 +100,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(AheadOfTimeCompilationTest.class); assertDeepEquals(type.klass(), filter.first().asConstant()); - assertDeepEquals(1, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(1, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -119,7 +112,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), AheadOfTimeCompilationTest.class); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -135,8 +127,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { Stamp constantStamp = filter.first().stamp(); Assert.assertTrue(constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -147,7 +138,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), Integer.TYPE); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -182,17 +172,18 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return Boolean.valueOf(true); } - @Ignore("ImmutableCode override may not work reliably in non-hosted mode") @Test public void testBoxedBooleanAOT() { StructuredGraph result = compile("getBoxedBoolean", true); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(1, result.getNodes(PiNode.TYPE).count()); + assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); + assertDeepEquals(0, result.getNodes(PiNode.TYPE).count()); assertDeepEquals(1, getConstantNodes(result).count()); ConstantNode constant = getConstantNodes(result).first(); - assertDeepEquals(JavaKind.Long, constant.getStackKind()); - assertDeepEquals(((HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(Boolean.class)).klass(), constant.asConstant()); + assertDeepEquals(JavaKind.Object, constant.getStackKind()); + + JavaConstant c = constant.asJavaConstant(); + Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE); } @Test @@ -210,17 +201,9 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph compile(String test, boolean compileAOT) { - try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { - StructuredGraph graph = parseEager(test, AllowAssumptions.YES); - ResolvedJavaMethod method = graph.method(); - // create suites everytime, as we modify options for the compiler - SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); - final Suites suitesLocal = suitesProvider.getDefaultSuites(); - final LIRSuites lirSuitesLocal = suitesProvider.getDefaultLIRSuites(); - final CompilationResult compResult = compileGraph(graph, method, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - suitesLocal, lirSuitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); - addMethod(method, compResult); - return graph; - } + OptionValues options = new OptionValues(getInitialOptions(), ImmutableCode, compileAOT); + StructuredGraph graph = parseEager(test, AllowAssumptions.YES, options); + compile(graph.method(), graph); + return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java index e3ea0bc743b..952dd2bc08e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java @@ -26,9 +26,6 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets; @@ -36,6 +33,9 @@ import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.JavaMethod; @@ -47,10 +47,10 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g) { + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g, boolean forceCompile, boolean installAsDefault, OptionValues options) { StructuredGraph graph = g == null ? parseForCompile(method) : g; int nodeCount = graph.getNodeCount(); - InstalledCode result = super.getCode(method, graph); + InstalledCode result = super.getCode(method, graph, forceCompile, installAsDefault, options); boolean graphWasProcessed = nodeCount != graph.getNodeCount(); if (graphWasProcessed) { if (mustIntrinsify) { @@ -160,7 +160,7 @@ public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { } /** - * Tests {@link ArrayCopySnippets#checkcastArraycopyWork(Object, int, Object, int, int)}. + * Tests {@link ArrayCopySnippets#checkcastArraycopyWork}. */ @Test public void testArrayStoreException() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index 42d4dd453c4..cf992114c54 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -47,6 +47,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.test.GraalTest; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.hotspot.VMIntrinsicMethod; @@ -75,7 +76,7 @@ public class CheckGraalIntrinsics extends GraalTest { return false; } - private static ResolvedJavaMethod findMethod(Set methods, VMIntrinsicMethod intrinsic) { + private static ResolvedJavaMethod findMethod(EconomicSet methods, VMIntrinsicMethod intrinsic) { for (ResolvedJavaMethod method : methods) { if (match(method, intrinsic)) { return method; @@ -434,7 +435,7 @@ public class CheckGraalIntrinsics extends GraalTest { impl.put(method, plugin); } - Set methods = invocationPlugins.getMethods(); + EconomicSet methods = invocationPlugins.getMethods(); HotSpotVMConfigStore store = rt.getVMConfig().getStore(); List intrinsics = store.getIntrinsics(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java index 481a3387af5..5dabc1d0b04 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java @@ -23,13 +23,13 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; - -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.hotspot.CompileTheWorld; -import org.graalvm.compiler.hotspot.CompileTheWorld.Config; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -41,11 +41,13 @@ public class CompileTheWorldTest extends GraalCompilerTest { @Test public void testJDK() throws Throwable { - boolean originalSetting = ExitVMOnException.getValue(); + boolean originalSetting = ExitVMOnException.getValue(getInitialOptions()); // Compile a couple classes in rt.jar HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base"); - new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, new Config("Inline=false"), 1, 5, null, null, true).compile(); - assert ExitVMOnException.getValue() == originalSetting; + OptionValues initialOptions = getInitialOptions(); + EconomicMap, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false"); + new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, true, initialOptions, compilationOptions).compile(); + assert ExitVMOnException.getValue(initialOptions) == originalSetting; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java index 2585d36f861..8bc3a79a0fc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java @@ -38,13 +38,17 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; import jdk.vm.ci.meta.ResolvedJavaMethod; -public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements Opcodes { +public class ConstantPoolSubstitutionsTests extends GraalCompilerTest { + + public ConstantPoolSubstitutionsTests() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { @@ -186,7 +190,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); @@ -194,131 +198,134 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements } } - // @formatter:off - /* - static class ConstantPoolTest { - public static int getSize(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getSize(); + static class Gen implements Opcodes { + // @formatter:off + /* + static class ConstantPoolTest { + public static int getSize(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getSize(); + } + + public static int getIntAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getIntAt(0); + } + + public static long getLongAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getLongAt(0); + } + + public static float getFloatAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getFloatAt(0); + } + + public static double getDoubleAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getDoubleAt(0); + } + + public static String getUTF8At(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getUTF8At(0); + } } + */ + // @formatter:on - public static int getIntAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getIntAt(0); + static byte[] generateClass() { + + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); + cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", + ACC_STATIC); + String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; + + mv = cw.visitMethod(0, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); + mv.visitInsn(LRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); + mv.visitInsn(FRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); + mv.visitInsn(DRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + cw.visitEnd(); + + return cw.toByteArray(); } - - public static long getLongAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getLongAt(0); - } - - public static float getFloatAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getFloatAt(0); - } - - public static double getDoubleAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getDoubleAt(0); - } - - public static String getUTF8At(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getUTF8At(0); - } - } - */ - // @formatter:on - private static byte[] generateClass() { - - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - - cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); - cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", - ACC_STATIC); - String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; - - mv = cw.visitMethod(0, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(1, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); - mv.visitInsn(LRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); - mv.visitInsn(FRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); - mv.visitInsn(DRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - cw.visitEnd(); - - return cw.toByteArray(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java index 445c48e2482..b7884847d16 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java @@ -25,8 +25,7 @@ package org.graalvm.compiler.hotspot.test; import org.junit.Assume; import org.junit.Test; - -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java index b1099a426e7..44dbfe55e67 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java @@ -25,7 +25,9 @@ package org.graalvm.compiler.hotspot.test; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -35,8 +37,8 @@ public class ExplicitExceptionTest extends GraalCompilerTest { private int expectedForeignCallCount; @Override - protected InstalledCode getCode(ResolvedJavaMethod method) { - InstalledCode installedCode = super.getCode(method); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + InstalledCode installedCode = super.getCode(method, graph, forceCompile, installAsDefault, options); assertDeepEquals(expectedForeignCallCount, lastCompiledGraph.getNodes().filter(ForeignCallNode.class).count()); return installedCode; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java index 5466a638e79..4834e51cfb3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java @@ -22,35 +22,652 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Ignore; -import org.junit.Test; +import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Test on-stack-replacement with locks. */ public class GraalOSRLockTest extends GraalOSRTestBase { - @Ignore("OSR with locks not supported") - @Test - public void testOSR() { - testOSR("test"); + private static boolean TestInSeparateThread = false; + + // testing only + public static boolean isMonitorLockHeld(Object o) { + return isMonitorLockHeldByThread(o, null); } - static int limit = 10000; + public static boolean isMonitorLockHeldByThread(Object o, Thread t) { + int oihc = System.identityHashCode(o); + ThreadMXBean tmxbean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] tinfos = tmxbean.dumpAllThreads(true, false); - private static Object lock = new Object(); - - public static ReturnValue test() { - synchronized (lock) { - for (int i = 0; i < limit * limit; i++) { - GraalDirectives.blackhole(i); - if (GraalDirectives.inCompiledCode()) { - return ReturnValue.SUCCESS; + for (ThreadInfo ti : tinfos) { + if (!(t != null && t.getId() != ti.getThreadId())) { + for (MonitorInfo mi : ti.getLockedMonitors()) { + if (mi.getIdentityHashCode() == oihc) { + return true; + } } } - return ReturnValue.FAILURE; + } + return false; + } + + protected static void run(Runnable r) { + if (TestInSeparateThread) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + }); + t.start(); + try { + t.join(); + } catch (Throwable t1) { + throw new GraalError(t1); + } + } else { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + } + + private static boolean wasLocked() { + return isMonitorLockHeld(lock) || isMonitorLockHeld(lock1); + } + + protected static EconomicMap, Object> osrLockNoDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.DeoptAfterOSR, false); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + protected static EconomicMap, Object> osrLockDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + public static int SideEffectI; + + private static void lockOnObject(Object o, String msg) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + synchronized (o) { + SideEffectI = 1; + } + } + }); + t.start(); + try { + t.join(1000); + } catch (InterruptedException e) { + Assert.fail("Object " + msg + " was locked"); + } + } + + private static void beforeOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + } + + private static void afterOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + } + + @BeforeClass + public static void init() { + DebugEnvironment.ensureInitialized(getInitialOptions()); + } + + // @Test + @SuppressWarnings("try") + public void testLockOSROuterImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterLockImmediateDeoptAfter"); + }); + } + + static class A { + + } + + static class B { + @SuppressWarnings("unused") + B(A a) { + + } + } + + HashMap> listeners = new HashMap<>(); + + public synchronized ReturnValue synchronizedSnippet() { + /* + * Test method for which liveness would conclude the original object is no longer alive + * although it is. + */ + Collection> allListeners = listeners.values(); + for (HashSet group : allListeners) { + GraalDirectives.blackhole(group); + } + return ReturnValue.SUCCESS; + } + + @Test + @SuppressWarnings("try") + public void testSynchronizedSnippet() { + GraalOSRLockTest instance = new GraalOSRLockTest(); + // enough entries to trigger OSR + for (int i = 0; i < 100000; i++) { + instance.listeners.put("hello" + i, null); + } + testOSR(getInitialOptions(), "synchronizedSnippet", instance); + Assert.assertFalse(isMonitorLockHeld(instance)); + } + + @Test + @SuppressWarnings("try") + public void testOSRTrivialLoop() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + try { + testOSR(options, "testReduceOSRTrivialLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterInnerLockImmediateDeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1CompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthDeopt() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1DeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod0() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod1"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod1() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod2"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethodSubsequentLock() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterLockCompileRestOfMethodSubsequentLock"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerSameLockCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerSameLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursive() { + run(() -> { + // call it + testRecursiveLockingLeaf(); + ResolvedJavaMethod leaf = getResolvedJavaMethod("testRecursiveLockingLeaf"); + // profile it + leaf.reprofile(); + testRecursiveLockingLeaf(); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + compile(options, leaf, -1); + testOSR(options, "testRecursiveLockingRoot"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursiveLeafOSR() { + run(() -> { + testRecursiveRootNoOSR(); + ResolvedJavaMethod root = getResolvedJavaMethod("testRecursiveRootNoOSR"); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + compile(options, root, -1); + testOSR(options, "testRecursiveLeafOSR"); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + // call the root to call into the leaf and enter the osr-ed code + testRecursiveRootNoOSR(); + + }); + } + + protected static int limit = 10000; + protected static Object lock = new Object(); + protected static Object lock1 = new Object(); + private static final boolean LOG = false; + + static { + // force identity hash code for easy displaced mark identification + int h1 = System.identityHashCode(lock); + int h2 = System.identityHashCode(lock1); + if (LOG) { + TTY.println("Forcing a system identity hashcode on lock object " + h1); + TTY.println("Forcing a system identity hashcode on lock1 object " + h2); + } + } + + public static ReturnValue testReduceOSRTrivialLoop() { + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (GraalDirectives.inCompiledCode()) { + return ReturnValue.SUCCESS; + } + } + return ReturnValue.FAILURE; + } + + public static ReturnValue testOuterLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not be part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + return ret; + } + } + + public static ReturnValue testOuterLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + System.gc(); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1CompileRestOfMethod() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } else { + // lock 1 must be free + if (isMonitorLockHeld(lock1)) { + throw new Error("Lock 1 must have been released already"); + } + + // lock 2 must still be locked and cannot be acquired by another thread + if (!isMonitorLockHeldByThread(lock, Thread.currentThread())) { + throw new Error("Lock must not have been released already"); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1DeoptAfter() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not part of compiled code"); + } + } + } + return ret; + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod1() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod2() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingRoot() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + testRecursiveLockingLeaf(); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingLeaf() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + } + return ret; + } + } + + public static ReturnValue testRecursiveRootNoOSR() { + // testing the order of the lock releasing + final Object l = lock; + synchronized (l) { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < 5; i++) { + if (GraalDirectives.inCompiledCode()) { + ret = testRecursiveLeafOSR(); + } + GraalDirectives.controlFlowAnchor(); + if (ret == ReturnValue.FAILURE) { + return ret; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + public static ReturnValue testRecursiveLeafOSR() { + ReturnValue ret = ReturnValue.FAILURE; + // lock is already locked by the caller + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + // test cases for optimizations + public static ReturnValue testOuterLockCompileRestOfMethodSubsequentLock() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + synchronized (monitor) { + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + } + return ret; + + } + + public static ReturnValue testOuterInnerSameLockCompileRestOfMethod() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (monitor) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java index 3ae96088676..a978dbf4bac 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Assert; +import org.junit.Test; /** * Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is @@ -33,13 +33,29 @@ import org.graalvm.compiler.api.directives.GraalDirectives; public class GraalOSRTest extends GraalOSRTestBase { @Test - public void testOSR() { - testOSR("test"); + public void testOSR01() { + try { + testOSR(getInitialOptions(), "testReduceLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + } + + @Test + public void testOSR02() { + testOSR(getInitialOptions(), "testSequentialLoop"); + } + + @Test + public void testOSR03() { + testOSR(getInitialOptions(), "testNonReduceLoop"); } static int limit = 10000; - public static ReturnValue test() { + public static int sideEffect; + + public static ReturnValue testReduceLoop() { for (int i = 0; i < limit * limit; i++) { GraalDirectives.blackhole(i); if (GraalDirectives.inCompiledCode()) { @@ -49,4 +65,38 @@ public class GraalOSRTest extends GraalOSRTestBase { return ReturnValue.FAILURE; } + public static ReturnValue testSequentialLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 7 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + if (sideEffect == 123) { + return ReturnValue.SIDE; + } + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + + public static ReturnValue testNonReduceLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java index 9742ebd1e1d..3079cbacf9f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java @@ -23,19 +23,23 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Assert; +import java.util.Arrays; import org.graalvm.compiler.bytecode.Bytecode; +import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.java.BciBlockMapping; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -47,25 +51,29 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class GraalOSRTestBase extends GraalCompilerTest { - protected void testOSR(String methodName) { - ResolvedJavaMethod method = getResolvedJavaMethod(methodName); - testOSR(method); + protected void testOSR(OptionValues options, String methodName) { + testOSR(options, methodName, null); } - protected void testOSR(ResolvedJavaMethod method) { + protected void testOSR(OptionValues options, String methodName, Object receiver, Object... args) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + testOSR(options, method, receiver, args); + } + + protected void testOSR(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { // invalidate any existing compiled code method.reprofile(); - compileOSR(method); - Result result = executeExpected(method, null); + compileOSR(options, method); + Result result = executeExpected(method, receiver, args); checkResult(result); } - private static void compile(ResolvedJavaMethod method, int bci) { + protected static void compile(OptionValues options, ResolvedJavaMethod method, int bci) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); long jvmciEnv = 0L; HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, true); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, options); HotSpotCompilationRequestResult result = task.runCompilation(); if (result.getFailure() != null) { throw new GraalError(result.getFailureMessage()); @@ -79,19 +87,24 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { private static int getBackedgeBCI(ResolvedJavaMethod method) { Bytecode code = new ResolvedJavaMethodBytecode(method); BytecodeStream stream = new BytecodeStream(code.getCode()); - BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code); - assert bciBlockMapping.getLoopCount() == 1 : "Expected exactly one loop " + method; + BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, getInitialOptions()); for (BciBlock block : bciBlockMapping.getBlocks()) { - int bci = block.startBci; - for (BciBlock succ : block.getSuccessors()) { - int succBci = succ.startBci; - if (succBci < bci) { - // back edge - return succBci; + if (block.startBci != -1) { + int bci = block.startBci; + for (BciBlock succ : block.getSuccessors()) { + if (succ.startBci != -1) { + int succBci = succ.startBci; + if (succBci < bci) { + // back edge + return succBci; + } + } } } } + TTY.println("Cannot find loop back edge with bytecode loops at:%s", Arrays.toString(bciBlockMapping.getLoopHeaders())); + TTY.println(new BytecodeDisassembler().disassemble(code)); return -1; } @@ -102,17 +115,20 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { Assert.assertEquals(ReturnValue.SUCCESS, result.returnValue); } - private void compileOSR(ResolvedJavaMethod method) { + private void compileOSR(OptionValues options, ResolvedJavaMethod method) { + // ensure eager resolving + parseEager(method, AllowAssumptions.YES, options); int bci = getBackedgeBCI(method); assert bci != -1; // ensure eager resolving - parseEager(method, AllowAssumptions.YES); - compile(method, bci); + parseEager(method, AllowAssumptions.YES, options); + compile(options, method, bci); } protected enum ReturnValue { SUCCESS, - FAILURE + FAILURE, + SIDE } public GraalOSRTestBase() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java index 1851b2619ea..acf2668f571 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java @@ -54,9 +54,9 @@ public abstract class HotSpotGraalCompilerTest extends GraalCompilerTest { HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); HotSpotProviders providers = rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId, getInitialOptions()); if (graph != null) { - return getCode(method, graph, true, true); + return getCode(method, graph, true, true, graph.getOptions()); } return null; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java index fe000286b9b..384f84886ee 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Test; import org.graalvm.compiler.graph.Node; @@ -40,7 +38,7 @@ public class HotSpotNodeSubstitutionsTest extends MethodSubstitutionTest { @Test public void test() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); test("getNodeClass", ConstantNode.forInt(42, graph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java index 549a69b238d..1265cd91f7f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java @@ -36,7 +36,7 @@ import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; - +import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; @@ -52,18 +52,24 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class}; private static final Method createFieldMethod; + private static final Field indexField; static { - Method ret = null; + Method m = null; + Field f = null; try { Class typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl"); - ret = typeImpl.getDeclaredMethod("createField", String.class, JavaType.class, long.class, int.class); - ret.setAccessible(true); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - e.printStackTrace(); + m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class); + Util.setAccessible(m, true); + Class fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl"); + f = fieldImpl.getDeclaredField("index"); + Util.setAccessible(f, true); + } catch (Exception e) { + throw new AssertionError(e); } - createFieldMethod = ret; + createFieldMethod = m; + indexField = f; } /** @@ -96,21 +102,22 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { /** * Tests that {@code HotSpotResolvedObjectType#createField(String, JavaType, long, int)} always - * returns the same object for an internal field. + * returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an internal + * field. * * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @Test - public void testCachingForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Assert.assertTrue("HotSpotResolvedObjectTypeImpl.createField method not found", createFieldMethod != null); + public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { for (Class c : classesWithInternalFields) { HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(c); for (ResolvedJavaField field : type.getInstanceFields(false)) { if (field.isInternal()) { HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field; - ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getName(), expected.getType(), expected.offset(), expected.getModifiers()); + int index = indexField.getInt(expected); + ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.offset(), expected.getModifiers(), index); Assert.assertEquals(expected, actual); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java index 9d9e1598bec..3717e9dcc14 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java @@ -24,15 +24,15 @@ package org.graalvm.compiler.hotspot.test; import static java.lang.reflect.Modifier.isStatic; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -76,8 +76,8 @@ public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java index 57c9776498d..15a5622a394 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java @@ -30,8 +30,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.JavaKind; @@ -58,10 +57,8 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope s = OptionValue.override(GraalOptions.ImmutableCode, true)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, GraalOptions.ImmutableCode, true)); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java index f12b0ba0a4e..82968d701ee 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java @@ -26,9 +26,7 @@ import static org.graalvm.compiler.debug.internal.MemUseTrackerImpl.getCurrentTh import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.AllocSpy; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.CompileTheWorld; import org.graalvm.compiler.hotspot.CompileTheWorldOptions; @@ -125,9 +123,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { Graal.getRuntime(); // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(System.out); - } + DebugEnvironment.ensureInitialized(getInitialOptions()); new MemoryUsageBenchmark().run(); } @@ -144,7 +140,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); task.runCompilation(); } } @@ -161,7 +157,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { try (AllocSpy as = AllocSpy.open(methodName)) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); task.runCompilation(); } } @@ -185,9 +181,9 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { public void run() { compileAndTime("simple"); compileAndTime("complex"); - if (CompileTheWorldOptions.CompileTheWorldClasspath.getValue() != CompileTheWorld.SUN_BOOT_CLASS_PATH) { + if (CompileTheWorldOptions.CompileTheWorldClasspath.getValue(getInitialOptions()) != CompileTheWorld.SUN_BOOT_CLASS_PATH) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); - CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler()); + CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), getInitialOptions()); try { ctw.compile(); } catch (Throwable e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java index 3185b44d826..b724319bffa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java @@ -22,13 +22,11 @@ */ package org.graalvm.compiler.hotspot.test; -import java.util.List; -import java.util.Set; +import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import org.junit.Test; +import java.util.List; import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -39,6 +37,8 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.util.EconomicSet; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.hotspot.VMIntrinsicMethod; @@ -62,7 +62,7 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { return false; } - private static ResolvedJavaMethod findMethod(Set methods, VMIntrinsicMethod intrinsic) { + private static ResolvedJavaMethod findMethod(EconomicSet methods, VMIntrinsicMethod intrinsic) { for (ResolvedJavaMethod method : methods) { if (match(method, intrinsic)) { return method; @@ -80,7 +80,7 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins(); InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins(); - Set pluginMethods = invocationPlugins.getMethods(); + EconomicSet pluginMethods = invocationPlugins.getMethods(); HotSpotVMConfigStore store = rt.getVMConfig().getStore(); List intrinsics = store.getIntrinsics(); for (VMIntrinsicMethod intrinsic : intrinsics) { @@ -88,7 +88,7 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { if (method != null) { InvocationPlugin plugin = invocationPlugins.lookupInvocation(method); if (plugin instanceof MethodSubstitutionPlugin && !method.isNative()) { - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, CompilationIdentifier.INVALID_COMPILATION_ID); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID, getInitialOptions()); getCode(method, graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java index ce367b0831e..81f0e73219e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.hotspot.test; import java.util.List; -import java.util.Map; - import org.junit.Assert; import org.junit.Test; @@ -66,6 +64,7 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.meta.ResolvedJavaField; @@ -306,7 +305,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { test("test6Snippet", 5, new int[]{1, 2}); } - @Test(expected = AssertionError.class) + @Test public void test23() { test("test6Snippet", 5, new int[]{3}); } @@ -712,7 +711,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { } @Override - protected Map processLoop(LoopBeginNode loop, Boolean initialState) { + protected EconomicMap processLoop(LoopBeginNode loop, Boolean initialState) { return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; } @@ -729,7 +728,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { DebugConfig debugConfig = DebugScope.getConfig(); DebugConfig fixedConfig = debugConfig == null ? null - : Debug.fixedConfig(0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); + : Debug.fixedConfig(debugConfig.getOptions(), 0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase(config).apply(graph); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java index 3a93d463936..cec7868e3c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import org.graalvm.compiler.core.common.CompressEncoding; + import jdk.vm.ci.hotspot.HotSpotVMConfigStore; public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { @@ -30,11 +32,15 @@ public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) { super(store); - // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift. + // AOT captures VM settings during compilation. For compressed oops this + // presents a problem for the case when the VM selects a zero-shift mode + // (i.e., when the heap is less than 4G). Compiling an AOT binary with + // zero-shift limits its usability. As such we force the shift to be + // always equal to alignment to avoid emitting zero-shift AOT code. CompressEncoding vmOopEncoding = super.getOopEncoding(); - aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment); + aotOopEncoding = new CompressEncoding(vmOopEncoding.getBase(), logMinObjAlignment()); CompressEncoding vmKlassEncoding = super.getKlassEncoding(); - aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment); + aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), logKlassAlignment); assert check(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java index 7e4ac5fe897..2fc58b3e698 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; -import static org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory.GRAAL_OPTION_PROPERTY_PREFIX; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; import java.util.Arrays; import java.util.HashMap; @@ -32,8 +32,9 @@ import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CompilationRequest; @@ -58,9 +59,9 @@ final class BootstrapWatchDog extends Thread { // @formatter:off @Option(help = "Ratio of the maximum compilation rate below which the bootstrap compilation rate must not fall " + "(0 or less disables monitoring).", type = OptionType.Debug) - public static final OptionValue BootstrapWatchDogCriticalRateRatio = new OptionValue<>(0.25D); + public static final OptionKey BootstrapWatchDogCriticalRateRatio = new OptionKey<>(0.25D); @Option(help = "Maximum time in minutes to spend bootstrapping (0 to disable this limit).", type = OptionType.Debug) - public static final OptionValue BootstrapTimeout = new OptionValue<>(15D); + public static final OptionKey BootstrapTimeout = new OptionKey<>(15D); // @formatter:on } @@ -88,13 +89,18 @@ final class BootstrapWatchDog extends Thread { * {@code null}. */ static BootstrapWatchDog maybeCreate(HotSpotGraalRuntimeProvider graalRuntime) { - return MAX_RATE_DECREASE <= 0.0D && TIMEOUT == 0 ? null : new BootstrapWatchDog(graalRuntime); + OptionValues options = graalRuntime.getOptions(); + int timeout = (int) (Options.BootstrapTimeout.getValue(options) * 60); + double maxRateDecrease = Options.BootstrapWatchDogCriticalRateRatio.getValue(options); + return maxRateDecrease <= 0.0D && timeout == 0 ? null : new BootstrapWatchDog(graalRuntime, timeout, maxRateDecrease); } - private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime) { + private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime, int timeout, double maxRateDecrease) { this.setName(getClass().getSimpleName()); this.start(); this.graalRuntime = graalRuntime; + this.timeout = timeout; + this.maxRateDecrease = maxRateDecrease; } /** @@ -115,13 +121,13 @@ final class BootstrapWatchDog extends Thread { /** * Time in seconds before stopping a bootstrap. */ - private static final int TIMEOUT = (int) (Options.BootstrapTimeout.getValue() * 60); + private final int timeout; /** * The watch dog {@link #hitCriticalCompilationRateOrTimeout() hits} a critical compilation rate * if the current compilation rate falls below this ratio of the maximum compilation rate. */ - private static final double MAX_RATE_DECREASE = Options.BootstrapWatchDogCriticalRateRatio.getValue(); + private final double maxRateDecrease; @Override public void run() { @@ -142,16 +148,16 @@ final class BootstrapWatchDog extends Thread { } if (rate > maxRate) { maxRate = rate; - } else if (rate < (maxRate * MAX_RATE_DECREASE)) { + } else if (rate < (maxRate * maxRateDecrease)) { TTY.printf("%nAfter %.2f seconds bootstrapping, compilation rate is %.2f compilations per second " + - "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, MAX_RATE_DECREASE, maxRate); + "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, maxRateDecrease, maxRate); TTY.printf("To enable monitoring of long running individual compilations, re-run with -D%s%s=%.2f%n", GRAAL_OPTION_PROPERTY_PREFIX, CompilationWatchDog.Options.CompilationWatchDogStartDelay.getName(), seconds(elapsed) - 5); hitCriticalRateOrTimeout = true; return; } - if (elapsed > TIMEOUT * 1000) { + if (elapsed > timeout * 1000) { if (requestsAtTimeout == null) { requestsAtTimeout = snapshotRequests(); stacksAtTimeout = new HashMap<>(); @@ -205,7 +211,7 @@ final class BootstrapWatchDog extends Thread { } /** - * Queries whether a critically low compilation rate or {@link #TIMEOUT} occurred. + * Queries whether a critically low compilation rate or {@link #timeout} occurred. */ boolean hitCriticalCompilationRateOrTimeout() { return hitCriticalRateOrTimeout; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java index e5f0f4ecc4c..824641be1b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.str; - import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -35,9 +34,8 @@ import java.util.TreeSet; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; - +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -47,12 +45,15 @@ class CompilationCounters { // @formatter:off @Option(help = "The number of compilations allowed for any method before " + "the VM exits (a value of 0 means there is no limit).", type = OptionType.Debug) - public static final OptionValue CompilationCountLimit = new StableOptionValue<>(0); + public static final OptionKey CompilationCountLimit = new OptionKey<>(0); // @formatter:on } - CompilationCounters() { + private final OptionValues options; + + CompilationCounters(OptionValues options) { TTY.println("Warning: Compilation counters enabled, excessive recompilation of a method will cause a failure!"); + this.options = options; } private final Map counters = new HashMap<>(); @@ -68,16 +69,16 @@ class CompilationCounters { Integer val = counters.get(method); val = val != null ? val + 1 : 1; counters.put(method, val); - if (val > Options.CompilationCountLimit.getValue()) { + if (val > Options.CompilationCountLimit.getValue(options)) { TTY.printf("Error. Method %s was compiled too many times. Number of compilations: %d\n", fmt(method), - CompilationCounters.Options.CompilationCountLimit.getValue()); + CompilationCounters.Options.CompilationCountLimit.getValue(options)); TTY.println("==================================== High compilation counters ===================================="); SortedSet> sortedCounters = new TreeSet<>(new CounterComparator()); for (Map.Entry e : counters.entrySet()) { sortedCounters.add(e); } for (Map.Entry entry : sortedCounters) { - if (entry.getValue() >= Options.CompilationCountLimit.getValue() / 2) { + if (entry.getValue() >= Options.CompilationCountLimit.getValue(options) / 2) { TTY.out.printf("%d\t%s%n", entry.getValue(), str(entry.getKey())); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java index a40d0711aaf..b0bcd702324 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java @@ -44,7 +44,8 @@ import java.util.concurrent.ConcurrentLinkedDeque; import org.graalvm.compiler.debug.CSVUtil; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import com.sun.management.ThreadMXBean; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -56,12 +57,11 @@ public final class CompilationStatistics { public static class Options { // @formatter:off @Option(help = "Enables CompilationStatistics.") - public static final OptionValue UseCompilationStatistics = new OptionValue<>(false); + public static final OptionKey UseCompilationStatistics = new OptionKey<>(false); // @formatter:on } private static final long RESOLUTION = 100000000; - private static final boolean ENABLED = Options.UseCompilationStatistics.getValue(); private static final CompilationStatistics DUMMY = new CompilationStatistics(null, false); @@ -114,6 +114,7 @@ public final class CompilationStatistics { bytecodeCount = method.getCodeSize(); threadAllocatedBytesStart = getThreadAllocatedBytes(); } else { + assert DUMMY == null : "only DUMMY has no method"; holder = ""; name = ""; signature = ""; @@ -122,7 +123,7 @@ public final class CompilationStatistics { } public void finish(HotSpotResolvedJavaMethod method, HotSpotInstalledCode code) { - if (ENABLED) { + if (isEnabled()) { duration = System.nanoTime() - startTime; codeSize = (int) code.getCodeSize(); memoryUsed = getThreadAllocatedBytes() - threadAllocatedBytesStart; @@ -137,8 +138,8 @@ public final class CompilationStatistics { return current.get().isEmpty() ? null : current.get().getLast(); } - public static CompilationStatistics create(HotSpotResolvedJavaMethod method, boolean isOSR) { - if (ENABLED) { + public static CompilationStatistics create(OptionValues options, HotSpotResolvedJavaMethod method, boolean isOSR) { + if (Options.UseCompilationStatistics.getValue(options)) { CompilationStatistics stats = new CompilationStatistics(method, isOSR); list.add(stats); current.get().addLast(stats); @@ -148,11 +149,12 @@ public final class CompilationStatistics { } } + public boolean isEnabled() { + return this != DUMMY; + } + @SuppressWarnings("deprecation") public static void clear(String dumpName) { - if (!ENABLED) { - return; - } try { ConcurrentLinkedDeque snapshot = list; long snapshotZeroTime = zeroTime; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java index e86a1bdb71c..bc17fd1c39b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java @@ -30,7 +30,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; - +import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.util.List; import org.graalvm.compiler.code.CompilationResult; @@ -44,8 +44,9 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimeSource; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; @@ -93,6 +94,7 @@ public class CompilationTask { private final boolean installAsDefault; private final boolean useProfilingInfo; + private final OptionValues options; static class Lazy { /** @@ -102,12 +104,33 @@ public class CompilationTask { static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); } - public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) { + public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, + OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.compilationId = new HotSpotCompilationIdentifier(request); this.useProfilingInfo = useProfilingInfo; this.installAsDefault = installAsDefault; + + /* + * Disable inlining if HotSpot has it disabled unless it's been explicitly set in Graal. + */ + HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); + GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); + OptionValues newOptions = options; + if (!config.inline) { + EconomicMap, Object> m = OptionValues.newOptionMap(); + if (Inline.getValue(options) && !Inline.hasBeenSet(options)) { + m.put(Inline, false); + } + if (InlineDuringParsing.getValue(options) && !InlineDuringParsing.hasBeenSet(options)) { + m.put(InlineDuringParsing, false); + } + if (!m.isEmpty()) { + newOptions = new OptionValues(options, m); + } + } + this.options = newOptions; } public HotSpotResolvedJavaMethod getMethod() { @@ -199,14 +222,14 @@ public class CompilationTask { CompilationResult result = null; try (DebugCloseable a = CompilationTime.start()) { - CompilationStatistics stats = CompilationStatistics.create(method, isOSR); - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); + final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); if (printCompilation) { TTY.println(getMethodDescription() + "..."); } - TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); + TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); final long start; final long allocatedBytesBefore; if (printAfterCompilation || printCompilation) { @@ -220,14 +243,7 @@ public class CompilationTask { try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { // Begin the compilation event. compilationEvent.begin(); - /* - * Disable inlining if HotSpot has it disabled unless it's been explicitly set in - * Graal. - */ - boolean disableInlining = !config.inline && !Inline.hasBeenSet(); - try (OverrideScope s1 = disableInlining ? OptionValue.override(Inline, false) : null) { - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId); - } + result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); } catch (Throwable e) { throw Debug.handle(e); } finally { @@ -264,11 +280,11 @@ public class CompilationTask { return null; } catch (BailoutException bailout) { BAILOUTS.increment(); - if (ExitVMOnBailout.getValue()) { + if (ExitVMOnBailout.getValue(options)) { TTY.out.println(method.format("Bailout in %H.%n(%p)")); bailout.printStackTrace(TTY.out); System.exit(-1); - } else if (PrintBailout.getValue()) { + } else if (PrintBailout.getValue(options)) { TTY.out.println(method.format("Bailout in %H.%n(%p)")); bailout.printStackTrace(TTY.out); } @@ -279,7 +295,7 @@ public class CompilationTask { * will happen if retry is false. */ final boolean permanentBailout = bailout.isPermanent(); - if (permanentBailout && PrintBailout.getValue()) { + if (permanentBailout && PrintBailout.getValue(options)) { TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : "")); } return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout); @@ -335,8 +351,8 @@ public class CompilationTask { * Automatically enable ExitVMOnException during bootstrap or when asserts are enabled but * respect ExitVMOnException if it's been explicitly set. */ - boolean exitVMOnException = ExitVMOnException.getValue(); - if (!ExitVMOnException.hasBeenSet()) { + boolean exitVMOnException = ExitVMOnException.getValue(options); + if (!ExitVMOnException.hasBeenSet(options)) { assert (exitVMOnException = true) == true; if (!exitVMOnException) { HotSpotGraalRuntimeProvider runtime = compiler.getGraalRuntime(); @@ -346,7 +362,7 @@ public class CompilationTask { } } - if (PrintStackTraceOnException.getValue() || exitVMOnException) { + if (PrintStackTraceOnException.getValue(options) || exitVMOnException) { try { t.printStackTrace(TTY.out); } catch (Throwable throwable) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java index eb9532cdccb..14a95d28592 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java @@ -28,8 +28,9 @@ import java.util.Arrays; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -53,12 +54,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Delay in seconds before watch dog monitoring a compilation (0 disables monitoring).", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStartDelay = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStartDelay = new OptionKey<>(0.0D); @Option(help = "Interval in seconds between a watch dog reporting stack traces for long running compilations.", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStackTraceInterval = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStackTraceInterval = new OptionKey<>(60.0D); @Option(help = "Number of contiguous identical compiler thread stack traces allowed before the VM exits " + "on the basis of a stuck compilation.", type = OptionType.Debug) - public static final OptionValue NonFatalIdenticalCompilationSnapshots = new OptionValue<>(10); + public static final OptionKey NonFatalIdenticalCompilationSnapshots = new OptionKey<>(20); // @formatter:on } @@ -90,12 +91,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * this time period and thus not be actively monitored by the watch dog. */ private static final int SPIN_TIMEOUT_MS = 1000; - private static final long START_DELAY_MS = ms(Options.CompilationWatchDogStartDelay.getValue()); - private static final long STACK_TRACE_INTERVAL_MS = ms(Options.CompilationWatchDogStackTraceInterval.getValue()); - private static final boolean ENABLED = START_DELAY_MS > 0.0D; private WatchDogState state = WatchDogState.SLEEPING; private final Thread compilerThread; + private final long startDelayMilliseconds; + private final long stackTraceIntervalMilliseconds; + private final int nonFatalIdenticalCompilationSnapshots; private volatile ResolvedJavaMethod currentMethod; private volatile int currentId; private ResolvedJavaMethod lastWatched; @@ -106,11 +107,14 @@ class CompilationWatchDog extends Thread implements AutoCloseable { private int numberOfIdenticalStackTraces; private StackTraceElement[] lastStackTrace; - CompilationWatchDog(Thread compilerThread) { + CompilationWatchDog(Thread compilerThread, long startDelayMilliseconds, long stackTraceIntervalMilliseconds, int nonFatalIdenticalCompilationSnapshots) { this.compilerThread = compilerThread; this.setName("WatchDog" + getId() + "[" + compilerThread.getName() + "]"); this.setPriority(Thread.MAX_PRIORITY); this.setDaemon(true); + this.startDelayMilliseconds = startDelayMilliseconds; + this.stackTraceIntervalMilliseconds = stackTraceIntervalMilliseconds; + this.nonFatalIdenticalCompilationSnapshots = nonFatalIdenticalCompilationSnapshots; } public void startCompilation(ResolvedJavaMethod method, int id) { @@ -183,8 +187,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { @Override public void run() { - trace("Started%n", this); try { + trace("Started%n", this); while (true) { // get a copy of the last set method final ResolvedJavaMethod currentlyCompiling = currentMethod; @@ -200,25 +204,27 @@ class CompilationWatchDog extends Thread implements AutoCloseable { tick(WatchDogState.WATCHING_WITHOUT_STACK_INSPECTION); break; case WATCHING_WITHOUT_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds) { // we looked at the same compilation for a certain time // so now we start to collect stack traces tick(WatchDogState.WATCHING_WITH_STACK_INSPECTION); trace("changes mode to watching with stack traces"); } else { - // we still compile the same method but won't collect traces yet + // we still compile the same method but won't collect traces + // yet trace("watching without stack traces [%.2f seconds]", secs(elapsed)); } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we exceeded initial watching period + // compilation finished before we exceeded initial watching + // period reset(); } break; case WATCHING_WITH_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS + (traceIntervals * STACK_TRACE_INTERVAL_MS)) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds + (traceIntervals * stackTraceIntervalMilliseconds)) { trace("took a stack trace"); boolean newStackTrace = recordStackTrace(compilerThread.getStackTrace()); if (!newStackTrace) { @@ -226,7 +232,7 @@ class CompilationWatchDog extends Thread implements AutoCloseable { numberOfIdenticalStackTraces = 0; } numberOfIdenticalStackTraces++; - if (numberOfIdenticalStackTraces > Options.NonFatalIdenticalCompilationSnapshots.getValue()) { + if (numberOfIdenticalStackTraces > nonFatalIdenticalCompilationSnapshots) { synchronized (CompilationWatchDog.class) { TTY.printf("======================= WATCH DOG THREAD =======================%n" + "%s took %d identical stack traces, which indicates a stuck compilation (id=%d) of %s%n%sExiting VM%n", this, @@ -247,7 +253,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we are able to collect stack traces + // compilation finished before we are able to collect stack + // traces reset(); } break; @@ -255,16 +262,29 @@ class CompilationWatchDog extends Thread implements AutoCloseable { break; } } - Thread.sleep(SPIN_TIMEOUT_MS); + try { + Thread.sleep(SPIN_TIMEOUT_MS); + } catch (InterruptedException e) { + // Silently swallow + } } + } catch (VirtualMachineError vmError) { + /* + * We encounter a VM error. This includes for example OutOfMemoryExceptions. In such a + * case we silently swallow the error. If it happens again the application thread will + * most likely encounter the same problem. If not the watchdog thread will no longer + * monitor the compilation and thus the error cannot happen again. + */ } catch (Throwable t) { - synchronized (CompilationWatchDog.class) { - TTY.printf("%s encountered an exception%n%s%n", this, fmt(t)); - } + /* + * A real exception happened on the compilation watchdog. This is unintended behavior + * and must not happen in any case. + */ + throw new InternalError(String.format("%s encountered an exception%n%s%n", this, fmt(t)), t); } } - private static final ThreadLocal WATCH_DOGS = ENABLED ? new ThreadLocal<>() : null; + private static final ThreadLocal WATCH_DOGS = new ThreadLocal<>(); /** * Opens a scope for watching the compilation of a given method. @@ -276,13 +296,16 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * is the whole compilation so that leaving the scope will cause {@link #close()} to be * called. */ - static CompilationWatchDog watch(ResolvedJavaMethod method, int id) { - if (ENABLED) { + static CompilationWatchDog watch(ResolvedJavaMethod method, int id, OptionValues options) { + long startDelayMilliseconds = ms(Options.CompilationWatchDogStartDelay.getValue(options)); + if (startDelayMilliseconds > 0.0D) { // Lazily get a watch dog thread for the current compiler thread CompilationWatchDog watchDog = WATCH_DOGS.get(); if (watchDog == null) { Thread currentThread = currentThread(); - watchDog = new CompilationWatchDog(currentThread); + long stackTraceIntervalMilliseconds = ms(Options.CompilationWatchDogStackTraceInterval.getValue(options)); + int nonFatalIdenticalCompilationSnapshots = Options.NonFatalIdenticalCompilationSnapshots.getValue(options); + watchDog = new CompilationWatchDog(currentThread, startDelayMilliseconds, stackTraceIntervalMilliseconds, nonFatalIdenticalCompilationSnapshots); WATCH_DOGS.set(watchDog); watchDog.start(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java index fae52a2f352..79e33708b7c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java @@ -57,10 +57,8 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -78,19 +76,16 @@ import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.compiler.options.OptionsParser.OptionConsumer; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -117,48 +112,22 @@ public final class CompileTheWorld { public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path"; /** - * A mechanism for overriding JVMCI options that affect compilation. A {@link Config} object - * should be used in a try-with-resources statement to ensure overriding of options is scoped - * properly. For example: - * - *
    -     *     Config config = ...;
    -     *     try (AutoCloseable s = config == null ? null : config.apply()) {
    -     *         // perform a JVMCI compilation
    -     *     }
    -     * 
    + * @param options a space separated set of option value settings with each option setting in a + * {@code -Dgraal.=} format but without the leading {@code -Dgraal.}. + * Ignored if null. */ - @SuppressWarnings("serial") - public static class Config extends HashMap, Object> implements OptionConsumer { - /** - * Creates a {@link Config} object by parsing a set of space separated override options. - * - * @param options a space separated set of option value settings with each option setting in - * a {@code -Dgraal.=} format but without the leading - * {@code -Dgraal.}. Ignored if null. - */ - public Config(String options) { - if (options != null) { - Map optionSettings = new HashMap<>(); - for (String optionSetting : options.split("\\s+|#")) { - OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); - } - OptionsParser.parseOptions(optionSettings, this, ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader())); + public static EconomicMap, Object> parseOptions(String options) { + if (options != null) { + EconomicMap optionSettings = EconomicMap.create(); + for (String optionSetting : options.split("\\s+|#")) { + OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); } + EconomicMap, Object> values = OptionValues.newOptionMap(); + ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); + OptionsParser.parseOptions(optionSettings, values, loader); + return values; } - - /** - * Applies the overrides represented by this object. The overrides are in effect until - * {@link OverrideScope#close()} is called on the returned object. - */ - OverrideScope apply() { - return OptionValue.override(this); - } - - @Override - public void set(OptionDescriptor desc, Object value) { - put(desc.getOptionValue(), value); - } + return EconomicMap.create(); } private final HotSpotJVMCIRuntimeProvider jvmciRuntime; @@ -199,7 +168,6 @@ public final class CompileTheWorld { private AtomicLong memoryUsed = new AtomicLong(); private boolean verbose; - private final Config config; /** * Signal that the threads should start compiling in multithreaded mode. @@ -208,6 +176,9 @@ public final class CompileTheWorld { private ThreadPoolExecutor threadPool; + private OptionValues currentOptions; + private final EconomicMap, Object> compilationOptions; + /** * Creates a compile-the-world instance. * @@ -217,8 +188,8 @@ public final class CompileTheWorld { * @param methodFilters * @param excludeMethodFilters */ - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, Config config, int startAt, int stopAt, String methodFilters, - String excludeMethodFilters, boolean verbose) { + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters, + boolean verbose, OptionValues initialOptions, EconomicMap, Object> compilationOptions) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.inputClassPath = files; @@ -227,19 +198,32 @@ public final class CompileTheWorld { this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters); this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters); this.verbose = verbose; - this.config = config; + EconomicMap, Object> compilationOptionsCopy = EconomicMap.create(compilationOptions); + this.currentOptions = initialOptions; // We don't want the VM to exit when a method fails to compile... - config.putIfAbsent(ExitVMOnException, false); + ExitVMOnException.update(compilationOptionsCopy, false); // ...but we want to see exceptions. - config.putIfAbsent(PrintBailout, true); - config.putIfAbsent(PrintStackTraceOnException, true); + PrintBailout.update(compilationOptionsCopy, true); + PrintStackTraceOnException.update(compilationOptionsCopy, true); + + // By default only report statistics for the CTW threads themselves + if (!GraalDebugConfig.Options.DebugValueThreadFilter.hasBeenSet(initialOptions)) { + GraalDebugConfig.Options.DebugValueThreadFilter.update(compilationOptionsCopy, "^CompileTheWorld"); + } + this.compilationOptions = EconomicMap.create(compilationOptionsCopy); } - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler) { - this(jvmciRuntime, compiler, CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue(), - CompileTheWorldMethodFilter.getValue(), CompileTheWorldExcludeMethodFilter.getValue(), CompileTheWorldVerbose.getValue()); + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) { + this(jvmciRuntime, compiler, CompileTheWorldClasspath.getValue(options), + CompileTheWorldStartAt.getValue(options), + CompileTheWorldStopAt.getValue(options), + CompileTheWorldMethodFilter.getValue(options), + CompileTheWorldExcludeMethodFilter.getValue(options), + CompileTheWorldVerbose.getValue(options), + options, + parseOptions(CompileTheWorldConfig.getValue(options))); } /** @@ -247,10 +231,6 @@ public final class CompileTheWorld { * equals {@link #SUN_BOOT_CLASS_PATH} the boot class path is used. */ public void compile() throws Throwable { - // By default only report statistics for the CTW threads themselves - if (!GraalDebugConfig.Options.DebugValueThreadFilter.hasBeenSet()) { - GraalDebugConfig.Options.DebugValueThreadFilter.setValue("^CompileTheWorld"); - } if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) { String bcpEntry = null; if (Java8OrEarlier) { @@ -513,16 +493,6 @@ public final class CompileTheWorld { final String[] entries = classPath.split(File.pathSeparator); long start = System.currentTimeMillis(); - CompilerThreadFactory factory = new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - return DebugEnvironment.initialize(System.out, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); - } - return null; - } - }); - try { // compile dummy method to get compiler initialized outside of the // config debug override. @@ -531,7 +501,7 @@ public final class CompileTheWorld { int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); } catch (NoSuchMethodException | SecurityException e1) { printStackTrace(e1); @@ -542,17 +512,26 @@ public final class CompileTheWorld { * DebugValueThreadFilter to filter on the thread names. */ int threadCount = 1; - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { - threadCount = CompileTheWorldOptions.CompileTheWorldThreads.getValue(); + if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue(currentOptions)) { + threadCount = CompileTheWorldOptions.CompileTheWorldThreads.getValue(currentOptions); if (threadCount == 0) { threadCount = Runtime.getRuntime().availableProcessors(); } } else { running = true; } - threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(savedOptions, compilationOptions); + threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), + new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { + @Override + public GraalDebugConfig getDebugConfig() { + return DebugEnvironment.ensureInitialized(currentOptions, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); + } + })); + + try { for (int i = 0; i < entries.length; i++) { final String entry = entries[i]; @@ -657,6 +636,8 @@ public final class CompileTheWorld { } cpe.close(); } + } finally { + currentOptions = savedOptions; } if (!running) { @@ -678,7 +659,7 @@ public final class CompileTheWorld { long elapsedTime = System.currentTimeMillis() - start; println(); - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { + if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue(currentOptions)) { TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, compileTime.get(), memoryUsed.get()); } else { @@ -713,8 +694,12 @@ public final class CompileTheWorld { @Override public void run() { waitToRun(); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(savedOptions, compilationOptions); + try { compileMethod(method, classFileCounter); + } finally { + currentOptions = savedOptions; } } }); @@ -735,7 +720,7 @@ public final class CompileTheWorld { // For more stable CTW execution, disable use of profiling information boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); // Invalidate the generated code so the code cache doesn't fill up diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java index 4f3032dc49f..5bed25e4fc4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to {@link CompileTheWorld}. @@ -35,40 +35,27 @@ import org.graalvm.compiler.options.OptionValue; public class CompileTheWorldOptions { // @formatter:off @Option(help = "Class path denoting methods to compile", type = OptionType.Debug) - public static final OptionValue CompileTheWorldClasspath = new OptionValue<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); + public static final OptionKey CompileTheWorldClasspath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); @Option(help = "Verbose CompileTheWorld operation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldVerbose = new OptionValue<>(true); + public static final OptionKey CompileTheWorldVerbose = new OptionKey<>(true); @Option(help = "The number of CompileTheWorld iterations to perform", type = OptionType.Debug) - public static final OptionValue CompileTheWorldIterations = new OptionValue<>(1); + public static final OptionKey CompileTheWorldIterations = new OptionKey<>(1); @Option(help = "Only compile methods matching this filter", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMethodFilter = new OptionValue<>(null); + public static final OptionKey CompileTheWorldMethodFilter = new OptionKey<>(null); @Option(help = "Exclude methods matching this filter from compilation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldExcludeMethodFilter = new OptionValue<>(null); + public static final OptionKey CompileTheWorldExcludeMethodFilter = new OptionKey<>(null); @Option(help = "First class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStartAt = new OptionValue<>(1); + public static final OptionKey CompileTheWorldStartAt = new OptionKey<>(1); @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE); + public static final OptionKey CompileTheWorldStopAt = new OptionKey<>(Integer.MAX_VALUE); @Option(help = "Option value overrides to use during compile the world. For example, " + "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", type = OptionType.Debug) - public static final OptionValue CompileTheWorldConfig = new OptionValue<>(null); + public static final OptionKey CompileTheWorldConfig = new OptionKey<>(null); @Option(help = "Run CTW using as many threads as there are processors on the system", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMultiThreaded = new OptionValue<>(false); + public static final OptionKey CompileTheWorldMultiThreaded = new OptionKey<>(false); @Option(help = "Number of threads to use for multithreaded CTW. Defaults to Runtime.getRuntime().availableProcessors()", type = OptionType.Debug) - public static final OptionValue CompileTheWorldThreads = new OptionValue<>(0); + public static final OptionKey CompileTheWorldThreads = new OptionKey<>(0); // @formatter:on - - /** - * Overrides {@link #CompileTheWorldStartAt} and {@link #CompileTheWorldStopAt} from {@code -XX} - * HotSpot options of the same name if the latter have non-default values. - */ - public static void overrideWithNativeOptions(GraalHotSpotVMConfig c) { - if (c.compileTheWorldStartAt != 1) { - CompileTheWorldStartAt.setValue(c.compileTheWorldStartAt); - } - if (c.compileTheWorldStopAt != Integer.MAX_VALUE) { - CompileTheWorldStopAt.setValue(c.compileTheWorldStopAt); - } - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java index 3940a9a7057..b82a2054632 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java @@ -26,16 +26,18 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.util.ArrayList; import java.util.Collections; -import java.util.IdentityHashMap; import java.util.List; import java.util.stream.Collectors; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.common.InitTimer; @@ -52,7 +54,7 @@ public abstract class CompilerConfigurationFactory implements Comparable CompilerConfiguration = new OptionValue<>(null); + public static final OptionKey CompilerConfiguration = new OptionKey<>(null); // @formatter:on } @@ -91,7 +93,7 @@ public abstract class CompilerConfigurationFactory implements Comparable, HotSpotBackendFactory> backends = new IdentityHashMap<>(); + private final EconomicMap, HotSpotBackendFactory> backends = EconomicMap.create(); @SuppressWarnings("try") public DefaultBackendMap(String backendName) { @@ -124,18 +126,11 @@ public abstract class CompilerConfigurationFactory implements Comparable factories = assertionsEnabled() ? new ArrayList<>() : null; + private static final List factories = Assertions.ENABLED ? new ArrayList<>() : null; private static boolean checkAndAddNewFactory(CompilerConfigurationFactory factory) { for (CompilerConfigurationFactory other : factories) { @@ -169,10 +164,10 @@ public abstract class CompilerConfigurationFactory implements Comparable PreferGraalStubs = new OptionValue<>(false); @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") - public static final OptionValue GraalArithmeticStubs = new OptionValue<>(true); + public static final OptionKey GraalArithmeticStubs = new OptionKey<>(true); @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) - public static final OptionValue ASMInstructionProfiling = new OptionValue<>(null); + public static final OptionKey ASMInstructionProfiling = new OptionKey<>(null); // @formatter:on } @@ -134,16 +127,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen private final HotSpotGraalRuntimeProvider runtime; - /** - * @see DeoptimizationFetchUnrollInfoCallNode - */ - public static final ForeignCallDescriptor FETCH_UNROLL_INFO = new ForeignCallDescriptor("fetchUnrollInfo", Word.class, long.class, int.class); - - /** - * @see DeoptimizationStub#unpackFrames(ForeignCallDescriptor, Word, int) - */ - public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(DeoptimizationStub.class, "unpackFrames", int.class, Word.class, int.class); - /** * @see AESCryptSubstitutions#encryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer) */ @@ -320,11 +303,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen public static final ForeignCallDescriptor INVOCATION_EVENT = new ForeignCallDescriptor("invocation_event", void.class, MethodCountersPointer.class); public static final ForeignCallDescriptor BACKEDGE_EVENT = new ForeignCallDescriptor("backedge_event", void.class, MethodCountersPointer.class, int.class, int.class); - /** - * @see UncommonTrapCallNode - */ - public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class, int.class); - public HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(providers); this.runtime = runtime; @@ -339,8 +317,9 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * runtime} object was initialized and this backend was registered with it. * * @param jvmciRuntime + * @param options */ - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { } /** @@ -349,8 +328,8 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param lir the LIR to examine * @return the registers that are defined by or used as temps for any instruction in {@code lir} */ - protected final Set gatherDestroyedCallerRegisters(LIR lir) { - final Set destroyedRegisters = new HashSet<>(); + protected final EconomicSet gatherDestroyedCallerRegisters(LIR lir) { + final EconomicSet destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY); ValueConsumer defConsumer = new ValueConsumer() { @Override @@ -382,7 +361,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen *

    * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove() * supports} pruning will have {@code destroyedRegisters} - * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as + * {@linkplain SaveRegistersOp#remove(EconomicSet) removed} as these registers are declared as * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by * the stub's caller). * @@ -393,17 +372,17 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual * slot to a frame slot index */ - protected void updateStub(Stub stub, Set destroyedRegisters, Map calleeSaveInfo, FrameMap frameMap) { + protected void updateStub(Stub stub, EconomicSet destroyedRegisters, EconomicMap calleeSaveInfo, FrameMap frameMap) { stub.initDestroyedCallerRegisters(destroyedRegisters); - for (Map.Entry e : calleeSaveInfo.entrySet()) { - SaveRegistersOp save = e.getValue(); + MapCursor cursor = calleeSaveInfo.getEntries(); + while (cursor.advance()) { + SaveRegistersOp save = cursor.getValue(); if (save.supportsRemove()) { save.remove(destroyedRegisters); } - DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo(); - if (info != null) { - info.setCalleeSaveInfo(save.getMap(frameMap)); + if (cursor.getKey() != LIRFrameState.NO_STATE) { + cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap)); } } } @@ -419,7 +398,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen } protected void profileInstructions(LIR lir, CompilationResultBuilder crb) { - if (HotSpotBackend.Options.ASMInstructionProfiling.getValue() != null) { + if (HotSpotBackend.Options.ASMInstructionProfiling.getValue(lir.getOptions()) != null) { HotSpotInstructionProfiling.countInstructions(lir, crb.asm); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java index 794f7674037..82f3ca48652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java @@ -27,15 +27,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.Arrays; -import java.util.HashMap; - import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; @@ -102,7 +101,7 @@ public abstract class HotSpotCounterOp extends LIRInstruction { proc.apply(0, increments[0], displacement); } else { // Slow path with sort by displacements ascending int[] displacements = new int[names.length]; - HashMap offsetMap = new HashMap<>(names.length); + EconomicMap offsetMap = EconomicMap.create(); for (int i = 0; i < names.length; i++) { int arrayIndex = getIndex(names[i], groups[i], increments[i]); displacements[i] = getDisplacementForLongIndex(target, arrayIndex); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java index 82d665be703..cb667da31cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -96,6 +96,11 @@ public interface HotSpotForeignCallLinkage extends ForeignCallLinkage, InvokeTar */ boolean isCompiledStub(); + /** + * Gets the stub, if any, this foreign call links to. + */ + Stub getStub(); + void finalizeAddress(Backend backend); long getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index c4e0d8d6bad..33422f760fb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -25,14 +25,13 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import java.util.Set; - import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CallingConvention.Type; @@ -228,13 +227,24 @@ public class HotSpotForeignCallLinkageImpl extends HotSpotForeignCallTarget impl return address == 0L || stub != null; } + @Override + public Stub getStub() { + assert checkStubCondition(); + return stub; + } + + private boolean checkStubCondition() { + assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + return true; + } + @Override public void finalizeAddress(Backend backend) { if (address == 0) { - assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + assert checkStubCondition(); InstalledCode code = stub.getCode(backend); - Set destroyedRegisters = stub.getDestroyedCallerRegisters(); + EconomicSet destroyedRegisters = stub.getDestroyedCallerRegisters(); if (!destroyedRegisters.isEmpty()) { AllocatableValue[] temporaryLocations = new AllocatableValue[destroyedRegisters.size()]; int i = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java index f4951022ed6..335ed22ff07 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java @@ -23,9 +23,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; - import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.Formattable; @@ -42,7 +40,6 @@ import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TopLevelDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; import org.graalvm.compiler.hotspot.CompilationCounters.Options; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -56,6 +53,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; import org.graalvm.compiler.phases.PhaseSuite; @@ -87,8 +85,9 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { this.jvmciRuntime = jvmciRuntime; this.graalRuntime = graalRuntime; // It is sufficient to have one compilation counter object per Graal compiler object. - this.compilationCounters = Options.CompilationCountLimit.getValue() > 0 ? new CompilationCounters() : null; - this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue() ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + OptionValues options = graalRuntime.getOptions(); + this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null; + this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; } @Override @@ -99,28 +98,29 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { @Override @SuppressWarnings("try") public CompilationRequestResult compileMethod(CompilationRequest request) { - if (graalRuntime.isBootstrapping() && GraalDebugConfig.Options.BootstrapInitializeOnly.getValue()) { - return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); - } - if (bootstrapWatchDog != null && graalRuntime.isBootstrapping()) { - if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { - // Drain the compilation queue to expedite completion of the bootstrap - return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + OptionValues options = graalRuntime.getOptions(); + if (graalRuntime.isBootstrapping()) { + if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) { + return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + } + if (bootstrapWatchDog != null) { + if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { + // Drain the compilation queue to expedite completion of the bootstrap + return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + } } } ResolvedJavaMethod method = request.getMethod(); HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; - try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId()); + try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod();) { + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { if (compilationCounters != null) { compilationCounters.countCompilation(method); } // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out, graalRuntime.getHostProviders().getSnippetReflection()); - } - CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true); + DebugEnvironment.ensureInitialized(options, graalRuntime.getHostProviders().getSnippetReflection()); + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true, options); CompilationRequestResult r = null; try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig()); Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) { @@ -133,37 +133,42 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { public void compileTheWorld() throws Throwable { HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmciRuntime.getHostJVMCIBackend().getCodeCache(); - int iterations = CompileTheWorldOptions.CompileTheWorldIterations.getValue(); + int iterations = CompileTheWorldOptions.CompileTheWorldIterations.getValue(graalRuntime.getOptions()); for (int i = 0; i < iterations; i++) { codeCache.resetCompilationStatistics(); TTY.println("CompileTheWorld : iteration " + i); - CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, this); + this.graalRuntime.getVMConfig(); + CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, this, graalRuntime.getOptions()); ctw.compile(); } System.exit(0); } - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId) { + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId); + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options); if (graph == null) { SpeculationLog speculationLog = method.getSpeculationLog(); if (speculationLog != null) { speculationLog.collectFailedSpeculations(); } - graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()), speculationLog, useProfilingInfo, compilationId); + graph = new StructuredGraph.Builder(options, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( + speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build(); } - Suites suites = getSuites(providers); - LIRSuites lirSuites = getLIRSuites(providers); + Suites suites = getSuites(providers, options); + LIRSuites lirSuites = getLIRSuites(providers, options); ProfilingInfo profilingInfo = useProfilingInfo ? method.getProfilingInfo(!isOSR, isOSR) : DefaultProfilingInfo.get(TriState.FALSE); - OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - if (isOSR) { - // In OSR compiles, we cannot rely on never executed code profiles, because - // all code after the OSR loop is never executed. + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo, options); + + /* + * Cut off never executed code profiles if there is code, e.g. after the osr loop, that is + * never executed. + */ + if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) { optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } CompilationResult result = new CompilationResult(); @@ -186,15 +191,16 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { * * @param method * @param compilationId + * @param options * @return an intrinsic graph that can be compiled and installed for {@code method} or null */ @SuppressWarnings("try") - public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId) { + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options) { Replacements replacements = providers.getReplacements(); ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method); if (substMethod != null) { assert !substMethod.equals(method); - StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES, NO_PROFILING_INFO, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); try (Debug.Scope scope = Debug.scope("GetIntrinsicGraph", graph)) { Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); @@ -210,16 +216,16 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { return null; } - protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { - return new OptimisticOptimizations(profilingInfo); + protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { + return new OptimisticOptimizations(profilingInfo, options); } - protected Suites getSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultSuites(); + protected Suites getSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultSuites(options); } - protected LIRSuites getLIRSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultLIRSuites(); + protected LIRSuites getLIRSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultLIRSuites(options); } /** @@ -245,6 +251,11 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); } if (isOSR) { + // We must not clear non liveness for OSR compilations. + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); + newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); newGbs.appendPhase(new OnStackReplacementPhase()); } return newGbs; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java index e7ca2262368..428bcffaf16 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -22,63 +22,30 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; -import static org.graalvm.compiler.options.OptionValue.PROFILE_OPTIONVALUE_PROPERTY_NAME; import static jdk.vm.ci.common.InitTimer.timer; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; import java.io.PrintStream; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.ServiceLoader; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import jdk.vm.ci.common.InitTimer; +import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotSignature; -import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; +import jdk.vm.ci.services.Services; public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { - /** - * The name of the system property specifying a file containing extra Graal option settings. - */ - private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; - - /** - * The name of the system property specifying the Graal version. - */ - private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; - - /** - * The prefix for system properties that correspond to {@link Option} annotated fields. A field - * named {@code MyOption} will have its value set from a system property with the name - * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. - */ - public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; - private static MethodFilter[] graalCompileOnlyFilter; - /** - * Gets the system property assignment that would set the current value for a given option. - */ - public static String asSystemPropertySetting(OptionValue value) { - return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(); - } - private final HotSpotGraalJVMCIServiceLocator locator; HotSpotGraalCompilerFactory(HotSpotGraalJVMCIServiceLocator locator) { @@ -90,137 +57,62 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return "graal"; } + /** + * Initialized when this factory is {@linkplain #onSelection() selected}. + */ + private OptionValues options; + @Override public void onSelection() { - initializeOptions(); JVMCIVersionCheck.check(false); + assert options == null : "cannot select " + getClass() + " service more than once"; + options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + initializeGraalCompileOnlyFilter(options); + if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue(options)) { + /* + * Exercise this code path early to encourage loading now. This doesn't solve problem of + * deadlock during class loading but seems to eliminate it in practice. + */ + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); + } + } + + private static void initializeGraalCompileOnlyFilter(OptionValues options) { + String optionValue = Options.GraalCompileOnly.getValue(options); + if (optionValue != null) { + MethodFilter[] filter = MethodFilter.parse(optionValue); + if (filter.length == 0) { + filter = null; + } + graalCompileOnlyFilter = filter; + } } @Override public void printProperties(PrintStream out) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); out.println("[Graal properties]"); - OptionsParser.printFlags(loader, out, allOptionsSettings.keySet(), GRAAL_OPTION_PROPERTY_PREFIX); + options.printHelp(OptionsParser.getOptionsLoader(), out, GRAAL_OPTION_PROPERTY_PREFIX); } static class Options { // @formatter:off @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert) - public static final OptionValue CompileGraalWithC1Only = new OptionValue<>(true); + public static final OptionKey CompileGraalWithC1Only = new OptionKey<>(true); @Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert) - public static final OptionValue UseTrivialPrefixes = new OptionValue<>(false); + public static final OptionKey UseTrivialPrefixes = new OptionKey<>(false); @Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert) - public static final OptionValue GraalCompileOnly = new OptionValue<>(null); + public static final OptionKey GraalCompileOnly = new OptionKey<>(null); // @formatter:on } - private static Map allOptionsSettings; - - /** - * Initializes options if they haven't already been initialized. - * - * Initialization means first parsing the options in the file denoted by the - * {@code VM.getSavedProperty(String) saved} system property named - * {@value HotSpotGraalCompilerFactory#GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists - * followed by parsing the options encoded in saved system properties whose names start with - * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned - * file with {@link Properties#load(java.io.Reader)}. - */ - @SuppressWarnings("try") - private static synchronized void initializeOptions() { - if (allOptionsSettings == null) { - try (InitTimer t = timer("InitializeOptions")) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); - Properties savedProps = getSavedProperties(Java8OrEarlier); - String optionsFile = savedProps.getProperty(GRAAL_OPTIONS_FILE_PROPERTY_NAME); - - if (optionsFile != null) { - File graalOptions = new File(optionsFile); - if (graalOptions.exists()) { - try (FileReader fr = new FileReader(graalOptions)) { - Properties props = new Properties(); - props.load(fr); - Map optionSettings = new HashMap<>(); - for (Map.Entry e : props.entrySet()) { - optionSettings.put((String) e.getKey(), (String) e.getValue()); - } - try { - OptionsParser.parseOptions(optionSettings, null, loader); - if (allOptionsSettings == null) { - allOptionsSettings = new HashMap<>(optionSettings); - } else { - allOptionsSettings.putAll(optionSettings); - } - } catch (Throwable e) { - throw new InternalError("Error parsing an option from " + graalOptions, e); - } - } catch (IOException e) { - throw new InternalError("Error reading " + graalOptions, e); - } - } - } - - Map optionSettings = new HashMap<>(); - for (Map.Entry e : savedProps.entrySet()) { - String name = (String) e.getKey(); - if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { - if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { - System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); - } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME) || name.equals(PROFILE_OPTIONVALUE_PROPERTY_NAME)) { - // Ignore well known properties that do not denote an option - } else { - String value = (String) e.getValue(); - optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); - } - } - } - - OptionsParser.parseOptions(optionSettings, null, loader); - - if (allOptionsSettings == null) { - allOptionsSettings = optionSettings; - } else { - allOptionsSettings.putAll(optionSettings); - } - - if (Options.GraalCompileOnly.getValue() != null) { - graalCompileOnlyFilter = MethodFilter.parse(Options.GraalCompileOnly.getValue()); - if (graalCompileOnlyFilter.length == 0) { - graalCompileOnlyFilter = null; - } - } - if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue()) { - /* - * Exercise this code path early to encourage loading now. This doesn't solve - * problem of deadlock during class loading but seems to eliminate it in - * practice. - */ - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); - } - } - } - } - - private static Properties getSavedProperties(boolean jdk8OrEarlier) { - try { - String vmClassName = jdk8OrEarlier ? "sun.misc.VM" : "jdk.internal.misc.VM"; - Class vmClass = Class.forName(vmClassName); - Field savedPropsField = vmClass.getDeclaredField("savedProps"); - savedPropsField.setAccessible(true); - return (Properties) savedPropsField.get(null); - } catch (Exception e) { - throw new GraalError(e); - } - } - @Override public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { - HotSpotGraalCompiler compiler = createCompiler(runtime, CompilerConfigurationFactory.selectFactory(null)); + HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options)); // Only the HotSpotGraalRuntime associated with the compiler created via // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving // VM events. @@ -236,18 +128,18 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} */ @SuppressWarnings("try") - public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, CompilerConfigurationFactory compilerConfigurationFactory) { + public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; try (InitTimer t = timer("HotSpotGraalRuntime.")) { - HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory); + HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options); return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime); } } @Override public String[] getTrivialPrefixes() { - if (Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { + if (Options.UseTrivialPrefixes.getValue(options)) { + if (Options.CompileGraalWithC1Only.getValue(options)) { return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"}; } } @@ -259,8 +151,8 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto if (graalCompileOnlyFilter != null) { return CompilationLevelAdjustment.ByFullSignature; } - if (!Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { + if (!Options.UseTrivialPrefixes.getValue(options)) { + if (Options.CompileGraalWithC1Only.getValue(options)) { // We only decide using the class declaring the method // so no need to have the method name and signature // symbols converted to a String. @@ -275,6 +167,13 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return adjustCompilationLevelInternal(declaringClass, name, signature, level); } + static { + // Fail-fast detection for package renaming to guard use of package + // prefixes in adjustCompilationLevelInternal. + assert Services.class.getName().equals("jdk.vm.ci.services.Services"); + assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory"); + } + /* * This method is static so it can be exercised during initialization. */ diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java index b33b0cf437f..43b48a2418c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java @@ -23,12 +23,14 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.util.ModuleAPI.addExports; +import static org.graalvm.compiler.core.common.util.ModuleAPI.addOpens; import static org.graalvm.compiler.core.common.util.ModuleAPI.getModule; import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; import org.graalvm.compiler.serviceprovider.ServiceProvider; import jdk.vm.ci.hotspot.HotSpotVMEventListener; +import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.services.JVMCIServiceLocator; @@ -38,10 +40,10 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator { private boolean exportsAdded; /** - * Dynamically exports various internal JDK packages to the Graal module. This requires only - * {@code --add-exports=java.base/jdk.internal.module=org.graalvm.compiler.graal_core} on the VM - * command line instead of a {@code --add-exports} instance for each JDK internal package used - * by Graal. + * Dynamically exports and opens various internal JDK packages to the Graal module. This + * requires only a single {@code --add-exports=java.base/jdk.internal.module=} on + * the VM command line instead of a {@code --add-exports} instance for each JDK internal package + * used by Graal. */ private void addExports() { if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) { @@ -50,6 +52,9 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator { addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); + addOpens.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); + addOpens.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); + addOpens.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); exportsAdded = true; } } @@ -70,8 +75,23 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator { return null; } - public void onCompilerCreation(HotSpotGraalCompiler compiler) { + /** + * The signature cannot mention HotSpotGraalCompiler since it indirectly references + * JVMCICompiler which is in a non-exported JVMCI package. This causes an IllegalAccessError + * while looking for the + * provider factory + * method: + * + *

    +     * java.util.ServiceConfigurationError: jdk.vm.ci.services.JVMCIServiceLocator: Unable to get public provider() method
    +     * ...
    +     * Caused by: java.lang.IllegalAccessError: superinterface check failed: class org.graalvm.compiler.api.runtime.GraalJVMCICompiler
    +     * (in module org.graalvm.compiler.graal_core) cannot access class jdk.vm.ci.runtime.JVMCICompiler (in module jdk.vm.ci) because
    +     * module jdk.vm.ci does not export jdk.vm.ci.runtime to module org.graalvm.compiler.graal_core
    +     * 
    + */ + void onCompilerCreation(JVMCICompiler compiler) { assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created"; - this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime(); + this.graalRuntime = (HotSpotGraalRuntime) ((HotSpotGraalCompiler) compiler).getGraalRuntime(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java new file mode 100644 index 00000000000..1bd63033471 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import static jdk.vm.ci.common.InitTimer.timer; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Properties; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionValuesAccess; +import org.graalvm.compiler.options.OptionsParser; +import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +import jdk.vm.ci.common.InitTimer; + +/** + * The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The + * values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix. + */ +@ServiceProvider(OptionValuesAccess.class) +public class HotSpotGraalOptionValues implements OptionValuesAccess { + + /** + * The name of the system property specifying a file containing extra Graal option settings. + */ + private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; + + /** + * The name of the system property specifying the Graal version. + */ + private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; + + /** + * The prefix for system properties that correspond to {@link Option} annotated fields. A field + * named {@code MyOption} will have its value set from a system property with the name + * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. + */ + public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; + + /** + * Gets the system property assignment that would set the current value for a given option. + */ + public static String asSystemPropertySetting(OptionValues options, OptionKey value) { + return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options); + } + + private static Properties getSavedProperties() { + try { + String value = System.getProperty("java.specification.version"); + if (value.startsWith("1.")) { + value = value.substring(2); + } + int javaVersion = Integer.parseInt(value); + String vmClassName = javaVersion <= 8 ? "sun.misc.VM" : "jdk.internal.misc.VM"; + Class vmClass = Class.forName(vmClassName); + Field savedPropsField = vmClass.getDeclaredField("savedProps"); + savedPropsField.setAccessible(true); + return (Properties) savedPropsField.get(null); + } catch (Exception e) { + throw new InternalError(e); + } + } + + public static final OptionValues HOTSPOT_OPTIONS = initializeOptions(); + + /** + * Global options. The values for these options are initialized by parsing the file denoted by + * the {@code VM.getSavedProperty(String) saved} system property named + * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options + * encoded in saved system properties whose names start with + * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned + * file with {@link Properties#load(java.io.Reader)}. + */ + @SuppressWarnings("try") + private static OptionValues initializeOptions() { + EconomicMap, Object> values = OptionValues.newOptionMap(); + try (InitTimer t = timer("InitializeOptions")) { + + Iterable loader = OptionsParser.getOptionsLoader(); + Properties savedProps = getSavedProperties(); + String optionsFile = savedProps.getProperty(GRAAL_OPTIONS_FILE_PROPERTY_NAME); + + if (optionsFile != null) { + File graalOptions = new File(optionsFile); + if (graalOptions.exists()) { + try (FileReader fr = new FileReader(graalOptions)) { + Properties props = new Properties(); + props.load(fr); + EconomicMap optionSettings = EconomicMap.create(); + MapCursor cursor = optionSettings.getEntries(); + while (cursor.advance()) { + optionSettings.put(cursor.getKey(), cursor.getValue()); + } + try { + OptionsParser.parseOptions(optionSettings, values, loader); + } catch (Throwable e) { + throw new InternalError("Error parsing an option from " + graalOptions, e); + } + } catch (IOException e) { + throw new InternalError("Error reading " + graalOptions, e); + } + } + } + + EconomicMap optionSettings = EconomicMap.create(); + for (Map.Entry e : savedProps.entrySet()) { + String name = (String) e.getKey(); + if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { + if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { + System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); + } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME)) { + // Ignore well known properties that do not denote an option + } else { + String value = (String) e.getValue(); + optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); + } + } + } + + OptionsParser.parseOptions(optionSettings, values, loader); + return new OptionValues(values); + } + } + + @Override + public OptionValues getOptions() { + return HOTSPOT_OPTIONS; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index 401169124f4..48b849572e1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -22,22 +22,21 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; -import static jdk.vm.ci.common.InitTimer.timer; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; -import org.graalvm.compiler.api.collections.CollectionsProvider; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.core.common.GraalOptions; @@ -48,15 +47,18 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.DebugValuesPrinter; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.graph.DefaultNodeCollectionsProvider; -import org.graalvm.compiler.graph.NodeCollectionsProvider; +import org.graalvm.compiler.hotspot.CompilationStatistics.Options; import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.stack.StackIntrospection; @@ -87,27 +89,31 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { private final HotSpotBackend hostBackend; private DebugValuesPrinter debugValuesPrinter; + private final List snippetCounterGroups; - private final Map, HotSpotBackend> backends = new HashMap<>(); + private final EconomicMap, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); private final GraalHotSpotVMConfig config; + private final OptionValues options; + /** * @param compilerConfigurationFactory factory for the compiler configuration - * {@link CompilerConfigurationFactory#selectFactory(String)} + * {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)} */ @SuppressWarnings("try") - HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) { - + HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); - CompileTheWorldOptions.overrideWithNativeOptions(config); + config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); // Only set HotSpotPrintInlining if it still has its default value (false). - if (GraalOptions.HotSpotPrintInlining.getValue() == false) { - GraalOptions.HotSpotPrintInlining.setValue(config.printInlining); + if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { + options = new OptionValues(initialOptions, HotSpotPrintInlining, true); + } else { + options = initialOptions; } + snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); BackendMap backendMap = compilerConfigurationFactory.createBackendMap(); @@ -136,16 +142,16 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } } - if (Log.getValue() == null && !areScopedGlobalMetricsEnabled() && Dump.getValue() == null && Verify.getValue() == null) { - if (MethodFilter.getValue() != null && !Debug.isEnabled()) { + if (Log.getValue(options) == null && !areScopedGlobalMetricsEnabled(options) && Dump.getValue(options) == null && Verify.getValue(options) == null) { + if (MethodFilter.getValue(options) != null && !Debug.isEnabled()) { TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null"); } } if (Debug.isEnabled()) { - DebugEnvironment.initialize(TTY.out, hostBackend.getProviders().getSnippetReflection()); + DebugEnvironment.ensureInitialized(options, hostBackend.getProviders().getSnippetReflection()); - String summary = DebugValueSummary.getValue(); + String summary = DebugValueSummary.getValue(options); if (summary != null) { switch (summary) { case "Name": @@ -160,12 +166,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } if (Debug.areUnconditionalCountersEnabled() || Debug.areUnconditionalTimersEnabled() || Debug.areUnconditionalMethodMetricsEnabled() || - (Debug.isEnabled() && areScopedGlobalMetricsEnabled()) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { + (Debug.isEnabled() && areScopedGlobalMetricsEnabled(options)) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { // This must be created here to avoid loading the DebugValuesPrinter class // during shutdown() which in turn can cause a deadlock int mmPrinterType = 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() ? 1 : 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null ? 2 : 0; + mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) ? 1 : 0; + mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null ? 2 : 0; switch (mmPrinterType) { case 0: debugValuesPrinter = new DebugValuesPrinter(); @@ -188,17 +194,17 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { // Complete initialization of backends try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { - hostBackend.completeInitialization(jvmciRuntime); + hostBackend.completeInitialization(jvmciRuntime, options); } - for (HotSpotBackend backend : backends.values()) { + for (HotSpotBackend backend : backends.getValues()) { if (backend != hostBackend) { try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { - backend.completeInitialization(jvmciRuntime); + backend.completeInitialization(jvmciRuntime, options); } } } - BenchmarkCounters.initialize(jvmciRuntime); + BenchmarkCounters.initialize(jvmciRuntime, options); assert checkArrayIndexScaleInvariants(); @@ -223,20 +229,33 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return config; } + @Override + public OptionValues getOptions() { + return options; + } + + @Override + public Group createSnippetCounterGroup(String name) { + if (snippetCounterGroups != null) { + Group group = new Group(name); + snippetCounterGroups.add(group); + return group; + } + return null; + } + @Override public String getName() { return getClass().getSimpleName(); } - private final NodeCollectionsProvider nodeCollectionsProvider = new DefaultNodeCollectionsProvider(); - @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { if (clazz == RuntimeProvider.class) { return (T) this; - } else if (clazz == CollectionsProvider.class || clazz == NodeCollectionsProvider.class) { - return (T) nodeCollectionsProvider; + } else if (clazz == OptionValues.class) { + return (T) options; } else if (clazz == StackIntrospection.class) { return (T) this; } else if (clazz == SnippetReflectionProvider.class) { @@ -258,10 +277,6 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return backends.get(arch); } - public Map, HotSpotBackend> getBackends() { - return Collections.unmodifiableMap(backends); - } - private long runtimeStartTime; /** @@ -269,18 +284,24 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { * * @param phase the execution phase being entered */ - static void phaseTransition(String phase) { - CompilationStatistics.clear(phase); + void phaseTransition(String phase) { + if (Options.UseCompilationStatistics.getValue(options)) { + CompilationStatistics.clear(phase); + } } void shutdown() { if (debugValuesPrinter != null) { - debugValuesPrinter.printDebugValues(); + debugValuesPrinter.printDebugValues(options); } phaseTransition("final"); - SnippetCounter.printGroups(TTY.out().out()); - BenchmarkCounters.shutdown(runtime(), runtimeStartTime); + if (snippetCounterGroups != null) { + for (Group group : snippetCounterGroups) { + TTY.out().out().println(group); + } + } + BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime); } void clearMeters() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java index f662ab8757c..7a2582cc18f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -24,6 +24,8 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.TargetDescription; @@ -33,7 +35,7 @@ import jdk.vm.ci.code.TargetDescription; /** * Configuration information for the HotSpot Graal runtime. */ -public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider { +public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider, Group.Factory { default TargetDescription getTarget() { return getHostBackend().getTarget(); @@ -51,6 +53,11 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid GraalHotSpotVMConfig getVMConfig(); + /** + * Gets the option values associated with this runtime. + */ + OptionValues getOptions(); + /** * Determines if the VM is currently bootstrapping the JVMCI compiler. */ diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java index 64d1073e80a..097f555a93a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java @@ -59,7 +59,7 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { @Override public void notifyBootstrapFinished() { runtime.notifyBootstrapFinished(); - if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue()) { + if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue(runtime.getOptions())) { runtime.clearMeters(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java index 8df8a9c82ae..f58232fbe79 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java @@ -29,12 +29,11 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; import org.graalvm.compiler.hotspot.stubs.Stub; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.common.InitTimer; @@ -49,16 +48,12 @@ import jdk.vm.ci.runtime.JVMCICompiler; public abstract class HotSpotHostBackend extends HotSpotBackend { /** - * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()} or - * {@link DeoptimizationStub#deoptimizationHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()}. */ public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class); /** - * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()} or - * {@link UncommonTrapStub#uncommonTrapHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()}. */ public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class); @@ -71,16 +66,16 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { @Override @SuppressWarnings("try") - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final HotSpotProviders providers = getProviders(); HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); try (InitTimer st = timer("foreignCalls.initialize")) { - foreignCalls.initialize(providers); + foreignCalls.initialize(providers, options); } try (InitTimer st = timer("lowerer.initialize")) { - lowerer.initialize(providers, config); + lowerer.initialize(options, providers, config); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java index 8b91390bfb9..a0d05bd48df 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot; -import java.util.List; +import java.util.ArrayList; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.InstructionCounter; @@ -80,7 +80,7 @@ public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase } public void doBlock(AbstractBlockBase block) { - List instructions = lir.getLIRforBlock(block); + ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java index 11383b77a7c..f3543dd8fed 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.hotspot; -import java.util.Map; - -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -32,6 +29,8 @@ import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -52,14 +51,14 @@ public class HotSpotLIRGenerationResult extends LIRGenerationResult { * Map from debug infos that need to be updated with callee save information to the operations * that provide the information. */ - private Map calleeSaveInfo = CollectionsFactory.newMap(); + private EconomicMap calleeSaveInfo = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); public HotSpotLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, CallingConvention callingConvention, Object stub) { super(compilationId, lir, frameMapBuilder, callingConvention); this.stub = stub; } - public Map getCalleeSaveInfo() { + public EconomicMap getCalleeSaveInfo() { return calleeSaveInfo; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java index f2f45e24fec..dab337092da 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java @@ -22,26 +22,18 @@ */ package org.graalvm.compiler.hotspot; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; import org.graalvm.compiler.hotspot.replacements.EncodedSymbolConstant; import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -70,65 +62,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); - /** - * Emits code for a {@link SaveAllRegistersNode}. - * - * @return a {@link SaveRegistersOp} operation - */ - SaveRegistersOp emitSaveAllRegisters(); - - /** - * Emits code for a {@link LeaveCurrentStackFrameNode}. - * - * @param saveRegisterOp saved registers - */ - default void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveDeoptimizedStackFrameNode}. - * - * @param frameSize - * @param initialInfo - */ - default void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link EnterUnpackFramesStackFrameNode}. - * - * @param framePc - * @param senderSp - * @param senderFp - * @param saveRegisterOp - */ - default void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveUnpackFramesStackFrameNode}. - * - * @param saveRegisterOp - */ - default void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link PushInterpreterFrameNode}. - * - * @param frameSize - * @param framePc - * @param senderSp - * @param initialInfo - */ - default void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - throw GraalError.unimplemented(); - } - /** * Emits code for a {@link LoadConstantIndirectlyNode}. * @@ -227,29 +160,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { throw GraalError.unimplemented(); } - /** - * Emits code for a {@link UncommonTrapCallNode}. - * - * @param trapRequest - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link DeoptimizationFetchUnrollInfoCallNode}. - * - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - /** * Gets a stack slot for a lock at a given lock nesting depth. */ diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java index 7dc534a29a9..b09b5bd2237 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.core.match.MatchableNode; import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -43,7 +42,4 @@ public interface HotSpotNodeLIRBuilder { } void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc); - - void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java index a8b7982ebf4..324040792fd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java @@ -29,7 +29,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.ArrayList; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index dc52af69b7a..e1e265de8d1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.hotspot.word.HotSpotOperation; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.ReplacementsImpl; @@ -37,8 +38,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class HotSpotReplacementsImpl extends ReplacementsImpl { - public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(providers, snippetReflection, bytecodeProvider, target); + public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + super(options, providers, snippetReflection, bytecodeProvider, target); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java index 8bd1710f9e7..0a8fe40f6f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + import java.io.PrintStream; import org.graalvm.compiler.debug.TTYStreamProvider; @@ -36,13 +38,13 @@ public class HotSpotTTYStreamProvider implements TTYStreamProvider { // @formatter:off @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying " + - "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) - public static final PrintStreamOption LogFile = new PrintStreamOption(); + "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) + public static final PrintStreamOptionKey LogFile = new PrintStreamOptionKey(); // @formatter:on } @Override public PrintStream getStream() { - return Options.LogFile.getStream(); + return Options.LogFile.getStream(HOTSPOT_OPTIONS); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index abae7a39549..5f2dc097c95 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.hotspot; import java.util.Formatter; +import java.util.Objects; /** * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API @@ -37,10 +38,11 @@ import java.util.Formatter; class JVMCIVersionCheck { private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 23; + private static final int JVMCI8_MIN_MINOR_VERSION = 24; - // Will be updated once an ea build with the required JVMCI API is available. - private static final int JVMCI9_MIN_EA_BUILD = 143; + // MAX_VALUE indicates that no current EA version is compatible with Graal. + // Note: Keep README.md in sync with the EA version support checked here. + private static final int JVMCI9_MIN_EA_BUILD = 161; private static void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); @@ -116,7 +118,11 @@ class JVMCIVersionCheck { if (build >= JVMCI9_MIN_EA_BUILD) { return; } - failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) { + failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n"); + } else { + failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + } return; } failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java similarity index 58% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java index e2b389f8b96..821767a67bd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java @@ -28,10 +28,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.UniquePathUtilities; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -39,32 +38,20 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; /** * An option that encapsulates and configures a print stream. */ -public class PrintStreamOption extends OptionValue { +public class PrintStreamOptionKey extends OptionKey { - public PrintStreamOption() { + public PrintStreamOptionKey() { super(null); } /** - * The print stream to which output will be written. - * - * Declared {@code volatile} to enable safe use of double-checked locking in - * {@link #getStream()} and {@link #setValue(Object)}. - */ - private volatile PrintStream ps; - - /** - * Replaces any instance of %p with an identifying name such as a process ID extracted from - * {@link RuntimeMXBean#getName()} and any instance of %t with the value of - * {@link System#currentTimeMillis()}. + * Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean + * name. * * @return the name of the file to log to */ - private String getFilename() { - String name = getValue(); - if (name.contains("%t")) { - name = name.replaceAll("%t", String.valueOf(UniquePathUtilities.getGlobalTimeStamp())); - } + private String getFilename(OptionValues options) { + String name = getValue(options); if (name.contains("%p")) { String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); try { @@ -126,45 +113,26 @@ public class PrintStreamOption extends OptionValue { * Gets the print stream configured by this option. If no file is configured, the print stream * will output to HotSpot's {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream. */ - public PrintStream getStream() { - if (ps == null) { - if (getValue() != null) { - synchronized (this) { - if (ps == null) { - try { - final boolean enableAutoflush = true; - ps = new PrintStream(new FileOutputStream(getFilename()), enableAutoflush); - /* - * Add the JVM and Java arguments to the log file to help identity it. - */ - String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); - ps.println("VM Arguments: " + inputArguments); - String cmd = System.getProperty("sun.java.command"); - if (cmd != null) { - ps.println("sun.java.command=" + cmd); - } - } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't open file: " + getValue(), e); - } - } + public PrintStream getStream(OptionValues options) { + if (getValue(options) != null) { + try { + final boolean enableAutoflush = true; + PrintStream ps = new PrintStream(new FileOutputStream(getFilename(options)), enableAutoflush); + /* + * Add the JVM and Java arguments to the log file to help identity it. + */ + String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); + ps.println("VM Arguments: " + inputArguments); + String cmd = System.getProperty("sun.java.command"); + if (cmd != null) { + ps.println("sun.java.command=" + cmd); } - } else { - ps = new PrintStream(new DelayedOutputStream()); + return ps; + } catch (FileNotFoundException e) { + throw new RuntimeException("couldn't open file: " + getValue(options), e); } + } else { + return new PrintStream(new DelayedOutputStream()); } - return ps; - } - - @Override - public void setValue(Object v) { - if (ps != null) { - synchronized (this) { - if (ps != null) { - ps.close(); - ps = null; - } - } - } - super.setValue(v); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java index 700fa99e65f..ada3106e7d4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java @@ -46,9 +46,9 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.UniquePathUtilities; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -93,26 +93,26 @@ public class BenchmarkCounters { //@formatter:off @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown", type = OptionType.Debug) - public static final OptionValue GenericDynamicCounters = new OptionValue<>(false); + public static final OptionKey GenericDynamicCounters = new OptionKey<>(false); @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds", type = OptionType.Debug) - public static final OptionValue TimedDynamicCounters = new OptionValue<>(-1); + public static final OptionKey TimedDynamicCounters = new OptionKey<>(-1); @Option(help = "Turn on the benchmark counters, and listen for specific patterns on System.out/System.err:%n" + "Format: (err|out),start pattern,end pattern (~ matches multiple digits)%n" + "Examples:%n" + " dacapo = 'err, starting =====, PASSED in'%n" + " specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug) - public static final OptionValue BenchmarkDynamicCounters = new OptionValue<>(null); + public static final OptionKey BenchmarkDynamicCounters = new OptionKey<>(null); @Option(help = "Use grouping separators for number printing", type = OptionType.Debug) - public static final OptionValue DynamicCountersPrintGroupSeparator = new OptionValue<>(true); + public static final OptionKey DynamicCountersPrintGroupSeparator = new OptionKey<>(true); @Option(help = "Print in human readable format", type = OptionType.Debug) - public static final OptionValue DynamicCountersHumanReadable = new OptionValue<>(true); + public static final OptionKey DynamicCountersHumanReadable = new OptionKey<>(true); @Option(help = "Benchmark counters log file (default is stdout)", type = OptionType.Debug) - public static final OptionValue BenchmarkCountersFile = new OptionValue<>(null); + public static final OptionKey BenchmarkCountersFile = new OptionKey<>(null); @Option(help = "Dump dynamic counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpDynamic = new StableOptionValue<>(true); + public static final OptionKey BenchmarkCountersDumpDynamic = new OptionKey<>(true); @Option(help = "Dump static counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpStatic = new StableOptionValue<>(false); + public static final OptionKey BenchmarkCountersDumpStatic = new OptionKey<>(false); //@formatter:on } @@ -168,24 +168,24 @@ public class BenchmarkCounters { return counter; } - private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { + private static synchronized void dump(OptionValues options, PrintStream out, double seconds, long[] counters, int maxRows) { if (!counterMap.isEmpty()) { - if (Options.DynamicCountersHumanReadable.getValue()) { + if (Options.DynamicCountersHumanReadable.getValue(options)) { out.println("====== dynamic counters (" + counterMap.size() + " in total) ======"); } TreeSet set = new TreeSet<>(); counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); for (String group : set) { if (group != null) { - if (Options.BenchmarkCountersDumpStatic.getValue()) { - dumpCounters(out, seconds, counters, true, group, maxRows); + if (Options.BenchmarkCountersDumpStatic.getValue(options)) { + dumpCounters(options, out, seconds, counters, true, group, maxRows); } - if (Options.BenchmarkCountersDumpDynamic.getValue()) { - dumpCounters(out, seconds, counters, false, group, maxRows); + if (Options.BenchmarkCountersDumpDynamic.getValue(options)) { + dumpCounters(options, out, seconds, counters, false, group, maxRows); } } } - if (Options.DynamicCountersHumanReadable.getValue()) { + if (Options.DynamicCountersHumanReadable.getValue(options)) { out.println("============================"); } @@ -197,7 +197,7 @@ public class BenchmarkCounters { delta = counters; } - private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { + private static synchronized void dumpCounters(OptionValues options, PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { // collect the numbers long[] array; @@ -213,8 +213,8 @@ public class BenchmarkCounters { } } Set> counterEntrySet = counterMap.entrySet(); - if (Options.DynamicCountersHumanReadable.getValue()) { - dumpHumanReadable(out, seconds, staticCounter, group, maxRows, array, counterEntrySet); + if (Options.DynamicCountersHumanReadable.getValue(options)) { + dumpHumanReadable(options, out, seconds, staticCounter, group, maxRows, array, counterEntrySet); } else { dumpComputerReadable(out, staticCounter, group, array, counterEntrySet); } @@ -224,7 +224,8 @@ public class BenchmarkCounters { return nameGroup.substring(0, nameGroup.length() - group.length() - 1); } - private static void dumpHumanReadable(PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, Set> counterEntrySet) { + private static void dumpHumanReadable(OptionValues options, PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, + Set> counterEntrySet) { // sort the counters by putting them into a sorted map TreeMap sorted = new TreeMap<>(); long sum = 0; @@ -252,7 +253,7 @@ public class BenchmarkCounters { cnt--; } - String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue() ? "%,19d" : "%19d"; + String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue(options) ? "%,19d" : "%19d"; if (staticCounter) { out.println("=========== " + group + " (static counters):"); for (Map.Entry entry : sorted.entrySet()) { @@ -348,7 +349,7 @@ public class BenchmarkCounters { } } - public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime) { + public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final class BenchmarkCountersOutputStream extends CallbackOutputStream { private long startTime; @@ -376,15 +377,15 @@ public class BenchmarkCounters { if (waitingForEnd) { waitingForEnd = false; running = false; - BenchmarkCounters.dump(getPrintStream(), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + BenchmarkCounters.dump(options, getPrintStream(options), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } break; } } } - if (Options.BenchmarkDynamicCounters.getValue() != null) { - String[] arguments = Options.BenchmarkDynamicCounters.getValue().split(","); + if (Options.BenchmarkDynamicCounters.getValue(options) != null) { + String[] arguments = Options.BenchmarkDynamicCounters.getValue(options).split(","); if (arguments.length == 0 || (arguments.length % 3) != 0) { throw new GraalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); } @@ -399,23 +400,23 @@ public class BenchmarkCounters { } enabled = true; } - if (Options.GenericDynamicCounters.getValue()) { + if (Options.GenericDynamicCounters.getValue(options)) { enabled = true; } - if (Options.TimedDynamicCounters.getValue() > 0) { + if (Options.TimedDynamicCounters.getValue(options) > 0) { Thread thread = new Thread() { long lastTime = System.nanoTime(); - PrintStream out = getPrintStream(); + PrintStream out = getPrintStream(options); @Override public void run() { while (true) { try { - Thread.sleep(Options.TimedDynamicCounters.getValue()); + Thread.sleep(Options.TimedDynamicCounters.getValue(options)); } catch (InterruptedException e) { } long time = System.nanoTime(); - dump(out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); + dump(options, out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); lastTime = time; } } @@ -430,16 +431,16 @@ public class BenchmarkCounters { } } - public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, long compilerStartTime) { - if (Options.GenericDynamicCounters.getValue()) { - dump(getPrintStream(), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options, long compilerStartTime) { + if (Options.GenericDynamicCounters.getValue(options)) { + dump(options, getPrintStream(options), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } } - private static PrintStream getPrintStream() { - if (Options.BenchmarkCountersFile.getValue() != null) { + private static PrintStream getPrintStream(OptionValues options) { + if (Options.BenchmarkCountersFile.getValue(options) != null) { try { - Path path = UniquePathUtilities.getPathGlobal(Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); + Path path = UniquePathUtilities.getPathGlobal(options, Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); TTY.println("Writing benchmark counters to '%s'", path); return new PrintStream(path.toFile()); } catch (FileNotFoundException e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 47ed91d18b3..3552d89ca06 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; @@ -31,13 +32,11 @@ import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_LAYOUT_HELPER_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION; -import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; - import java.lang.ref.Reference; import org.graalvm.compiler.api.directives.GraalDirectives; @@ -53,12 +52,9 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -70,6 +66,10 @@ import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; +import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; @@ -102,7 +102,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -119,13 +118,14 @@ import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode; @@ -134,6 +134,7 @@ import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; @@ -148,6 +149,7 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider; import org.graalvm.compiler.replacements.nodes.AssertionNode; @@ -194,25 +196,29 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - super.initialize(providers, providers.getSnippetReflection()); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + super.initialize(options, runtime, providers, providers.getSnippetReflection()); assert target == providers.getCodeCache().getTarget(); - instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); - newObjectSnippets = new NewObjectSnippets.Templates(providers, target, config); - monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); - unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); - assertionSnippets = new AssertionSnippets.Templates(providers, target); - arraycopySnippets = new ArrayCopySnippets.Templates(providers, target); - stringToBytesSnippets = new StringToBytesSnippets.Templates(providers, target); - hashCodeSnippets = new HashCodeSnippets.Templates(providers, target); - if (GeneratePIC.getValue()) { - resolveConstantSnippets = new ResolveConstantSnippets.Templates(providers, target); - profileSnippets = new ProfileSnippets.Templates(providers, target); + instanceofSnippets = new InstanceOfSnippets.Templates(options, runtime, providers, target); + newObjectSnippets = new NewObjectSnippets.Templates(options, runtime, providers, target, config); + monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers, target, config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, providers, target); + unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, providers, target); + assertionSnippets = new AssertionSnippets.Templates(options, providers, target); + arraycopySnippets = new ArrayCopySnippets.Templates(options, runtime, providers, target); + stringToBytesSnippets = new StringToBytesSnippets.Templates(options, providers, target); + hashCodeSnippets = new HashCodeSnippets.Templates(options, providers, target); + if (GeneratePIC.getValue(options)) { + resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, providers, target); + profileSnippets = new ProfileSnippets.Templates(options, providers, target); } - providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); + providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, providers, target)); + } + + public MonitorSnippets.Templates getMonitorSnippets() { + return monitorSnippets; } @Override @@ -303,7 +309,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } } else if (n instanceof MonitorExitNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((MonitorExitNode) n, tool); + monitorSnippets.lower((MonitorExitNode) n, registers, tool); } } else if (n instanceof ArrayCopyNode) { arraycopySnippets.lower((ArrayCopyNode) n, tool); @@ -395,7 +401,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getHub().isConstant(); AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().klassLayoutHelperOffset); - n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE))); + n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), null, BarrierType.NONE))); } private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { @@ -406,7 +412,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getHub().isConstant(); AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), null, BarrierType.NONE)); n.replaceAtUsagesAndDelete(read); } @@ -418,7 +424,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getValue().isConstant(); AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getVMConfig().klassOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), null, BarrierType.NONE)); n.replaceAtUsagesAndDelete(read); } @@ -428,15 +434,15 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - GuardingNode receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, ((ObjectStamp) receiver.stamp()).join(StampFactory.objectNonNull()), (ValueNode) receiverNullCheck)); + ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); parameters.set(0, nonNullReceiver); receiver = nonNullReceiver; } JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); LoweredCallTargetNode loweredCallTarget = null; - if (InlineVTableStubs.getValue() && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { + OptionValues options = graph.getOptions(); + if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { @@ -512,7 +518,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + protected void lowerUnsafeLoadNode(RawLoadNode load, LoweringTool tool) { StructuredGraph graph = load.graph(); if (!(load instanceof GuardedUnsafeLoadNode) && !graph.getGuardsStage().allowsFloatingGuards() && addReadBarrier(load)) { unsafeLoadSnippets.lower(load, tool); @@ -559,23 +565,64 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider ParameterNode buffer = graph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(StampFactory.forKind(runtime.getTarget().wordJavaKind)))); ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); migrationEnd.setStateAfter(osrStart.stateAfter()); - newStart.setNext(migrationEnd); FixedNode next = osrStart.next(); osrStart.setNext(null); migrationEnd.setNext(next); graph.setStart(newStart); - // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) - int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + final int wordSize = target.wordSize; + + // @formatter:off + // taken from c2 locals_addr = osr_buf + (max_locals-1)*wordSize) + // @formatter:on + int localsOffset = (graph.method().getMaxLocals() - 1) * wordSize; for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) { int size = osrLocal.getStackKind().getSlotCount(); - int offset = localsOffset - (osrLocal.index() + size - 1) * 8; + int offset = localsOffset - (osrLocal.index() + size - 1) * wordSize; AddressNode address = createOffsetAddress(graph, buffer, offset); ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } + + // @formatter:off + // taken from c2 monitors_addr = osr_buf + (max_locals+mcnt*2-1)*wordSize); + // @formatter:on + final int lockCount = osrStart.stateAfter().locksSize(); + final int locksOffset = (graph.method().getMaxLocals() + lockCount * 2 - 1) * wordSize; + + // first initialize the lock slots for all enters with the displaced marks read from the + // buffer + for (OSRMonitorEnterNode osrMonitorEnter : graph.getNodes(OSRMonitorEnterNode.TYPE)) { + MonitorIdNode monitorID = osrMonitorEnter.getMonitorId(); + OSRLockNode lock = (OSRLockNode) osrMonitorEnter.object(); + final int index = lock.index(); + + final int offsetDisplacedHeader = locksOffset - ((index * 2) + 1) * wordSize; + final int offsetLockObject = locksOffset - index * 2 * wordSize; + + // load the displaced mark from the osr buffer + AddressNode addressDisplacedHeader = createOffsetAddress(graph, buffer, offsetDisplacedHeader); + ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(), BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, loadDisplacedHeader); + + // we need to initialize the stack slot for the lock + BeginLockScopeNode beginLockScope = graph.add(new BeginLockScopeNode(lock.getStackKind(), monitorID.getLockDepth())); + graph.addBeforeFixed(migrationEnd, beginLockScope); + + // write the displaced mark to the correct stack slot + AddressNode addressDisplacedMark = createOffsetAddress(graph, beginLockScope, runtime.getVMConfig().basicLockDisplacedHeaderOffset); + WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, writeStackSlot); + + // load the lock object from the osr buffer + AddressNode addressLockObject = createOffsetAddress(graph, buffer, offsetLockObject); + ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(), BarrierType.NONE)); + lock.replaceAndDelete(loadObject); + graph.addBeforeFixed(migrationEnd, loadObject); + } + osrStart.replaceAtUsagesAndDelete(newStart); } } @@ -616,7 +663,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) { - if (OmitHotExceptionStacktrace.getValue()) { + if (OmitHotExceptionStacktrace.getValue(node.getOptions())) { if (throwCachedException(node)) { return; } @@ -640,7 +687,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider graph.replaceFixedWithFixed(node, foreignCallNode); } - private boolean addReadBarrier(UnsafeLoadNode load) { + private boolean addReadBarrier(RawLoadNode load) { if (runtime.getVMConfig().useG1GC && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getStackKind() == JavaKind.Object && load.accessKind() == JavaKind.Object && !StampTool.isPointerAlwaysNull(load.object())) { ResolvedJavaType type = StampTool.typeOrNull(load.object()); @@ -659,7 +706,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - Stamp methodStamp = MethodPointerStamp.method(); + Stamp methodStamp = MethodPointerStamp.methodNonNull(); AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset); ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE)); return metaspaceMethod; @@ -734,9 +781,4 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider public int arrayLengthOffset() { return runtime.getVMConfig().arrayOopDescLengthOffset(); } - - @Override - public LocationIdentity initLocationIdentity() { - return INIT_LOCATION; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java index ec7de3fad23..2b7ccf97ab4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java @@ -25,8 +25,9 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -34,17 +35,17 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { public static class Options { @Option(help = "Do profiling and callbacks to tiered runtime", type = OptionType.User)// - public static final OptionValue TieredAOT = new OptionValue<>(false); + public static final OptionKey TieredAOT = new OptionKey<>(false); @Option(help = "Invocation notification frequency", type = OptionType.Expert)// - public static final OptionValue TierAInvokeNotifyFreqLog = new OptionValue<>(13); + public static final OptionKey TierAInvokeNotifyFreqLog = new OptionKey<>(13); @Option(help = "Inlinee invocation notification frequency (-1 means count, but do not notify)", type = OptionType.Expert)// - public static final OptionValue TierAInvokeInlineeNotifyFreqLog = new OptionValue<>(-1); + public static final OptionKey TierAInvokeInlineeNotifyFreqLog = new OptionKey<>(-1); @Option(help = "Invocation profile probability", type = OptionType.Expert)// - public static final OptionValue TierAInvokeProfileProbabilityLog = new OptionValue<>(8); + public static final OptionKey TierAInvokeProfileProbabilityLog = new OptionKey<>(8); @Option(help = "Backedge notification frequency", type = OptionType.Expert)// - public static final OptionValue TierABackedgeNotifyFreqLog = new OptionValue<>(16); + public static final OptionKey TierABackedgeNotifyFreqLog = new OptionKey<>(16); @Option(help = "Backedge profile probability", type = OptionType.Expert)// - public static final OptionValue TierABackedgeProfileProbabilityLog = new OptionValue<>(12); + public static final OptionKey TierABackedgeProfileProbabilityLog = new OptionKey<>(12); } @Override @@ -53,27 +54,27 @@ public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { } @Override - public int invokeNotifyFreqLog() { - return Options.TierAInvokeNotifyFreqLog.getValue(); + public int invokeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeNotifyFreqLog.getValue(options); } @Override - public int invokeInlineeNotifyFreqLog() { - return Options.TierAInvokeInlineeNotifyFreqLog.getValue(); + public int invokeInlineeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeInlineeNotifyFreqLog.getValue(options); } @Override - public int invokeProfilePobabilityLog() { - return Options.TierAInvokeProfileProbabilityLog.getValue(); + public int invokeProfilePobabilityLog(OptionValues options) { + return Options.TierAInvokeProfileProbabilityLog.getValue(options); } @Override - public int backedgeNotifyFreqLog() { - return Options.TierABackedgeNotifyFreqLog.getValue(); + public int backedgeNotifyFreqLog(OptionValues options) { + return Options.TierABackedgeNotifyFreqLog.getValue(options); } @Override - public int backedgeProfilePobabilityLog() { - return Options.TierABackedgeProfileProbabilityLog.getValue(); + public int backedgeProfilePobabilityLog(OptionValues options) { + return Options.TierABackedgeProfileProbabilityLog.getValue(options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java index f7f99c64208..588982ebfb5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.core.common.spi.JavaConstantFieldProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; import jdk.vm.ci.meta.MetaAccessProvider; @@ -47,7 +48,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { if (!config.foldStableValues) { return false; } - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -59,7 +60,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { @Override protected boolean isFinalField(ResolvedJavaField field, ConstantFieldTool tool) { - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -68,7 +69,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { private static final String SystemClassName = "Ljava/lang/System;"; - protected boolean isStaticFieldConstant(ResolvedJavaField field) { + protected boolean isStaticFieldConstant(ResolvedJavaField field, @SuppressWarnings("unused") OptionValues options) { ResolvedJavaType declaringClass = field.getDeclaringClass(); return declaringClass.isInitialized() && !declaringClass.getName().equals(SystemClassName); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java index 76b663c6b8b..e3a51de05c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java @@ -22,7 +22,10 @@ */ package org.graalvm.compiler.hotspot.meta; +import java.util.List; + import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.meta.Value; @@ -35,4 +38,9 @@ public interface HotSpotForeignCallsProvider extends ForeignCallsProvider { * Gets the registers that must be saved across a foreign call into the runtime. */ Value[] getNativeABICallerSaveRegisters(); + + /** + * Gets the set of stubs linked to by the foreign calls represented by this object. + */ + List getStubs(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index f2ddb967437..9b1f6e44056 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LocationIdentity; @@ -40,8 +40,10 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.stubs.ForeignCallStub; import org.graalvm.compiler.hotspot.stubs.Stub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -64,7 +66,7 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC protected final HotSpotJVMCIRuntimeProvider jvmciRuntime; protected final HotSpotGraalRuntimeProvider runtime; - protected final Map foreignCalls = new HashMap<>(); + protected final EconomicMap foreignCalls = EconomicMap.create(); protected final MetaAccessProvider metaAccess; protected final CodeCacheProvider codeCache; protected final WordTypes wordTypes; @@ -144,9 +146,9 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC * cannot be re-executed. * @param killedLocations the memory locations killed by the foreign call */ - public void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, - LocationIdentity... killedLocations) { - ForeignCallStub stub = new ForeignCallStub(jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); + public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, + boolean reexecutable, LocationIdentity... killedLocations) { + ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); linkage.setCompiledStub(stub); @@ -198,4 +200,17 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC public LIRKind getValueKind(JavaKind javaKind) { return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind); } + + @Override + public List getStubs() { + List stubs = new ArrayList<>(); + for (HotSpotForeignCallLinkage linkage : foreignCalls.getValues()) { + if (linkage.isCompiledStub()) { + Stub stub = linkage.getStub(); + assert stub != null; + stubs.add(stub); + } + } + return stubs; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java index 659a79ee6d3..f9709bce633 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.ImmutableCodeLazy.isCalledForSnippets; -import static org.graalvm.compiler.hotspot.stubs.SnippetStub.SnippetGraphUnderConstruction; import java.util.ArrayList; import java.util.List; @@ -32,18 +30,13 @@ import java.util.List; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.options.StableOptionValue; -import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.runtime.JVMCI; /** * Extends {@link HotSpotConstantFieldProvider} to override the implementation of @@ -57,25 +50,55 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } @Override - public T readConstantField(ResolvedJavaField field, ConstantFieldTool tool) { - assert !ImmutableCode.getValue() || isCalledForSnippets(metaAccess) || SnippetGraphUnderConstruction.get() != null || - FieldReadEnabledInImmutableCode.get() == Boolean.TRUE : tool.getReceiver(); - if (!field.isStatic() && field.getName().equals("value")) { - if (getStableOptionValueType().isInstance(tool.getReceiver())) { - JavaConstant ret = tool.readValue(); - return tool.foldConstant(ret); - } - } - - return super.readConstantField(field, tool); + protected boolean isStaticFieldConstant(ResolvedJavaField field, OptionValues options) { + return super.isStaticFieldConstant(field, options) && (!ImmutableCode.getValue(options) || isEmbeddableField(field)); } /** - * In AOT mode, some fields should never be embedded even for snippets/replacements. + * The set of fields whose values cannot be constant folded in ImmutableCode mode. This is + * volatile to support double-checked locking lazy initialization. */ - @Override - protected boolean isStaticFieldConstant(ResolvedJavaField field) { - return super.isStaticFieldConstant(field) && (!ImmutableCode.getValue() || ImmutableCodeLazy.isEmbeddable(field)); + private volatile List nonEmbeddableFields; + + protected boolean isEmbeddableField(ResolvedJavaField field) { + if (nonEmbeddableFields == null) { + synchronized (this) { + if (nonEmbeddableFields == null) { + List fields = new ArrayList<>(); + try { + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); + + Class characterCacheClass = Character.class.getDeclaredClasses()[0]; + assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); + + Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; + assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); + + Class shortCacheClass = Short.class.getDeclaredClasses()[0]; + assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); + + Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; + assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); + + Class longCacheClass = Long.class.getDeclaredClasses()[0]; + assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); + + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); + } catch (SecurityException | NoSuchFieldException e) { + throw new GraalError(e); + } + nonEmbeddableFields = fields; + } + } + } + return !nonEmbeddableFields.contains(field); } @Override @@ -112,18 +135,10 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi private final MetaAccessProvider metaAccess; - private ResolvedJavaType cachedStableOptionValueType; private ResolvedJavaType cachedHotSpotVMConfigType; private ResolvedJavaType cachedSnippetCounterType; private ResolvedJavaType cachedNodeClassType; - private ResolvedJavaType getStableOptionValueType() { - if (cachedStableOptionValueType == null) { - cachedStableOptionValueType = metaAccess.lookupJavaType(StableOptionValue.class); - } - return cachedStableOptionValueType; - } - private ResolvedJavaType getHotSpotVMConfigType() { if (cachedHotSpotVMConfigType == null) { cachedHotSpotVMConfigType = metaAccess.lookupJavaType(GraalHotSpotVMConfig.class); @@ -144,102 +159,4 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } return cachedNodeClassType; } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal FieldReadEnabledInImmutableCode = assertionsEnabled() ? new ThreadLocal<>() : null; - - /** - * Compares two {@link StackTraceElement}s for equality, ignoring differences in - * {@linkplain StackTraceElement#getLineNumber() line number}. - */ - private static boolean equalsIgnoringLine(StackTraceElement left, StackTraceElement right) { - return left.getClassName().equals(right.getClassName()) && left.getMethodName().equals(right.getMethodName()) && left.getFileName().equals(right.getFileName()); - } - - /** - * Separate out the static initialization of {@linkplain #isEmbeddable(ResolvedJavaField) - * embeddable fields} to eliminate cycles between clinit and other locks that could lead to - * deadlock. Static code that doesn't call back into type or field machinery is probably ok but - * anything else should be made lazy. - */ - static class ImmutableCodeLazy { - - /** - * If the compiler is configured for AOT mode, {@link #readConstantField} should be only - * called for snippets or replacements. - */ - static boolean isCalledForSnippets(MetaAccessProvider metaAccess) { - assert ImmutableCode.getValue(); - ResolvedJavaMethod makeGraphMethod = null; - ResolvedJavaMethod initMethod = null; - try { - Class rjm = ResolvedJavaMethod.class; - makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm)); - initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalError(e); - } - StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(0); - StackTraceElement initSTE = initMethod.asStackTraceElement(0); - - StackTraceElement[] stackTrace = new Exception().getStackTrace(); - for (StackTraceElement element : stackTrace) { - // Ignoring line numbers should not weaken this check too much while at - // the same time making it more robust against source code changes - if (equalsIgnoringLine(makeGraphSTE, element) || equalsIgnoringLine(initSTE, element)) { - return true; - } - } - return false; - } - - /** - * Determine if it's ok to embed the value of {@code field}. - */ - static boolean isEmbeddable(ResolvedJavaField field) { - assert ImmutableCode.getValue(); - return !embeddableFields.contains(field); - } - - private static final List embeddableFields = new ArrayList<>(); - static { - try { - MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); - - Class characterCacheClass = Character.class.getDeclaredClasses()[0]; - assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); - - Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; - assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); - - Class shortCacheClass = Short.class.getDeclaredClasses()[0]; - assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); - - Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; - assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); - - Class longCacheClass = Long.class.getDeclaredClasses()[0]; - assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); - - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); - } catch (SecurityException | NoSuchFieldException e) { - throw new GraalError(e); - } - } - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 0fc8323be99..5b0af5573b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -22,15 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; - -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; - import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MutableCallSite; import java.lang.invoke.VolatileCallSite; @@ -53,8 +51,8 @@ import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; -import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; +import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; import org.graalvm.compiler.hotspot.replacements.ObjectSubstitutions; import org.graalvm.compiler.hotspot.replacements.ReflectionGetCallerClassNode; @@ -90,9 +88,8 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.InlineDuringParsingPlugin; -import org.graalvm.compiler.replacements.InlineGraalDirectivesPlugin; import org.graalvm.compiler.replacements.MethodHandlePlugin; import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; import org.graalvm.compiler.replacements.ReplacementsImpl; @@ -137,7 +134,8 @@ public class HotSpotGraphBuilderPlugins { plugins.appendTypePlugin(nodePlugin); plugins.appendNodePlugin(nodePlugin); - if (GeneratePIC.getValue()) { + OptionValues options = replacements.getOptions(); + if (GeneratePIC.getValue(options)) { // AOT needs to filter out bad invokes plugins.prependNodePlugin(new NodePlugin() { @Override @@ -174,14 +172,13 @@ public class HotSpotGraphBuilderPlugins { } plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); plugins.appendInlineInvokePlugin(replacements); - if (InlineDuringParsing.getValue()) { + if (InlineDuringParsing.getValue(options)) { plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin()); } - plugins.appendInlineInvokePlugin(new InlineGraalDirectivesPlugin()); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); - if (TieredAOT.getValue()) { + if (TieredAOT.getValue(options)) { plugins.setProfilingPlugin(new HotSpotAOTProfilingPlugin()); } } @@ -191,14 +188,13 @@ public class HotSpotGraphBuilderPlugins { @Override public void run() { BytecodeProvider replacementBytecodeProvider = replacements.getReplacementBytecodeProvider(); - registerObjectPlugins(invocationPlugins, replacementBytecodeProvider); + registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider); registerClassPlugins(plugins, config, replacementBytecodeProvider); registerSystemPlugins(invocationPlugins, foreignCalls); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider); registerCallSitePlugins(invocationPlugins); registerReflectionPlugins(invocationPlugins, replacementBytecodeProvider); registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider); - registerStableOptionPlugins(invocationPlugins, snippetReflection); registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider); registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider); registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider); @@ -213,9 +209,9 @@ public class HotSpotGraphBuilderPlugins { return plugins; } - private static void registerObjectPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) { Registration r = new Registration(plugins, Object.class, bytecodeProvider); - if (!GeneratePIC.getValue()) { + if (!GeneratePIC.getValue(options)) { // FIXME: clone() requires speculation and requires a fix in here (to check that // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is // an instantiation of IntrinsicGraphBuilder using a constructor that sets @@ -327,7 +323,7 @@ public class HotSpotGraphBuilderPlugins { */ private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) { // ConstantPool.constantPoolOop is in fact the holder class. - ClassGetHubNode klass = b.add(new ClassGetHubNode(constantPoolOop)); + ClassGetHubNode klass = b.add(new ClassGetHubNode(b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None))); boolean notCompressible = false; AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset)))); @@ -442,21 +438,6 @@ public class HotSpotGraphBuilderPlugins { r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class); } - private static void registerStableOptionPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection) { - Registration r = new Registration(plugins, StableOptionValue.class); - r.register1("getValue", Receiver.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - if (receiver.isConstant()) { - StableOptionValue option = snippetReflection.asObject(StableOptionValue.class, (JavaConstant) receiver.get().asConstant()); - b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReflection.forObject(option.getValue()), b.getMetaAccess())); - return true; - } - return false; - } - }); - } - public static final String cbcEncryptName; public static final String cbcDecryptName; public static final String aesEncryptName; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 726087805f3..ea346eb1b8b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -22,15 +22,11 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; @@ -38,8 +34,9 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_ import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_MULTIPLY; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_SQUARE; import static org.graalvm.compiler.hotspot.HotSpotBackend.MULTIPLY_TO_LEN; @@ -47,16 +44,16 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.MUL_ADD; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR; import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; @@ -77,7 +74,6 @@ import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITORE import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITOREXIT; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_ARRAY; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE; -import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; import static org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions.THREAD_IS_INTERRUPTED; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPOSTCALL; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL; @@ -99,20 +95,17 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.Una import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; -import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub; import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub; import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub; @@ -125,8 +118,10 @@ import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; import org.graalvm.compiler.hotspot.stubs.VerifyOopStub; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -183,7 +178,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - private void registerArraycopyDescriptor(Map descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { + private void registerArraycopyDescriptor(EconomicMap descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { ForeignCallDescriptor desc = descMap.get(routine); if (desc == null) { desc = buildDescriptor(kind, aligned, disjoint, uninit, killAny, routine); @@ -231,7 +226,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall * but only within the same Kind. For instance short and char are the same copy routines but * they kill different memory so they still have to be distinct. */ - Map descMap = new HashMap<>(); + EconomicMap descMap = EconomicMap.create(); registerArraycopyDescriptor(descMap, kind, false, false, uninit, false, routine); registerArraycopyDescriptor(descMap, kind, true, false, uninit, false, alignedRoutine); registerArraycopyDescriptor(descMap, kind, false, true, uninit, false, disjointRoutine); @@ -245,12 +240,10 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig c = runtime.getVMConfig(); - if (!PreferGraalStubs.getValue()) { - registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - } + registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); @@ -269,17 +262,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, NOT_REEXECUTABLE, any()); - - /* - * We cannot use LEAF_SP here because on some architectures we have to align the stack - * manually before calling into the VM. See {@link - * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}. - */ - registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); CreateExceptionStub.registerForeignCalls(c, this); @@ -290,47 +274,47 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new NewArrayStub(providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new ExceptionHandlerStub(providers, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); - link(new VerifyOopStub(providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); - link(new ArrayStoreExceptionStub(providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new ClassCastExceptionStub(providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new NullPointerExceptionStub(providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new OutOfBoundsExceptionStub(providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); + link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); + link(new ArrayStoreExceptionStub(options, providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new ClassCastExceptionStub(options, providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NullPointerExceptionStub(options, providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); - linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + linkForeignCall(options, providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE); + linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE); + linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); - linkForeignCall(providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); } // Cannot be a leaf as VM acquires Thread_lock which requires thread_in_vm state - linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); registerArrayCopy(JavaKind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 6c7f0088cd5..8ec609f8a42 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -73,7 +73,7 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroNode.class.getSimpleName(), node, plugin); } } - if (GraalOptions.ImmutableCode.getValue()) { + if (GraalOptions.ImmutableCode.getValue(b.getOptions())) { for (Node node : newNodes) { if (node.hasUsages() && node instanceof ConstantNode) { ConstantNode c = (ConstantNode) node; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java index 95b21a0d201..c133a5f8f4c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java @@ -24,11 +24,12 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.spi.LoweringProvider; +import org.graalvm.compiler.options.OptionValues; /** * HotSpot implementation of {@link LoweringProvider}. */ public interface HotSpotLoweringProvider extends LoweringProvider { - void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config); + void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java index 10b2255a3dc..0fbdf510ac4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.nodes.ConstantNode; @@ -90,7 +89,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (object.isConstant()) { JavaConstant asJavaConstant = object.asJavaConstant(); if (tryReadField(b, field, asJavaConstant)) { @@ -106,7 +105,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (tryReadField(b, field, null)) { return true; } @@ -118,21 +117,11 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { } private static boolean tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - // FieldReadEnabledInImmutableCode is non null only if assertions are enabled - if (FieldReadEnabledInImmutableCode != null && ImmutableCode.getValue()) { - FieldReadEnabledInImmutableCode.set(Boolean.TRUE); - try { - return tryConstantFold(b, field, object); - } finally { - FieldReadEnabledInImmutableCode.set(null); - } - } else { - return tryConstantFold(b, field, object); - } + return tryConstantFold(b, field, object); } private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object); + ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object, b.getOptions()); if (result != null) { result = b.getGraph().unique(result); b.push(field.getJavaKind(), result); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java index d0dad67e740..311e4199e97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java @@ -33,28 +33,29 @@ import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { public static class Options { @Option(help = "Emit profiling of invokes", type = OptionType.Expert)// - public static final OptionValue ProfileInvokes = new OptionValue<>(true); + public static final OptionKey ProfileInvokes = new OptionKey<>(true); @Option(help = "Emit profiling of backedges", type = OptionType.Expert)// - public static final OptionValue ProfileBackedges = new OptionValue<>(true); + public static final OptionKey ProfileBackedges = new OptionKey<>(true); } - public abstract int invokeNotifyFreqLog(); + public abstract int invokeNotifyFreqLog(OptionValues options); - public abstract int invokeInlineeNotifyFreqLog(); + public abstract int invokeInlineeNotifyFreqLog(OptionValues options); - public abstract int invokeProfilePobabilityLog(); + public abstract int invokeProfilePobabilityLog(OptionValues options); - public abstract int backedgeNotifyFreqLog(); + public abstract int backedgeNotifyFreqLog(OptionValues options); - public abstract int backedgeProfilePobabilityLog(); + public abstract int backedgeProfilePobabilityLog(OptionValues options); @Override public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { @@ -64,8 +65,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileInvokes.getValue() && !method.isClassInitializer()) { - ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(), invokeProfilePobabilityLog())); + OptionValues options = builder.getOptions(); + if (Options.ProfileInvokes.getValue(options) && !method.isClassInitializer()) { + ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(options), invokeProfilePobabilityLog(options))); p.setStateBefore(frameState); } } @@ -73,8 +75,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && targetBci <= bci) { - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), bci, targetBci)); + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && targetBci <= bci) { + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), bci, targetBci)); p.setStateBefore(frameState); } } @@ -82,7 +85,8 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && (falseBranchBci <= bci || trueBranchBci <= bci)) { + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && (falseBranchBci <= bci || trueBranchBci <= bci)) { boolean negate = false; int targetBci = trueBranchBci; if (falseBranchBci <= bci) { @@ -95,7 +99,7 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { ValueNode trueValue = builder.append(ConstantNode.forBoolean(!negate)); ValueNode falseValue = builder.append(ConstantNode.forBoolean(negate)); ConditionalNode branchCondition = builder.append(new ConditionalNode(condition, trueValue, falseValue)); - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), branchCondition, bci, targetBci)); + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), branchCondition, bci, targetBci)); p.setStateBefore(frameState); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java index 32d7281b31a..2f194448d57 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java @@ -22,17 +22,16 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; import java.util.ListIterator; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; @@ -50,16 +49,19 @@ import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.AddressLoweringPhase; import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.SuitesCreator; @@ -83,22 +85,22 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } @Override - public Suites createSuites() { - Suites ret = defaultSuitesCreator.createSuites(); + public Suites createSuites(OptionValues options) { + Suites ret = defaultSuitesCreator.createSuites(options); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { // lowering introduces class constants, therefore it must be after lowering ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); - if (VerifyPhases.getValue()) { + if (VerifyPhases.getValue(options)) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { // EliminateRedundantInitializationPhase must happen before the first lowering. ListIterator> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); highTierLowering.previous(); highTierLowering.add(new EliminateRedundantInitializationPhase()); - if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue()) { - highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue())); + if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { + highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); } ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase()); @@ -111,11 +113,15 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); - if (VerifyPhases.getValue()) { + if (VerifyPhases.getValue(options)) { ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); } - ret.getLowTier().findPhase(ExpandLogicPhase.class).add(new AddressLoweringPhase(addressLowering)); + ListIterator> findPhase = ret.getLowTier().findPhase(FixReadsPhase.class); + if (findPhase == null) { + findPhase = ret.getLowTier().findPhase(ExpandLogicPhase.class); + } + findPhase.add(new AddressLoweringPhase(addressLowering)); return ret; } @@ -131,7 +137,7 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { * encoding and decoding process work correctly. The decoding performs canonicalization during * decoding, so the decoded graph can be different than the encoded graph - we cannot check them * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the - * encoding itself}, i.e., performs a decoding without canoncialization and checks the graphs + * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs * for equality. */ private boolean appendGraphEncoderTest(PhaseSuite suite) { @@ -141,8 +147,8 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), - context.getStampProvider(), !ImmutableCode.getValue(), runtime.getTarget().arch); - StructuredGraph targetGraph = new StructuredGraph(graph.method(), AllowAssumptions.YES, INVALID_COMPILATION_ID); + context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()), runtime.getTarget().arch); + StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build(); graphDecoder.decode(targetGraph, encodedGraph); } @@ -169,9 +175,9 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - LIRSuites suites = defaultSuitesCreator.createLIRSuites(); - String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(); + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); + String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); if (profileInstructions != null) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java index cb47a5ad446..aac6581fef3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java @@ -40,7 +40,6 @@ import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; import org.graalvm.compiler.hotspot.word.PointerCastNode; -import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; @@ -149,11 +148,6 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); } ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE)); - /* - * The read must not float outside its block otherwise it may float above an - * explicit zero check on its base address. - */ - read.setGuard(AbstractBeginNode.prevBegin(read)); b.push(returnKind, read); break; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java index d3c5b867643..07c188d9414 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,6 +60,11 @@ public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implement this.lockDepth = lockDepth; } + public BeginLockScopeNode(JavaKind kind, int lockDepth) { + super(TYPE, StampFactory.forKind(kind)); + this.lockDepth = lockDepth; + } + @Override public boolean hasSideEffect() { return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/CompressionNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/CompressionNode.java index 104859a0397..d8cfc1e1959 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/CompressionNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/CompressionNode.java @@ -26,13 +26,13 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; @@ -176,7 +176,7 @@ public final class CompressionNode extends UnaryNode implements ConvertNode, LIR @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(tool.getOptions())) { // We always want uncompressed constants return this; } @@ -214,9 +214,12 @@ public final class CompressionNode extends UnaryNode implements ConvertNode, LIR default: throw GraalError.shouldNotReachHere(); } + gen.setResult(this, result); } - @NodeIntrinsic - public static native Object compression(@ConstantNodeParameter CompressionOp op, Object object, @ConstantNodeParameter CompressEncoding encoding); + @Override + public boolean mayNullCheckSkipConversion() { + return true; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java deleted file mode 100644 index 06a26f6f08b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code {@code Deoptimization::fetch_unroll_info}. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DeoptimizationFetchUnrollInfoCallNode.class); - @Input SaveAllRegistersNode registerSaver; - @Input ValueNode mode; - protected final ForeignCallsProvider foreignCalls; - - public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.mode = mode; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizationFetchUnrollInfoCall(gen.operand(getMode()), getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word fetchUnrollInfo(long registerSaver, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java index db08803de12..4c2f3782a91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.asm.NumUtil.roundUp; +import static org.graalvm.compiler.core.common.NumUtil.roundUp; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java deleted file mode 100644 index 74eac1ede7e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.InputType.Association; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.java.CompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -/** - * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a - * {@link StateSplit} and it {@linkplain #compareAndSwap(Address, Word, Word, LocationIdentity)} - * returns either the expected value or the compared against value instead of a boolean. - */ -@NodeInfo(allowedUsageTypes = Memory, cycles = CYCLES_30, size = SIZE_8) -public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DirectCompareAndSwapNode.class); - @Input(Association) AddressNode address; - @Input ValueNode expectedValue; - @Input ValueNode newValue; - - protected final LocationIdentity locationIdentity; - - public DirectCompareAndSwapNode(ValueNode address, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { - super(TYPE, expected.stamp()); - this.address = (AddressNode) address; - this.expectedValue = expected; - this.newValue = newValue; - this.locationIdentity = locationIdentity; - } - - public AddressNode getAddress() { - return address; - } - - public ValueNode expectedValue() { - return expectedValue; - } - - public ValueNode newValue() { - return newValue; - } - - @Override - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this); - } - - /** - * Compares an expected value with the actual value in a location denoted by an address. Iff - * they are same, {@code newValue} is placed into the location and the {@code expectedValue} is - * returned. Otherwise, the actual value is returned. All of the above is performed in one - * atomic hardware transaction. - * - * @param address the address to be atomically tested and updated - * @param expectedValue if this value is currently in the field, perform the swap - * @param newValue the new value to put into the field - * @return either {@code expectedValue} or the actual value - */ - @NodeIntrinsic - public static native Word compareAndSwap(Address address, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java deleted file mode 100644 index 2685973c15e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_10; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to enter a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_20, size = SIZE_10) -public final class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(EnterUnpackFramesStackFrameNode.class); - - @Input ValueNode framePc; - @Input ValueNode senderSp; - @Input ValueNode senderFp; - @Input SaveAllRegistersNode registerSaver; - - public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value operandValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value senderFpValue = gen.operand(senderFp); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue, getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp, long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java index 8d0575fe6b5..d03186b38ee 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java @@ -170,20 +170,20 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab @Override public Node canonical(CanonicalizerTool tool) { if (markId == 0) { - return ConstantNode.forBoolean(!GeneratePIC.getValue()); + return ConstantNode.forBoolean(!GeneratePIC.getValue(tool.getOptions())); } - if (!GeneratePIC.getValue()) { - if (markId == cardTableAddressMark(config)) { + if (!GeneratePIC.getValue(tool.getOptions())) { + if (markId == config.MARKID_CARD_TABLE_ADDRESS) { return ConstantNode.forLong(config.cardtableStartAddress); - } else if (markId == heapTopAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_TOP_ADDRESS) { return ConstantNode.forLong(config.heapTopAddress); - } else if (markId == heapEndAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_END_ADDRESS) { return ConstantNode.forLong(config.heapEndAddress); - } else if (markId == crcTableAddressMark(config)) { + } else if (markId == config.MARKID_CRC_TABLE_ADDRESS) { return ConstantNode.forLong(config.crcTableAddress); - } else if (markId == logOfHeapRegionGrainBytesMark(config)) { + } else if (markId == config.MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES) { return ConstantNode.forInt(config.logOfHRGrainBytes); - } else if (markId == inlineContiguousAllocationSupportedMark(config)) { + } else if (markId == config.MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) { return ConstantNode.forBoolean(config.inlineContiguousAllocationSupported); } else { assert false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java deleted file mode 100644 index 45e076f64e2..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave (pop) the current low-level stack frame. This operation also removes the - * return address if its location is on the stack. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveCurrentStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveCurrentStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveCurrentStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java deleted file mode 100644 index 843dbc65947..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node - * is only used in {@link DeoptimizationStub}. - */ -@NodeInfo(cycles = CYCLES_3, size = SIZE_2) -public final class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveDeoptimizedStackFrameNode.class); - @Input ValueNode frameSize; - @Input ValueNode initialInfo; - - public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java deleted file mode 100644 index 2c54a4a2c83..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveUnpackFramesStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveUnpackFramesStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java deleted file mode 100644 index e779da57db9..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(cycles = CYCLES_8, size = SIZE_6) -public final class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(PushInterpreterFrameNode.class); - @Input ValueNode framePc; - @Input ValueNode frameSize; - @Input ValueNode senderSp; - @Input ValueNode initialInfo; - - public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.framePc = framePc; - this.senderSp = senderSp; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value framePcValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo); - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java deleted file mode 100644 index e0a25037e31..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import jdk.vm.ci.meta.JavaKind; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Saves all allocatable registers. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(SaveAllRegistersNode.class); - protected SaveRegistersOp saveRegistersOp; - - public SaveAllRegistersNode() { - super(TYPE, StampFactory.forKind(JavaKind.Long)); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters(); - } - - /** - * @return the map from registers to the stack locations in they are saved - */ - public SaveRegistersOp getSaveRegistersOp() { - assert saveRegistersOp != null : "saved registers op has not yet been created"; - return saveRegistersOp; - } - - /** - * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter - * has access to the {@linkplain SaveRegistersOp#getMap register save map} - */ - @NodeIntrinsic - public static native long saveAllRegisters(); - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java deleted file mode 100644 index 061dc110df3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Canonicalizable; -import org.graalvm.compiler.graph.spi.CanonicalizerTool; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; - -@NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}, cycles = CYCLES_0, size = SIZE_0) -public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable, Node.ValueNumberable { - - public static final NodeClass TYPE = NodeClass.create(SnippetLocationProxyNode.class); - @Input(InputType.Unchecked) ValueNode location; - - public SnippetLocationProxyNode(ValueNode location) { - super(TYPE, StampFactory.object()); - this.location = location; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - return location.isAllowedUsageType(InputType.Association) ? location : this; - } - - @NodeIntrinsic - public static native GuardingNode location(Object location); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java deleted file mode 100644 index 2cee5fc0185..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(UncommonTrapCallNode.class); - @Input ValueNode trapRequest; - @Input ValueNode mode; - @Input SaveAllRegistersNode registerSaver; - protected final ForeignCallsProvider foreignCalls; - - public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); - this.trapRequest = trapRequest; - this.mode = mode; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value trapRequestValue = gen.operand(trapRequest); - Value modeValue = gen.operand(getMode()); - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, modeValue, getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word uncommonTrap(long registerSaver, int trapRequest, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java index 257fc5a7fca..babce55c047 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -56,14 +56,14 @@ public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implement protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyFixedNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyFixedNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java index 10c3c9337aa..f9d265283f4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -55,14 +55,14 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java index 1b8180b082c..2bb79d8a2c1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java index 017feacf64d..c4a98c87741 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java index 9d5e015bf4c..e90ac81a919 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.hotspot.nodes.profiling; -import jdk.vm.ci.meta.ResolvedJavaMethod; - import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -34,14 +32,16 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; + +import jdk.vm.ci.meta.ResolvedJavaMethod; @NodeInfo public class ProfileNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static class Options { @Option(help = "Control probabilistic profiling on AMD64", type = OptionType.Expert)// - public static final OptionValue ProbabilisticProfiling = new OptionValue<>(true); + public static final OptionKey ProbabilisticProfiling = new OptionKey<>(true); } public static final NodeClass TYPE = NodeClass.create(ProfileNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java index 51ef44ea120..ee34fee657e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java @@ -24,11 +24,11 @@ package org.graalvm.compiler.hotspot.nodes.type; import java.util.Objects; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.hotspot.CompressEncoding; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java index 4db514de7e1..53a2298fb81 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java @@ -59,6 +59,11 @@ public abstract class MetaspacePointerStamp extends AbstractPointerStamp { return true; } + @Override + public Stamp join(Stamp other) { + return defaultPointerJoin(other); + } + @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { throw GraalError.shouldNotReachHere("metaspace pointer has no Java type"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/NarrowOopStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/NarrowOopStamp.java index 5f96876b0a8..a0ebc20c350 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/NarrowOopStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/NarrowOopStamp.java @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.hotspot.nodes.type; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.hotspot.CompressEncoding; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java index bb5d0f71bdd..fa6a21512a9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java @@ -26,12 +26,12 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java index 84f0f33ecb5..2c6d3488c33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java @@ -24,9 +24,11 @@ package org.graalvm.compiler.hotspot.phases; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -35,17 +37,30 @@ import org.graalvm.compiler.loop.phases.LoopTransformations; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractLocalNode; import org.graalvm.compiler.nodes.EntryMarkerNode; import org.graalvm.compiler.nodes.EntryProxyNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; +import org.graalvm.compiler.nodes.java.AccessMonitorNode; +import org.graalvm.compiler.nodes.java.MonitorEnterNode; +import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; @@ -53,6 +68,24 @@ import jdk.vm.ci.runtime.JVMCICompiler; public class OnStackReplacementPhase extends Phase { + public static class Options { + // @formatter:off + @Option(help = "Deoptimize OSR compiled code when the OSR entry loop is finished " + + "if there is no mature profile available for the rest of the method.", type = OptionType.Debug) + public static final OptionKey DeoptAfterOSR = new OptionKey<>(true); + @Option(help = "Support OSR compilations with locks. If DeoptAfterOSR is true we can per definition not have " + + "unbalaced enter/extis mappings. If DeoptAfterOSR is false insert artificial monitor enters after " + + "the OSRStart to have balanced enter/exits in the graph.", type = OptionType.Debug) + public static final OptionKey SupportOSRWithLocks = new OptionKey<>(true); + // @formatter:on + } + + private static final DebugCounter OsrWithLocksCount = Debug.counter("OSRWithLocks"); + + private static boolean supportOSRWithLocks(OptionValues options) { + return Options.SupportOSRWithLocks.getValue(options); + } + @Override protected void run(StructuredGraph graph) { if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) { @@ -61,10 +94,29 @@ public class OnStackReplacementPhase extends Phase { assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty(); return; } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial"); + Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); + EntryMarkerNode osr; int maxIterations = -1; int iterations = 0; + + final EntryMarkerNode originalOSRNode = getEntryMarker(graph); + final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode); + final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode); + + if (originalOSRLoop == null) { + /* + * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we + * cannot decide where to deopt and which framestate will be used. In the worst case the + * framestate of the OSR entry would be used. + */ + throw new PermanentBailoutException("OSR compilation without OSR entry loop."); + } + + if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) { + throw new PermanentBailoutException("OSR with locks disabled."); + } + do { osr = getEntryMarker(graph); LoopsData loops = new LoopsData(graph); @@ -73,6 +125,7 @@ public class OnStackReplacementPhase extends Phase { if (l == null) { break; } + iterations++; if (maxIterations == -1) { maxIterations = l.getDepth(); @@ -104,26 +157,81 @@ public class OnStackReplacementPhase extends Phase { graph.setStart(osrStart); osrStart.setStateAfter(osrState); - for (int i = 0; i < osrState.localsSize(); i++) { - ValueNode value = osrState.localAt(i); + Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after setting OSR start"); + final int localsSize = osrState.localsSize(); + final int locksSize = osrState.locksSize(); + + for (int i = 0; i < localsSize + locksSize; i++) { + ValueNode value = null; + if (i >= localsSize) { + value = osrState.lockAt(i - localsSize); + } else { + value = osrState.localAt(i); + } if (value instanceof EntryProxyNode) { EntryProxyNode proxy = (EntryProxyNode) value; /* * we need to drop the stamp since the types we see during OSR may be too precise * (if a branch was not parsed for example). */ - proxy.replaceAndDelete(graph.addOrUnique(new OSRLocalNode(i, proxy.stamp().unrestricted()))); + Stamp s = proxy.stamp().unrestricted(); + AbstractLocalNode osrLocal = null; + if (i >= localsSize) { + osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, s)); + } else { + osrLocal = graph.addOrUnique(new OSRLocalNode(i, s)); + } + proxy.replaceAndDelete(osrLocal); } else { assert value == null || value instanceof OSRLocalNode; } } + osr.replaceAtUsages(InputType.Guard, osrStart); - assert osr.usages().isEmpty(); - + Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); GraphUtil.killCFG(start); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); + + if (currentOSRWithLocks) { + OsrWithLocksCount.increment(); + for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) { + MonitorIdNode id = osrState.monitorIdAt(i); + ValueNode lockedObject = osrState.lockAt(i); + OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id)); + for (Node usage : id.usages()) { + if (usage instanceof AccessMonitorNode) { + AccessMonitorNode access = (AccessMonitorNode) usage; + access.setObject(lockedObject); + } + } + FixedNode oldNext = osrStart.next(); + oldNext.replaceAtPredecessor(null); + osrMonitorEnter.setNext(oldNext); + osrStart.setNext(osrMonitorEnter); + } + Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After inserting OSR monitor enters"); + /* + * Ensure balanced monitorenter - monitorexit + * + * Ensure that there is no monitor exit without a monitor enter in the graph. If there + * is one this can only be done by bytecode as we have the monitor enter before the OSR + * loop but the exit in a path of the loop that must be under a condition, else it will + * throw an IllegalStateException anyway in the 2.iteration + */ + for (MonitorExitNode exit : graph.getNodes(MonitorExitNode.TYPE)) { + MonitorIdNode id = exit.getMonitorId(); + if (id.usages().filter(MonitorEnterNode.class).count() != 1) { + throw new PermanentBailoutException("Unbalanced monitor enter-exit in OSR compilation with locks. Object is locked before the loop but released inside the loop."); + } + } + } + Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); + new DeadCodeEliminationPhase(Required).apply(graph); + /* + * There must not be any parameter nodes left after OSR compilation. + */ + assert graph.getNodes(ParameterNode.TYPE).count() == 0 : "OSR Compilation contains references to parameters."; } private static EntryMarkerNode getEntryMarker(StructuredGraph graph) { @@ -135,15 +243,26 @@ public class OnStackReplacementPhase extends Phase { if (osrNodes.count() > 1) { throw new GraalError("Multiple OnStackReplacementNodes generated"); } - if (osr.stateAfter().locksSize() != 0) { - throw new PermanentBailoutException("OSR with locks not supported"); - } if (osr.stateAfter().stackSize() != 0) { throw new PermanentBailoutException("OSR with stack entries not supported: %s", osr.stateAfter().toString(Verbosity.Debugger)); } return osr; } + private static LoopBeginNode osrLoop(EntryMarkerNode osr) { + // Check that there is an OSR loop for the OSR begin + LoopsData loops = new LoopsData(osr.graph()); + Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); + if (l == null) { + return null; + } + return (LoopBeginNode) l.getHeader().getBeginNode(); + } + + private static boolean osrWithLocks(EntryMarkerNode osr) { + return osr.stateAfter().locksSize() != 0; + } + @Override public float codeSizeIncrease() { return 5.0f; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java index a252994fe7b..f837b9127e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java @@ -35,8 +35,8 @@ import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; +import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; @@ -63,8 +63,8 @@ public class WriteBarrierAdditionPhase extends Phase { } else if (n instanceof LoweredAtomicReadAndWriteNode) { LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n; addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph); - } else if (n instanceof LoweredCompareAndSwapNode) { - addCASBarriers((LoweredCompareAndSwapNode) n, graph); + } else if (n instanceof AbstractCompareAndSwapNode) { + addCASBarriers((AbstractCompareAndSwapNode) n, graph); } else if (n instanceof ArrayRangeWriteNode) { ArrayRangeWriteNode node = (ArrayRangeWriteNode) n; if (node.isObjectArray()) { @@ -116,7 +116,7 @@ public class WriteBarrierAdditionPhase extends Phase { case PRECISE: boolean precise = barrierType == BarrierType.PRECISE; if (config.useG1GC) { - if (!node.isInitialization()) { + if (!node.getLocationIdentity().isInit()) { addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); } addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph); @@ -150,7 +150,7 @@ public class WriteBarrierAdditionPhase extends Phase { } } - private void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) { + private void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) { BarrierType barrierType = node.getBarrierType(); switch (barrierType) { case NONE: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java index 1cd9421ffe6..639292f3772 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.hotspot.nodes.ArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.ObjectWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LoopBeginNode; @@ -40,7 +41,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; @@ -48,6 +49,7 @@ import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.Phase; /** @@ -73,6 +75,12 @@ public class WriteBarrierVerificationPhase extends Phase { private void processWrites(StructuredGraph graph) { for (Node node : graph.getNodes()) { if (isObjectWrite(node) || isObjectArrayRangeWrite(node)) { + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (StampTool.isPointerAlwaysNull(writeNode.value())) { + continue; + } + } validateWrite(node); } } @@ -92,7 +100,7 @@ public class WriteBarrierVerificationPhase extends Phase { while (iterator.hasNext()) { Node currentNode = iterator.next(); if (isSafepoint(currentNode)) { - throw new AssertionError("Write barrier must be present " + write); + throw new AssertionError("Write barrier must be present " + write.toString(Verbosity.All) + " / " + write.inputs()); } if (useG1GC()) { if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) { @@ -114,7 +122,13 @@ public class WriteBarrierVerificationPhase extends Phase { private boolean hasAttachedBarrier(FixedWithNextNode node) { final Node next = node.next(); final Node previous = node.predecessor(); - final boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (writeNode.getLocationIdentity().isInit()) { + validatePreBarrier = false; + } + } if (isObjectWrite(node)) { return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous)); } else if (isObjectArrayRangeWrite(node)) { @@ -150,6 +164,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean isSafepoint(Node node) { + if (node instanceof FixedAccessNode) { + // Implicit null checks on reads or writes do not count. + return false; + } /* * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write @@ -161,8 +179,8 @@ public class WriteBarrierVerificationPhase extends Phase { private static ValueNode getValueWritten(FixedWithNextNode write) { if (write instanceof WriteNode) { return ((WriteNode) write).value(); - } else if (write instanceof LoweredCompareAndSwapNode) { - return ((LoweredCompareAndSwapNode) write).getNewValue(); + } else if (write instanceof LogicCompareAndSwapNode) { + return ((LogicCompareAndSwapNode) write).getNewValue(); } else if (write instanceof LoweredAtomicReadAndWriteNode) { return ((LoweredAtomicReadAndWriteNode) write).getNewValue(); } else { @@ -171,10 +189,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) { - assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; + assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; if (!barrier.usePrecise()) { if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) { - return ((OffsetAddressNode) barrier.getAddress()).getBase() == ((OffsetAddressNode) write.getAddress()).getBase(); + return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase()); } } return barrier.getAddress() == write.getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java index 8f1efa35b38..fbf81adcc66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java @@ -31,8 +31,9 @@ import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; @@ -44,11 +45,11 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { public static class Options { // @formatter:off @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningDepthToSizeRate = new OptionValue<>(2.5); + public static final OptionKey AOTInliningDepthToSizeRate = new OptionKey<>(2.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMaximum = new OptionValue<>(300); + public static final OptionKey AOTInliningSizeMaximum = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMinimum = new OptionValue<>(50); + public static final OptionKey AOTInliningSizeMinimum = new OptionKey<>(50); // @formatter:on } @@ -56,8 +57,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { super(hints); } - protected double maxInliningSize(int inliningDepth) { - return Math.max(Options.AOTInliningSizeMaximum.getValue() / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue()), Options.AOTInliningSizeMinimum.getValue()); + protected double maxInliningSize(int inliningDepth, OptionValues options) { + return Math.max(Options.AOTInliningSizeMaximum.getValue(options) / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue(options)), Options.AOTInliningSizeMinimum.getValue(options)); } @Override @@ -74,7 +75,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { final double probability = invocation.probability(); final double relevance = invocation.relevance(); - if (InlineEverything.getValue()) { + OptionValues options = info.graph().getOptions(); + if (InlineEverything.getValue(options)) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return true; } @@ -92,12 +94,12 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { double inliningBonus = getInliningBonus(info); int nodes = info.determineNodeCount(); - if (nodes < TrivialInliningSize.getValue() * inliningBonus) { + if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); return true; } - double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth) * inliningBonus)); + double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus)); if (nodes <= maximumNodes) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, nodes, maximumNodes); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java index 46d8be12171..8295dd81fe2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java @@ -142,7 +142,8 @@ public class EliminateRedundantInitializationPhase extends BasePhase nodesInCurrent = e.getValue(); if (nodesInCurrent != null) { // if the list is null, the initializer has already been // eliminated. - for (Block d : currentBlock.getDominated()) { + Block d = currentBlock.getFirstDominated(); + while (d != null) { ArrayList nodesInDominated = blockToInits.get(d); if (nodesInDominated != null) { // if the list is null, the initializer has // already been eliminated. @@ -151,6 +152,7 @@ public class EliminateRedundantInitializationPhase extends BasePhase { public static class Options { @Option(help = "Profile simple methods", type = OptionType.Expert)// - public static final OptionValue ProfileSimpleMethods = new OptionValue<>(true); + public static final OptionKey ProfileSimpleMethods = new OptionKey<>(true); @Option(help = "Maximum number of nodes in a graph for a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodGraphSize = new OptionValue<>(256); + public static final OptionKey SimpleMethodGraphSize = new OptionKey<>(256); @Option(help = "Maximum number of calls in a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodCalls = new OptionValue<>(1); + public static final OptionKey SimpleMethodCalls = new OptionKey<>(1); @Option(help = "Maximum number of indirect calls in a simple moethod", type = OptionType.Expert)// - public static final OptionValue SimpleMethodIndirectCalls = new OptionValue<>(0); + public static final OptionKey SimpleMethodIndirectCalls = new OptionKey<>(0); } @@ -88,12 +88,12 @@ public class FinalizeProfileNodesPhase extends BasePhase { // Hacky heuristic to determine whether we want any profiling in this method. // The heuristic is applied after the graph is fully formed and before the first lowering. private static boolean simpleMethodHeuristic(StructuredGraph graph) { - if (Options.ProfileSimpleMethods.getValue()) { + if (Options.ProfileSimpleMethods.getValue(graph.getOptions())) { return false; } // Check if the graph is smallish.. - if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue()) { + if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue(graph.getOptions())) { return false; } @@ -103,7 +103,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } // Check if method has calls - if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue()) { + if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue(graph.getOptions())) { return false; } @@ -160,7 +160,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } assignInlineeInvokeFrequencies(graph); - if (ProfileNode.Options.ProbabilisticProfiling.getValue()) { + if (ProfileNode.Options.ProbabilisticProfiling.getValue(graph.getOptions())) { assignRandomSources(graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java index 3dfb4210356..4073b8701a2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java @@ -42,7 +42,7 @@ import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; @@ -120,7 +120,7 @@ public class AESCryptSubstitutions { private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) { checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); - Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); @@ -128,7 +128,7 @@ public class AESCryptSubstitutions { encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java index a99dbd4c535..516bada415e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.hotspot.nodes.StubStartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -53,15 +54,15 @@ public class AssertionSnippets implements Snippets { public static final ForeignCallDescriptor ASSERTION_VM_MESSAGE_C = new ForeignCallDescriptor("assertionVmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class); @Snippet - public static void assertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void assertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @Snippet - public static void stubAssertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void stubAssertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @@ -74,14 +75,14 @@ public class AssertionSnippets implements Snippets { private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion"); private final SnippetInfo stubAssertion = snippet(AssertionSnippets.class, "stubAssertion"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(AssertionNode assertionNode, LoweringTool tool) { StructuredGraph graph = assertionNode.graph(); Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("value", assertionNode.value()); + args.add("condition", assertionNode.condition()); args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"); template(args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java index 218b4f0508e..b7c816d95f4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java @@ -57,7 +57,10 @@ public class CRC32Substitutions { return config.crcTableAddress; } - @MethodSubstitution + /** + * Removed in 9. + */ + @MethodSubstitution(optional = true) static int update(int crc, int b) { final long crcTableRawAddress = GraalHotSpotVMConfigNode.crcTableAddress(); @@ -69,7 +72,10 @@ public class CRC32Substitutions { return ~result; } - @MethodSubstitution + /** + * Removed in 9. + */ + @MethodSubstitution(optional = true) static int updateBytes(int crc, byte[] buf, int off, int len) { Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); @@ -84,7 +90,10 @@ public class CRC32Substitutions { return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } - @MethodSubstitution + /** + * Removed in 9. + */ + @MethodSubstitution(optional = true) static int updateByteBuffer(int crc, long addr, int off, int len) { Word bufAddr = Word.unsigned(addr).add(off); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java index ab52ce28373..9906fb4b47a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java @@ -39,7 +39,7 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; @@ -82,7 +82,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -95,7 +95,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implEncrypt") static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -108,7 +108,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -121,7 +121,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -138,7 +138,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "decrypt") static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -154,7 +154,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implDecrypt") static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -168,8 +168,8 @@ public class CipherBlockChainingSubstitutions { AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object aesCipher = getAESCryptClass().cast(embeddedCipher); - Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); - Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); + Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte)); Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); @@ -178,7 +178,7 @@ public class CipherBlockChainingSubstitutions { encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index ea6af4de1f2..3cef759ec5d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -35,9 +35,10 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; @@ -59,16 +60,12 @@ import jdk.vm.ci.meta.ResolvedJavaType; * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}. */ @NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +public final class ClassGetHubNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(ClassGetHubNode.class); @Input protected ValueNode clazz; public ClassGetHubNode(ValueNode clazz) { - this(clazz, null); - } - - public ClassGetHubNode(ValueNode clazz, ValueNode guard) { - super(TYPE, KlassPointerStamp.klass(), (GuardingNode) guard); + super(TYPE, KlassPointerStamp.klass()); this.clazz = clazz; } @@ -106,10 +103,10 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera } @NodeIntrinsic - public static native KlassPointer readClass(Class clazz); + public static native KlassPointer readClass(Class clazzNonNull); - @NodeIntrinsic - public static native KlassPointer readClass(Class clazz, GuardingNode guard); + @NodeIntrinsic(PiNode.class) + public static native KlassPointer piCastNonNull(Object object, GuardingNode anchor); @Override public ValueNode getValue() { @@ -138,6 +135,14 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera return false; } + /** + * There is more than one {@link java.lang.Class} value that has a NULL hub. + */ + @Override + public boolean mayNullCheckSkipConversion() { + return false; + } + @Override public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) { assert op == Condition.EQ || op == Condition.NE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java index 301b03d12a6..9341f650207 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java @@ -26,7 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.nio.ByteBuffer; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.DataPointerConstant; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java index f0608fdafbb..4a0a4e1c3b7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -76,8 +77,8 @@ public class HashCodeSnippets implements Snippets { private final SnippetInfo identityHashCodeSnippet = snippet(HashCodeSnippets.class, "identityHashCodeSnippet", HotSpotReplacementsUtil.MARK_WORD_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(IdentityHashCodeNode node, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java index 8113802a62a..0a53eb454f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; // JaCoCo Exclude @@ -78,7 +79,8 @@ public class HotSpotClassSubstitutions { // Class for primitive type return false; } else { - return klassIsArray(klass); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + return klassIsArray(klassNonNull); } } @@ -92,16 +94,18 @@ public class HotSpotClassSubstitutions { public static Class getSuperclass(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - int accessFlags = klass.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + int accessFlags = klassNonNull.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klass)) { + if (klassIsArray(klassNonNull)) { return Object.class; } else { - KlassPointer superKlass = klass.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); + KlassPointer superKlass = klassNonNull.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); if (superKlass.isNull()) { return null; } else { - return readJavaMirror(superKlass); + KlassPointer superKlassNonNull = ClassGetHubNode.piCastNonNull(superKlass, SnippetAnchorNode.anchor()); + return HubGetClassNode.readClass(superKlassNonNull); } } } @@ -111,16 +115,13 @@ public class HotSpotClassSubstitutions { return null; } - public static Class readJavaMirror(KlassPointer klass) { - return PiNode.asNonNullClass(HubGetClassNode.readClass(klass)); - } - @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - if (klassIsArray(klass)) { - return PiNode.asNonNullClass(klass.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + if (klassIsArray(klassNonNull)) { + return PiNode.asNonNullClass(klassNonNull.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); } } else { // Class for primitive type diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 90c34836d4e..54b97fae577 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -42,17 +42,15 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.CanonicalizableLocation; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.memory.Access; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -389,32 +387,23 @@ public class HotSpotReplacementsUtil { return config.klassLayoutHelperOffset; } - public static int readLayoutHelper(KlassPointer hub) { - // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); - GuardingNode anchorNode = SnippetAnchorNode.anchor(); - return loadKlassLayoutHelperIntrinsic(hub, anchorNode); - } - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object, GuardingNode anchor); - - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object); + public static native int readLayoutHelper(KlassPointer object); /** * Checks if class {@code klass} is an array. * * See: Klass::layout_helper_is_array * - * @param klass the class to be checked - * @return true if klass is an array, false otherwise + * @param klassNonNull the class to be checked + * @return true if klassNonNull is an array, false otherwise */ - public static boolean klassIsArray(KlassPointer klass) { + public static boolean klassIsArray(KlassPointer klassNonNull) { /* * The less-than check only works if both values are ints. We use local variables to make * sure these are still ints and haven't changed. */ - final int layoutHelper = readLayoutHelper(klass); + final int layoutHelper = readLayoutHelper(klassNonNull); final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue; return (layoutHelper < layoutHelperNeutralValue); } @@ -479,6 +468,31 @@ public class HotSpotReplacementsUtil { return config.unlockedMask; } + @Fold + public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) { + return config.monitorMask; + } + + @Fold + public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorOwner; + } + + @Fold + public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorRecursions; + } + + @Fold + public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorCxq; + } + + @Fold + public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorEntryList; + } + /** * Mask for a biasable, locked or unlocked mark word. * @@ -626,6 +640,14 @@ public class HotSpotReplacementsUtil { public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord"); + public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner"); + + public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions"); + + public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq"); + + public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); + @Fold public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockDisplacedHeaderOffset; @@ -709,10 +731,10 @@ public class HotSpotReplacementsUtil { @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); @NodeIntrinsic(value = LoadHubNode.class) diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java index 94724505f30..e22020218bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java @@ -23,10 +23,10 @@ package org.graalvm.compiler.hotspot.replacements; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.ProfileContext; -import org.graalvm.compiler.options.EnumOptionValue; +import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to HotSpot snippets in this package. @@ -39,31 +39,34 @@ public class HotspotSnippetsOptions { // @formatter:off @Option(help = "If the probability that a type check will hit one the profiled types (up to " + "TypeCheckMaxHints) is below this value, the type check will be compiled without profiling info", type = OptionType.Expert) - public static final OptionValue TypeCheckMinProfileHitProbability = new OptionValue<>(0.5); + public static final OptionKey TypeCheckMinProfileHitProbability = new OptionKey<>(0.5); @Option(help = "The maximum number of profiled types that will be used when compiling a profiled type check. " + "Note that TypeCheckMinProfileHitProbability also influences whether profiling info is used in compiled type checks.", type = OptionType.Expert) - public static final OptionValue TypeCheckMaxHints = new OptionValue<>(2); + public static final OptionKey TypeCheckMaxHints = new OptionKey<>(2); @Option(help = "Use a VM runtime call to load and clear the exception object from the thread at the start of a compiled exception handler.", type = OptionType.Debug) - public static final OptionValue LoadExceptionObjectInVM = new OptionValue<>(false); + public static final OptionKey LoadExceptionObjectInVM = new OptionKey<>(false); @Option(help = "Enable profiling of allocation sites.", type = OptionType.Debug) - public static final OptionValue ProfileAllocations = new OptionValue<>(false); + public static final OptionKey ProfileAllocations = new OptionKey<>(false); @Option(help = "Control the naming of the counters when using ProfileAllocations.", type = OptionType.Debug) - public static final EnumOptionValue ProfileAllocationsContext = new EnumOptionValue<>(ProfileContext.AllocatingMethod); + public static final EnumOptionKey ProfileAllocationsContext = new EnumOptionKey<>(ProfileContext.AllocatingMethod); @Option(help = "Enable profiling of monitor operations.", type = OptionType.Debug) - public static final OptionValue ProfileMonitors = new OptionValue<>(false); + public static final OptionKey ProfileMonitors = new OptionKey<>(false); + + @Option(help = "Handle simple cases for inflated monitors in the fast-path.", type = OptionType.Expert) + public static final OptionKey SimpleFastInflatedLocking = new OptionKey<>(true); @Option(help = "Trace monitor operations on objects whose type contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsTypeFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsTypeFilter = new OptionKey<>(null); @Option(help = "Trace monitor operations in methods whose fully qualified name contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsMethodFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsMethodFilter = new OptionKey<>(null); @Option(help = "Emit extra code to dynamically check monitor operations are balanced.", type = OptionType.Debug) - public static final OptionValue VerifyBalancedMonitors = new OptionValue<>(false); + public static final OptionKey VerifyBalancedMonitors = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java index 647b8d0c7c5..a48ba4f7646 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java @@ -34,9 +34,9 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -51,12 +51,12 @@ import jdk.vm.ci.meta.ResolvedJavaType; * also used by {@link ClassGetHubNode} to eliminate chains of {@code klass._java_mirror._klass}. */ @NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +public final class HubGetClassNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(HubGetClassNode.class); @Input protected ValueNode hub; public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { - super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class))), null); + super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class)))); this.hub = hub; } @@ -114,11 +114,16 @@ public final class HubGetClassNode extends FloatingGuardedNode implements Lowera } } + /** + * Any concrete Klass* has a corresponding {@link java.lang.Class}. + */ @Override public boolean isLossless() { - /* - * Any concrete Klass* has a corresponding java.lang.Class - */ + return true; + } + + @Override + public boolean mayNullCheckSkipConversion() { return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java index 9c1da836f4a..c3e12db7141 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java @@ -67,7 +67,7 @@ public class IdentityHashCodeNode extends FixedWithNextNode implements Canonical if (object.isConstant()) { assert object.stamp() instanceof AbstractObjectStamp; JavaConstant c = (JavaConstant) object.asConstant(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(getOptions())) { return this; } JavaConstant identityHashCode = null; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java index 177b159f9ec..4a0ed0450a7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION; @@ -31,34 +33,28 @@ import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.T import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkSecondarySubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkUnknownSubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.createHints; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.isNull; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; +import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; +import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Counters; import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Hints; import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.nodes.ValueNode; @@ -68,7 +64,9 @@ import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.InstanceOfSnippetsTemplates; +import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; @@ -99,9 +97,9 @@ public class InstanceOfSnippets implements Snippets { */ @Snippet public static Object instanceofWithProfile(Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, - @ConstantParameter boolean nullSeen) { + @ConstantParameter boolean nullSeen, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (!nullSeen) { // See comment below for other deoptimization path; the // same reasoning applies here. @@ -117,10 +115,10 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(LIKELY_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } - hintsMiss.inc(); + counters.hintsMiss.inc(); } // This maybe just be a rare event but it might also indicate a phase change // in the application. Ideally we want to use DeoptimizationAction.None for @@ -134,59 +132,60 @@ public class InstanceOfSnippets implements Snippets { * A test against a final type. */ @Snippet - public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { + public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) { - exactMiss.inc(); + counters.exactMiss.inc(); return falseValue; } - exactHit.inc(); + counters.exactHit.inc(); return trueValue; } @Snippet - public static Object instanceofExactPIC(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { + public static Object instanceofExactPIC(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { KlassPointer exactHubPIC = ResolveConstantSnippets.resolveKlassConstant(exactHub); - return instanceofExact(object, exactHubPIC, trueValue, falseValue); + return instanceofExact(object, exactHubPIC, trueValue, falseValue, counters); } /** * A test against a primary type. */ @Snippet - public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { + public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) { - displayMiss.inc(); + counters.displayMiss.inc(); return falseValue; } - displayHit.inc(); + counters.displayHit.inc(); return trueValue; } @Snippet - public static Object instanceofPrimaryPIC(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { + public static Object instanceofPrimaryPIC(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofPrimary(resolvedHub, object, superCheckOffset, trueValue, falseValue); + return instanceofPrimary(resolvedHub, object, superCheckOffset, trueValue, falseValue, counters); } /** * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue) { + public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); @@ -197,12 +196,12 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } } - hintsMiss.inc(); - if (!checkSecondarySubType(hub, objectHub)) { + counters.hintsMiss.inc(); + if (!checkSecondarySubType(hub, objectHub, counters)) { return falseValue; } return trueValue; @@ -210,18 +209,18 @@ public class InstanceOfSnippets implements Snippets { @Snippet public static Object instanceofSecondaryPIC(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, - Object falseValue) { + Object falseValue, @ConstantParameter Counters counters) { KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofSecondary(resolvedHub, object, hints, hintIsPositive, trueValue, falseValue); + return instanceofSecondary(resolvedHub, object, hints, hintIsPositive, trueValue, falseValue, counters); } /** * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull) { + public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (allowNull) { return trueValue; } else { @@ -229,31 +228,44 @@ public class InstanceOfSnippets implements Snippets { } } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); + KlassPointer nonNullObjectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); // The hub of a primitive type can be null => always return false in this case. - if (hub.isNull() || !checkUnknownSubType(hub, objectHub)) { - return falseValue; + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !hub.isNull())) { + if (checkUnknownSubType(hub, nonNullObjectHub, counters)) { + return trueValue; + } } - return trueValue; + return falseValue; } @Snippet - public static Object isAssignableFrom(Class thisClass, Class otherClass, Object trueValue, Object falseValue) { - if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, otherClass == null)) { + public static Object isAssignableFrom(@NonNullParameter Class thisClassNonNull, Class otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { + if (otherClass == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); return false; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode); - KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode); - if (thisHub.isNull() || otherHub.isNull()) { - // primitive types, only true if equal. - return thisClass == otherClass ? trueValue : falseValue; + Class otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode); + + if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) { + return trueValue; } - if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { - return falseValue; + + KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull); + KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull); + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) { + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) { + GuardingNode guardNonNull = SnippetAnchorNode.anchor(); + KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull); + if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) { + return trueValue; + } + } } - return trueValue; + + // If either hub is null, one of them is a primitive type and given that the class is not + // equal, return false. + return falseValue; } public static class Templates extends InstanceOfSnippetsTemplates { @@ -268,8 +280,11 @@ public class InstanceOfSnippets implements Snippets { private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic", SECONDARY_SUPER_CACHE_LOCATION); private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom", SECONDARY_SUPER_CACHE_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + private final Counters counters; + + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } @Override @@ -279,13 +294,15 @@ public class InstanceOfSnippets implements Snippets { ValueNode object = instanceOf.getValue(); Assumptions assumptions = instanceOf.graph().getAssumptions(); + OptionValues localOptions = instanceOf.getOptions(); JavaTypeProfile profile = instanceOf.profile(); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { // FIXME: We can't embed constants in hints. We can't really load them from GOT // either. Hard problem. profile = null; } - TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); + TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(localOptions), + TypeCheckMaxHints.getValue(localOptions)); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type().getType(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), instanceOf.graph()); @@ -299,19 +316,19 @@ public class InstanceOfSnippets implements Snippets { args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(JavaKind.Boolean), hints.isPositive); } else if (hintInfo.exact != null) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofExactPIC : instanceofExact; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofExactPIC : instanceofExact; args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", object); args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph)); } else if (type.isPrimaryType()) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofPrimaryPIC : instanceofPrimary; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofPrimaryPIC : instanceofPrimary; args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph); - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofSecondaryPIC : instanceofSecondary; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofSecondaryPIC : instanceofSecondary; args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); @@ -323,6 +340,7 @@ public class InstanceOfSnippets implements Snippets { if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) { args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE); } + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) { InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; @@ -334,14 +352,17 @@ public class InstanceOfSnippets implements Snippets { args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); args.addConst("allowNull", instanceOf.allowsNull()); + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) { ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf; Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("thisClass", isAssignable.getThisClass()); + assert ((ObjectStamp) isAssignable.getThisClass().stamp()).nonNull(); + args.add("thisClassNonNull", isAssignable.getThisClass()); args.add("otherClass", isAssignable.getOtherClass()); args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); + args.addConst("counters", counters); return args; } else { throw GraalError.shouldNotReachHere(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java index 346c94ff104..13d7a4dd9bf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java @@ -35,9 +35,8 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -52,20 +51,16 @@ import jdk.vm.ci.meta.ResolvedJavaType; * information in {@code klass}. */ @NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { +public final class KlassLayoutHelperNode extends FloatingNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(KlassLayoutHelperNode.class); @Input protected ValueNode klass; protected final GraalHotSpotVMConfig config; public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { - this(config, klass, null); - } - - public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass, ValueNode guard) { - super(TYPE, StampFactory.forKind(JavaKind.Int), (GuardingNode) guard); - this.klass = klass; + super(TYPE, StampFactory.forKind(JavaKind.Int)); this.config = config; + this.klass = klass; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java index 02eaf651a88..a18850bbfdc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java @@ -29,18 +29,19 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionPc; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.LoadExceptionObjectInVM; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -63,31 +64,26 @@ import jdk.vm.ci.code.TargetDescription; */ public class LoadExceptionObjectSnippets implements Snippets { - /** - * Alternative way to implement exception object loading. - */ - private static final boolean USE_C_RUNTIME = HotspotSnippetsOptions.LoadExceptionObjectInVM.getValue(); - @Snippet public static Object loadException(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); writeExceptionPc(thread, Word.zero()); - return piCast(exception, StampFactory.forNodeIntrinsic()); + return piCastToSnippetReplaceeStamp(exception); } public static class Templates extends AbstractTemplates { private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { - if (USE_C_RUNTIME) { - StructuredGraph graph = loadExceptionObject.graph(); + StructuredGraph graph = loadExceptionObject.graph(); + if (LoadExceptionObjectInVM.getValue(graph.getOptions())) { ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); graph.addBeforeFixed(loadExceptionObject, thread); ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java index 91747913671..952284cc3bf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java @@ -22,14 +22,18 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode.beginLockScope; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.nodes.EndLockScopeNode.endLockScope; import static org.graalvm.compiler.hotspot.nodes.VMErrorNode.vmError; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_CXQ_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -39,6 +43,11 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockDisplacedMarkOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.markOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorMask; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorCxqOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -47,12 +56,16 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileMonitors; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.SimpleFastInflatedLocking; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsMethodFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsTypeFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.VerifyBalancedMonitors; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; @@ -71,11 +84,11 @@ import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode; import org.graalvm.compiler.hotspot.nodes.CurrentLockNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.FastAcquireBiasedLockNode; import org.graalvm.compiler.hotspot.nodes.MonitorCounterNode; import org.graalvm.compiler.hotspot.word.KlassPointer; @@ -90,14 +103,14 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; import org.graalvm.compiler.nodes.java.RawMonitorEnterNode; -import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; @@ -105,6 +118,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; +import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordBase; @@ -114,7 +128,6 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -201,13 +214,13 @@ public class MonitorSnippets implements Snippets { private static final boolean PROFILE_CONTEXT = false; @Fold - static boolean doProfile() { - return ProfileMonitors.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileMonitors.getValue(options); } @Snippet public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { verifyOop(object); // Load the mark word - this includes a null-check on object @@ -215,197 +228,256 @@ public class MonitorSnippets implements Snippets { final Word lock = beginLockScope(lockDepth); - trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + Pointer objectPointer = Word.objectToTrackedPointer(object); + trace(trace, " object: 0x%016lx\n", objectPointer); trace(trace, " lock: 0x%016lx\n", lock); trace(trace, " mark: 0x%016lx\n", mark); - incCounter(); + incCounter(options); if (useBiasedLocking(INJECTED_VMCONFIG)) { - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid. - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits. - final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); - - // Check whether the bias pattern is present in the object's mark word - // and the bias owner and the epoch are both still current. - final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); - final Word thread = registerAsWord(threadRegister); - final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); - trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); - trace(trace, " thread: 0x%016lx\n", thread); - trace(trace, " tmp: 0x%016lx\n", tmp); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, tmp.equal(0))) { - // Object is already biased to current thread -> done - traceObject(trace, "+lock{bias:existing}", object, true); - lockBiasExisting.inc(); - FastAcquireBiasedLockNode.mark(object); + if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) { return; } - - // Now check to see whether biasing is enabled for this object - if (probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { - // Biasing not enabled -> fall through to lightweight locking - unbiasable.inc(); - } else { - // At this point we know that the mark word has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the mark word in order to - // know what operations can be legally performed on the object's - // mark word. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biasable and we have to revoke - // the bias on this object. - if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // Biasing is still enabled for object's type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype mark word. (Note that the prototype mark word's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); - Word biasedMark = unbiasedMark.or(thread); - trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:acquired}", object, true); - lockBiasAcquired.inc(); - return; - } - // If the biasing toward our thread failed, this means that another thread - // owns the bias and we need to revoke that bias. The revocation will occur - // in the interpreter runtime. - traceObject(trace, "+lock{stub:revoke}", object, true); - lockStubRevoke.inc(); - } else { - // At this point we know the epoch has expired, meaning that the - // current bias owner, if any, is actually invalid. Under these - // circumstances _only_, are we allowed to use the current mark word - // value as the comparison value when doing the CAS to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - Word biasedMark = prototypeMarkWord.or(thread); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:transfer}", object, true); - lockBiasTransfer.inc(); - return; - } - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - traceObject(trace, "+lock{stub:epoch-expired}", object, true); - lockStubEpochExpired.inc(); - } - monitorenterStubC(MONITORENTER, object, lock); - return; - } else { - // The prototype mark word doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - Word result = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, prototypeMarkWord, MARK_WORD_LOCATION); - - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - - if (ENABLE_BREAKPOINT) { - bkpt(object, mark, tmp, result); - } - revokeBias.inc(); - } - } + // not biased, fall-through } - - // Create the unlocked mark word pattern - Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); - trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); - - // Copy this unlocked mark word into the lock slot on the stack - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); - - // Test if the object's mark word is unlocked, and if so, store the - // (address of) the lock slot into the object's mark word. - Word currentMark = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unlockedMark, lock, MARK_WORD_LOCATION); - if (probability(BranchProbabilityNode.SLOW_PATH_PROBABILITY, currentMark.notEqual(unlockedMark))) { - trace(trace, " currentMark: 0x%016lx\n", currentMark); - // The mark word in the object header was not the same. - // Either the object is locked by another thread or is already locked - // by the current thread. The latter is true if the mark word - // is a stack pointer into the current thread's stack, i.e.: - // - // 1) (currentMark & aligned_mask) == 0 - // 2) rsp <= currentMark - // 3) currentMark <= rsp + page_size - // - // These 3 tests can be done by evaluating the following expression: - // - // (currentMark - rsp) & (aligned_mask - page_size) - // - // assuming both the stack pointer and page_size have their least - // significant 2 bits cleared and page_size is a power of 2 - final Word alignedMask = Word.unsigned(wordSize() - 1); - final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); - if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { - // Most likely not a recursive lock, go into a slow runtime call - traceObject(trace, "+lock{stub:failed-cas}", object, true); - lockStubFailedCas.inc(); - monitorenterStubC(MONITORENTER, object, lock); + if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) { return; - } else { - // Recursively locked => write 0 to the lock slot - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), Word.zero(), DISPLACED_MARK_WORD_LOCATION); - traceObject(trace, "+lock{cas:recursive}", object, true); - lockCasRecursive.inc(); } } else { - traceObject(trace, "+lock{cas}", object, true); - lockCas.inc(); - AcquiredCASLockNode.mark(object); + // Create the unlocked mark word pattern + Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); + trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); + + // Copy this unlocked mark word into the lock slot on the stack + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); + + // make sure previous store does not float below compareAndSwap + MembarNode.memoryBarrier(STORE_STORE); + + // Test if the object's mark word is unlocked, and if so, store the + // (address of) the lock slot into the object's mark word. + Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION); + if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) { + traceObject(trace, "+lock{cas}", object, true, options); + counters.lockCas.inc(); + AcquiredCASLockNode.mark(object); + return; + } else { + trace(trace, " currentMark: 0x%016lx\n", currentMark); + // The mark word in the object header was not the same. + // Either the object is locked by another thread or is already locked + // by the current thread. The latter is true if the mark word + // is a stack pointer into the current thread's stack, i.e.: + // + // 1) (currentMark & aligned_mask) == 0 + // 2) rsp <= currentMark + // 3) currentMark <= rsp + page_size + // + // These 3 tests can be done by evaluating the following expression: + // + // (currentMark - rsp) & (aligned_mask - page_size) + // + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + final Word alignedMask = Word.unsigned(wordSize() - 1); + final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); + if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) { + // Recursively locked => write 0 to the lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), Word.zero(), DISPLACED_MARK_WORD_LOCATION); + traceObject(trace, "+lock{cas:recursive}", object, true, options); + counters.lockCasRecursive.inc(); + return; + } + traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options); + counters.lockStubFailedCas.inc(); + } } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + } + + private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid. + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits. + final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); + + // Check whether the bias pattern is present in the object's mark word + // and the bias owner and the epoch are both still current. + final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + final Word thread = registerAsWord(threadRegister); + final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); + trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); + trace(trace, " thread: 0x%016lx\n", thread); + trace(trace, " tmp: 0x%016lx\n", tmp); + if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) { + // Object is already biased to current thread -> done + traceObject(trace, "+lock{bias:existing}", object, true, options); + counters.lockBiasExisting.inc(); + FastAcquireBiasedLockNode.mark(object); + return true; + } + + // Now check to see whether biasing is enabled for this object + if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.equal(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + Pointer objectPointer = Word.objectToTrackedPointer(object); + // At this point we know that the mark word has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the mark word in order to + // know what operations can be legally performed on the object's + // mark word. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biasable and we have to revoke + // the bias on this object. + if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // Biasing is still enabled for object's type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype mark word. (Note that the prototype mark word's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); + Word biasedMark = unbiasedMark.or(thread); + trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:acquired}", object, true, options); + counters.lockBiasAcquired.inc(); + return true; + } + // If the biasing toward our thread failed, this means that another thread + // owns the bias and we need to revoke that bias. The revocation will occur + // in the interpreter runtime. + traceObject(trace, "+lock{stub:revoke}", object, true, options); + counters.lockStubRevoke.inc(); + } else { + // At this point we know the epoch has expired, meaning that the + // current bias owner, if any, is actually invalid. Under these + // circumstances _only_, are we allowed to use the current mark word + // value as the comparison value when doing the CAS to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + Word biasedMark = prototypeMarkWord.or(thread); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:transfer}", object, true, options); + counters.lockBiasTransfer.inc(); + return true; + } + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + traceObject(trace, "+lock{stub:epoch-expired}", object, true, options); + counters.lockStubEpochExpired.inc(); + } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + return true; + } else { + // The prototype mark word doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + Word result = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, prototypeMarkWord, MARK_WORD_LOCATION); + + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + + if (ENABLE_BREAKPOINT) { + bkpt(object, mark, tmp, result); + } + counters.revokeBias.inc(); + return false; + } + } else { + // Biasing not enabled -> fall through to lightweight locking + counters.unbiasable.inc(); + return false; + } + } + + @Fold + public static boolean useFastInflatedLocking(OptionValues options) { + return SimpleFastInflatedLocking.getValue(options); + } + + private static boolean inlineFastLockSupported(OptionValues options) { + return inlineFastLockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastLockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && monitorMask(config) >= 0 && objectMonitorOwnerOffset(config) >= 0; + } + + private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // write non-zero value to lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), lock, DISPLACED_MARK_WORD_LOCATION); + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + if (probability(FREQUENT_PROBABILITY, owner.equal(0))) { + // it appears unlocked (owner == 0) + if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, registerAsWord(threadRegister), OBJECT_MONITOR_OWNER_LOCATION))) { + // success + traceObject(trace, "+lock{inflated:cas}", object, true, options); + counters.inflatedCas.inc(); + return true; + } else { + traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true, options); + counters.inflatedFailedCas.inc(); + } + } else { + traceObject(trace, "+lock{stub:inflated:owned}", object, true, options); + counters.inflatedOwned.inc(); + } + return false; } /** * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - incCounter(); + incCounter(options); if (object == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); } // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above final Word lock = beginLockScope(lockDepth); - traceObject(trace, "+lock{stub}", object, true); + traceObject(trace, "+lock{stub}", object, true, options); monitorenterStubC(MONITORENTER, object, lock); } @Snippet - public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); if (useBiasedLocking(INJECTED_VMCONFIG)) { // Check for biased locking unlock case, which is a no-op // Note: we do not have to check the thread ID for two reasons. @@ -413,13 +485,12 @@ public class MonitorSnippets implements Snippets { // a higher level. Second, if the bias was revoked while we held the // lock, the object could not be rebiased toward another thread, so // the bias bit would be clear. - final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); trace(trace, " mark: 0x%016lx\n", mark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { endLockScope(); - decCounter(); - traceObject(trace, "-lock{bias}", object, false); - unlockBias.inc(); + decCounter(options); + traceObject(trace, "-lock{bias}", object, false, options); + counters.unlockBias.inc(); return; } } @@ -430,46 +501,95 @@ public class MonitorSnippets implements Snippets { final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), DISPLACED_MARK_WORD_LOCATION); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { + if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { // Recursive locking => done - traceObject(trace, "-lock{recursive}", object, false); - unlockCasRecursive.inc(); + traceObject(trace, "-lock{recursive}", object, false, options); + counters.unlockCasRecursive.inc(); } else { - verifyOop(object); - // Test if object's mark word is pointing to the displaced mark word, and if so, restore - // the displaced mark in the object - if the object's mark word is not pointing to - // the displaced mark word, do unlocking via runtime call. - if (probability(VERY_SLOW_PATH_PROBABILITY, - DirectCompareAndSwapNode.compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) { - // The object's mark word was not pointing to the displaced header, - // we do unlocking via runtime call. - traceObject(trace, "-lock{stub}", object, false); - unlockStub.inc(); - monitorexitStubC(MONITOREXIT, object, lock); - } else { - traceObject(trace, "-lock{cas}", object, false); - unlockCas.inc(); + if (!tryExitInflated(object, mark, lock, threadRegister, trace, options, counters)) { + verifyOop(object); + // Test if object's mark word is pointing to the displaced mark word, and if so, + // restore + // the displaced mark in the object - if the object's mark word is not pointing to + // the displaced mark word, do unlocking via runtime call. + Pointer objectPointer = Word.objectToTrackedPointer(object); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), lock, displacedMark, MARK_WORD_LOCATION))) { + traceObject(trace, "-lock{cas}", object, false, options); + counters.unlockCas.inc(); + } else { + // The object's mark word was not pointing to the displaced header + traceObject(trace, "-lock{stub}", object, false, options); + counters.unlockStub.inc(); + monitorexitStubC(MONITOREXIT, object, lock); + } } } endLockScope(); - decCounter(); + decCounter(options); + } + + private static boolean inlineFastUnlockSupported(OptionValues options) { + return inlineFastUnlockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastUnlockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && objectMonitorEntryListOffset(config) >= 0 && objectMonitorCxqOffset(config) >= 0 && monitorMask(config) >= 0 && + objectMonitorOwnerOffset(config) >= 0 && objectMonitorRecursionsOffset(config) >= 0; + } + + private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + if (!inlineFastUnlockSupported(options)) { + return false; + } + if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG); + Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION); + Word thread = registerAsWord(threadRegister); + if (probability(FAST_PATH_PROBABILITY, owner.xor(thread).or(recursions).equal(0))) { + // owner == thread && recursions == 0 + int cxqOffset = objectMonitorCxqOffset(INJECTED_VMCONFIG); + Word cxq = monitor.readWord(cxqOffset, OBJECT_MONITOR_CXQ_LOCATION); + int entryListOffset = objectMonitorEntryListOffset(INJECTED_VMCONFIG); + Word entryList = monitor.readWord(entryListOffset, OBJECT_MONITOR_ENTRY_LIST_LOCATION); + if (probability(FREQUENT_PROBABILITY, cxq.or(entryList).equal(0))) { + // cxq == 0 && entryList == 0 + // Nobody is waiting, success + // release_store + MembarNode.memoryBarrier(LOAD_STORE | STORE_STORE); + monitor.writeWord(ownerOffset, Word.zero()); + traceObject(trace, "-lock{inflated:simple}", object, false, options); + counters.unlockInflatedSimple.inc(); + return true; + } + } + counters.unlockStubInflated.inc(); + traceObject(trace, "-lock{stub:inflated}", object, false, options); + monitorexitStubC(MONITOREXIT, object, lock); + return true; + } + return false; } /** * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - traceObject(trace, "-lock{stub}", object, false); + traceObject(trace, "-lock{stub}", object, false, options); final Word lock = CurrentLockNode.currentLock(lockDepth); monitorexitStubC(MONITOREXIT, object, lock); endLockScope(); - decCounter(); + decCounter(options); } - public static void traceObject(boolean enabled, String action, Object object, boolean enter) { - if (doProfile()) { + public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) { + if (doProfile(options)) { DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT); } if (enabled) { @@ -496,18 +616,21 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word mark, Word tmp, Word value); - private static final boolean VERIFY_BALANCED_MONITORS = VerifyBalancedMonitors.getValue(); + @Fold + static boolean verifyBalancedMonitors(OptionValues options) { + return VerifyBalancedMonitors.getValue(options); + } - public static void incCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void incCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION); } } - public static void decCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void decCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION); @@ -529,6 +652,64 @@ public class MonitorSnippets implements Snippets { } } + public static class Counters { + /** + * Counters for the various paths for acquiring a lock. The counters whose names start with + * {@code "lock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter lockBiasExisting; + public final SnippetCounter lockBiasAcquired; + public final SnippetCounter lockBiasTransfer; + public final SnippetCounter lockCas; + public final SnippetCounter lockCasRecursive; + public final SnippetCounter lockStubEpochExpired; + public final SnippetCounter lockStubRevoke; + public final SnippetCounter lockStubFailedCas; + public final SnippetCounter inflatedCas; + public final SnippetCounter inflatedFailedCas; + public final SnippetCounter inflatedOwned; + public final SnippetCounter unbiasable; + public final SnippetCounter revokeBias; + + /** + * Counters for the various paths for releasing a lock. The counters whose names start with + * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter unlockBias; + public final SnippetCounter unlockCas; + public final SnippetCounter unlockCasRecursive; + public final SnippetCounter unlockStub; + public final SnippetCounter unlockStubInflated; + public final SnippetCounter unlockInflatedSimple; + + public Counters(SnippetCounter.Group.Factory factory) { + SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); + SnippetCounter.Group exit = factory.createSnippetCounterGroup("MonitorExits"); + lockBiasExisting = new SnippetCounter(enter, "lock{bias:existing}", "bias-locked previously biased object"); + lockBiasAcquired = new SnippetCounter(enter, "lock{bias:acquired}", "bias-locked newly biased object"); + lockBiasTransfer = new SnippetCounter(enter, "lock{bias:transfer}", "bias-locked, biased transferred"); + lockCas = new SnippetCounter(enter, "lock{cas}", "cas-locked an object"); + lockCasRecursive = new SnippetCounter(enter, "lock{cas:recursive}", "cas-locked, recursive"); + lockStubEpochExpired = new SnippetCounter(enter, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); + lockStubRevoke = new SnippetCounter(enter, "lock{stub:revoke}", "stub-locked, biased revoked"); + lockStubFailedCas = new SnippetCounter(enter, "lock{stub:failed-cas/stack}", "stub-locked, failed cas and stack locking"); + inflatedCas = new SnippetCounter(enter, "lock{inflated:cas}", "heavyweight-locked, cas-locked"); + inflatedFailedCas = new SnippetCounter(enter, "lock{inflated:failed-cas}", "heavyweight-locked, failed cas"); + inflatedOwned = new SnippetCounter(enter, "lock{inflated:owned}", "heavyweight-locked, already owned"); + unbiasable = new SnippetCounter(enter, "unbiasable", "object with unbiasable type"); + revokeBias = new SnippetCounter(enter, "revokeBias", "object had bias revoked"); + + unlockBias = new SnippetCounter(exit, "unlock{bias}", "bias-unlocked an object"); + unlockCas = new SnippetCounter(exit, "unlock{cas}", "cas-unlocked an object"); + unlockCasRecursive = new SnippetCounter(exit, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); + unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); + unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); + unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + } + } + public static class Templates extends AbstractTemplates { private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); @@ -539,10 +720,13 @@ public class MonitorSnippets implements Snippets { private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); private final boolean useFastLocking; + public final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { + super(options, providers, providers.getSnippetReflection(), target); this.useFastLocking = useFastLocking; + + this.counters = new Counters(factory); } public void lower(RawMonitorEnterNode monitorenterNode, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -559,18 +743,22 @@ public class MonitorSnippets implements Snippets { args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("stackPointerRegister", registers.getStackPointerRegister()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } else { args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", monitorenterNode.object()); args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } template(args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); } - public void lower(MonitorExitNode monitorexitNode, LoweringTool tool) { + public void lower(MonitorExitNode monitorexitNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = monitorexitNode.graph(); Arguments args; @@ -581,14 +769,17 @@ public class MonitorSnippets implements Snippets { } args.add("object", monitorexitNode.object()); args.addConst("lockDepth", monitorexitNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); } public static boolean isTracingEnabledForType(ValueNode object) { ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); - String filter = TraceMonitorsTypeFilter.getValue(); + String filter = TraceMonitorsTypeFilter.getValue(object.getOptions()); if (filter == null) { return false; } else { @@ -602,18 +793,18 @@ public class MonitorSnippets implements Snippets { } } - public static boolean isTracingEnabledForMethod(ResolvedJavaMethod method) { - String filter = TraceMonitorsMethodFilter.getValue(); + public static boolean isTracingEnabledForMethod(StructuredGraph graph) { + String filter = TraceMonitorsMethodFilter.getValue(graph.getOptions()); if (filter == null) { return false; } else { if (filter.length() == 0) { return true; } - if (method == null) { + if (graph.method() == null) { return false; } - return (method.format("%H.%n").contains(filter)); + return (graph.method().format("%H.%n").contains(filter)); } } @@ -622,7 +813,7 @@ public class MonitorSnippets implements Snippets { * return points of the graph to initialize and check the monitor counter respectively. */ private void checkBalancedMonitors(StructuredGraph graph, LoweringTool tool) { - if (VERIFY_BALANCED_MONITORS) { + if (VerifyBalancedMonitors.getValue(options)) { NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. @@ -634,7 +825,7 @@ public class MonitorSnippets implements Snippets { graph.addAfterFixed(graph.start(), invoke); StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); for (ReturnNode ret : rets) { @@ -652,7 +843,7 @@ public class MonitorSnippets implements Snippets { Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("errMsg", msg); inlineeGraph = template(args).copySpecializedGraph(); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + InliningUtil.inline(invoke, inlineeGraph, false, null); } } } @@ -667,31 +858,4 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(ForeignCallNode.class) public static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); - - /** - * Counters for the various paths for acquiring a lock. The counters whose names start with - * {@code "lock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group lockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorEnters") : null; - public static final SnippetCounter lockBiasExisting = new SnippetCounter(lockCounters, "lock{bias:existing}", "bias-locked previously biased object"); - public static final SnippetCounter lockBiasAcquired = new SnippetCounter(lockCounters, "lock{bias:acquired}", "bias-locked newly biased object"); - public static final SnippetCounter lockBiasTransfer = new SnippetCounter(lockCounters, "lock{bias:transfer}", "bias-locked, biased transferred"); - public static final SnippetCounter lockCas = new SnippetCounter(lockCounters, "lock{cas}", "cas-locked an object"); - public static final SnippetCounter lockCasRecursive = new SnippetCounter(lockCounters, "lock{cas:recursive}", "cas-locked, recursive"); - public static final SnippetCounter lockStubEpochExpired = new SnippetCounter(lockCounters, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); - public static final SnippetCounter lockStubRevoke = new SnippetCounter(lockCounters, "lock{stub:revoke}", "stub-locked, biased revoked"); - public static final SnippetCounter lockStubFailedCas = new SnippetCounter(lockCounters, "lock{stub:failed-cas}", "stub-locked, failed cas"); - - public static final SnippetCounter unbiasable = new SnippetCounter(lockCounters, "unbiasable", "object with unbiasable type"); - public static final SnippetCounter revokeBias = new SnippetCounter(lockCounters, "revokeBias", "object had bias revoked"); - - /** - * Counters for the various paths for releasing a lock. The counters whose names start with - * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group unlockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorExits") : null; - public static final SnippetCounter unlockBias = new SnippetCounter(unlockCounters, "unlock{bias}", "bias-unlocked an object"); - public static final SnippetCounter unlockCas = new SnippetCounter(unlockCounters, "unlock{cas}", "cas-unlocked an object"); - public static final SnippetCounter unlockCasRecursive = new SnippetCounter(unlockCounters, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); - public static final SnippetCounter unlockStub = new SnippetCounter(unlockCounters, "unlock{stub}", "stub-unlocked an object"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java index 564e89a36f1..b3f6650f8d5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java @@ -22,8 +22,9 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION; @@ -53,8 +54,10 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext; import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCast; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; @@ -64,8 +67,6 @@ import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; import static org.graalvm.compiler.replacements.nodes.ExplodeLoopNode.explodeLoop; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; -import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; @@ -90,13 +91,13 @@ import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.PrefetchAllocateNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.nodes.debug.VerifyHeapNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; @@ -107,8 +108,10 @@ import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -133,8 +136,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ public class NewObjectSnippets implements Snippets { - public static final LocationIdentity INIT_LOCATION = NamedLocationIdentity.mutable("Initialization"); - enum ProfileContext { AllocatingMethod, InstanceOrArray, @@ -144,8 +145,8 @@ public class NewObjectSnippets implements Snippets { } @Fold - static String createName(String path, String typeContext) { - switch (HotspotSnippetsOptions.ProfileAllocationsContext.getValue()) { + static String createName(String path, String typeContext, OptionValues options) { + switch (ProfileAllocationsContext.getValue(options)) { case AllocatingMethod: return ""; case InstanceOrArray: @@ -161,21 +162,21 @@ public class NewObjectSnippets implements Snippets { } @Fold - static boolean doProfile() { - return HotspotSnippetsOptions.ProfileAllocations.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileAllocations.getValue(options); } @Fold - static boolean withContext() { - ProfileContext context = HotspotSnippetsOptions.ProfileAllocationsContext.getValue(); + static boolean withContext(OptionValues options) { + ProfileContext context = ProfileAllocationsContext.getValue(options); return context == ProfileContext.AllocatingMethod || context == ProfileContext.AllocatedTypesInMethod; } - protected static void profileAllocation(String path, long size, String typeContext) { - if (doProfile()) { - String name = createName(path, typeContext); + protected static void profileAllocation(String path, long size, String typeContext, OptionValues options) { + if (doProfile(options)) { + String name = createName(path, typeContext, options); - boolean context = withContext(); + boolean context = withContext(options); DynamicCounterNode.counter(name, "number of bytes allocated", size, context); DynamicCounterNode.counter(name, "number of allocations", 1, context); } @@ -198,8 +199,14 @@ public class NewObjectSnippets implements Snippets { } @Snippet - public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); + } + + public static Object allocateInstanceHelper(int size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents, + Register threadRegister, boolean constantSize, String typeContext, OptionValues options, Counters counters) { Object result; Word thread = registerAsWord(threadRegister); Word top = readTlabTop(thread); @@ -208,13 +215,15 @@ public class NewObjectSnippets implements Snippets { if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, false); - result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, true); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters); } else { - new_stub.inc(); + if (counters != null && counters.stub != null) { + counters.stub.inc(); + } result = newInstance(HotSpotBackend.NEW_INSTANCE, hub); } - profileAllocation("instance", size, typeContext); - return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + profileAllocation("instance", size, typeContext, options); + return verifyOop(result); } @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) @@ -222,25 +231,37 @@ public class NewObjectSnippets implements Snippets { @Snippet public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { // Klass must be initialized by the time the first instance is allocated, therefore we can // just load it from the corresponding cell and avoid the resolution check. We have to use a // fixed load though, to prevent it from floating above the initialization. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateInstance(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext); + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); } @Snippet - public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister) { - if (probability(SLOW_PATH_PROBABILITY, type == null || DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { + public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + if (probability(SLOW_PATH_PROBABILITY, type == null)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + Class nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor()); + + if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - KlassPointer hub = ClassGetHubNode.readClass(type); + return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType)); + } + + private static Object allocateInstanceDynamicHelper(Class type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class nonNullType) { + KlassPointer hub = ClassGetHubNode.readClass(nonNullType); if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) { - if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { - int layoutHelper = readLayoutHelper(hub); + KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor()); + + if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) { + int layoutHelper = readLayoutHelper(nonNullHub); /* * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number, * the instance size. This size is already passed through align_object_size and @@ -248,12 +269,12 @@ public class NewObjectSnippets implements Snippets { * allocated using the fastpath. */ if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) { - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); /* * FIXME(je,ds): we should actually pass typeContext instead of "" but late * binding of parameters is not yet supported by the GraphBuilderPlugin system. */ - return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, ""); + return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters); } } } @@ -267,28 +288,30 @@ public class NewObjectSnippets implements Snippets { @Snippet public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { KlassPointer picHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArray(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { - Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); + return piArrayCast(verifyOop(result), length); } - private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean maybeUnroll, String typeContext, boolean skipNegativeCheck) { + private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, + boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) { Object result; int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); @@ -300,12 +323,14 @@ public class NewObjectSnippets implements Snippets { probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, true); - newarray_loopInit.inc(); - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true); + if (counters != null && counters.arrayLoopInit != null) { + counters.arrayLoopInit.inc(); + } + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters); } else { result = newArray(HotSpotBackend.NEW_ARRAY, hub, length, fillContents); } - profileAllocation("array", allocationSize, typeContext); + profileAllocation("array", allocationSize, typeContext, options); return result; } @@ -327,13 +352,14 @@ public class NewObjectSnippets implements Snippets { @Snippet public static Object allocateArrayDynamic(Class elementType, Class voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord) { - Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord); + @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, options, counters); return result; } private static Object allocateArrayDynamicImpl(Class elementType, Class voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind, - int knownLayoutHelper, Word prototypeMarkWord) { + int knownLayoutHelper, Word prototypeMarkWord, OptionValues options, Counters counters) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -344,10 +370,15 @@ public class NewObjectSnippets implements Snippets { } KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION); - if (probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, klass.isNull() || length < 0)) { + if (klass.isNull()) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(klass); + KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + + if (length < 0) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(nonNullKlass); //@formatter:off // from src/share/vm/oops/klass.hpp: // @@ -364,8 +395,8 @@ public class NewObjectSnippets implements Snippets { int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); - Object result = allocateArrayImpl(klass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters); + return piArrayCast(verifyOop(result), length); } /** @@ -376,7 +407,7 @@ public class NewObjectSnippets implements Snippets { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - dims.writeInt(i * 4, dimensions[i], INIT_LOCATION); + dims.writeInt(i * 4, dimensions[i], LocationIdentity.init()); } return newArrayCall(HotSpotBackend.NEW_MULTI_ARRAY, hub, rank, dims); } @@ -406,15 +437,15 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, counters); } - private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { + private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; if ((offset & 0x7) != 0) { - memory.writeInt(offset, (int) value, INIT_LOCATION); + memory.writeInt(offset, (int) value, LocationIdentity.init()); offset += 4; } ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset"); @@ -423,31 +454,32 @@ public class NewObjectSnippets implements Snippets { // This case handles arrays of constant length. Instead of having a snippet variant for // each length, generate a chain of stores of maximum length. Once it's inlined the // break statement will trim excess stores. - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } + explodeLoop(); for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) { if (offset == size) { break; } - memory.initializeLong(offset, value, INIT_LOCATION); + memory.initializeLong(offset, value, LocationIdentity.init()); } } else { // Use Word instead of int to avoid extension to long in generated code Word off = Word.signed(offset); if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } explodeLoop(); } else { - if (useSnippetCounters) { - new_loopInit.inc(); + if (counters != null && counters.instanceLoopInit != null) { + counters.instanceLoopInit.inc(); } } for (; off.rawValue() < size; off = off.add(8)) { - memory.initializeLong(off, value, INIT_LOCATION); + memory.initializeLong(off, value, LocationIdentity.init()); } } } @@ -462,8 +494,8 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters); } /** @@ -471,22 +503,22 @@ public class NewObjectSnippets implements Snippets { * since they can't be compiled in stubs. */ public static Object formatObjectForStub(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord) { - return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, false); + return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, null); } /** * Formats some allocated memory with an object header and zeroes out the rest. */ - protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean useSnippetCounters) { + protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) { Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); } @Snippet @@ -505,43 +537,61 @@ public class NewObjectSnippets implements Snippets { * Formats some allocated memory with an object header and zeroes out the rest. */ public static Object formatArray(KlassPointer hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, - boolean useSnippetCounters) { - memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, INIT_LOCATION); + Counters counters) { + memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init()); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field * is not null */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); + } + + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group newInstance = factory.createSnippetCounterGroup("NewInstance"); + Group newArray = factory.createSnippetCounterGroup("NewArray"); + instanceSeqInit = new SnippetCounter(newInstance, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); + instanceLoopInit = new SnippetCounter(newInstance, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + arrayLoopInit = new SnippetCounter(newArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + stub = new SnippetCounter(newInstance, "stub", "alloc and zeroing via stub"); + } + + final SnippetCounter instanceSeqInit; + final SnippetCounter instanceLoopInit; + final SnippetCounter arrayLoopInit; + final SnippetCounter stub; } public static class Templates extends AbstractTemplates { - private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION); private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap"); private final GraalHotSpotVMConfig config; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { + super(options, providers, providers.getSnippetReflection(), target); this.config = config; + counters = new Counters(factory); } /** @@ -554,7 +604,8 @@ public class NewObjectSnippets implements Snippets { ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); int size = instanceSize(type); - SnippetInfo snippet = GeneratePIC.getValue() ? allocateInstancePIC : allocateInstance; + OptionValues localOptions = graph.getOptions(); + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? allocateInstancePIC : allocateInstance; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("size", size); args.add("hub", hub); @@ -562,7 +613,9 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("constantSize", true); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? type.toJavaName(false) : ""); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); @@ -581,8 +634,9 @@ public class NewObjectSnippets implements Snippets { final int headerSize = getArrayBaseOffset(elementKind); int log2ElementSize = CodeUtil.log2(HotSpotJVMCIRuntimeProvider.getArrayIndexScale(elementKind)); + OptionValues localOptions = graph.getOptions(); SnippetInfo snippet; - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { if (elementType.isPrimitive()) { snippet = allocatePrimitiveArrayPIC; } else { @@ -603,7 +657,9 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("maybeUnroll", length.isConstant()); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? arrayType.toJavaName(false) : ""); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); @@ -611,12 +667,15 @@ public class NewObjectSnippets implements Snippets { public void lower(DynamicNewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(allocateInstanceDynamic, newInstanceNode.graph().getGuardsStage(), tool.getLoweringStage()); + OptionValues localOptions = newInstanceNode.getOptions(); args.add("type", newInstanceNode.getInstanceType()); ValueNode classClass = newInstanceNode.getClassClass(); assert classClass != null; args.add("classClass", classClass); args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); @@ -624,6 +683,7 @@ public class NewObjectSnippets implements Snippets { public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); + OptionValues localOptions = graph.getOptions(); Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); ValueNode voidClass = newArrayNode.getVoidClass(); @@ -644,6 +704,8 @@ public class NewObjectSnippets implements Snippets { args.addConst("knownLayoutHelper", 0); } args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } @@ -654,6 +716,7 @@ public class NewObjectSnippets implements Snippets { public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) { StructuredGraph graph = newmultiarrayNode.graph(); + OptionValues localOptions = graph.getOptions(); int rank = newmultiarrayNode.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; for (int i = 0; i < newmultiarrayNode.dimensionCount(); i++) { @@ -662,7 +725,7 @@ public class NewObjectSnippets implements Snippets { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); - SnippetInfo snippet = GeneratePIC.getValue() ? newmultiarrayPIC : newmultiarray; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? newmultiarrayPIC : newmultiarray; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.addConst("rank", rank); @@ -688,13 +751,4 @@ public class NewObjectSnippets implements Snippets { } } } - - private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null; - private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); - private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub"); - - private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null; - private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java index 7e6252df6d3..b0ef4f4b9bc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import java.lang.reflect.Method; import org.graalvm.compiler.core.common.type.StampPair; @@ -86,7 +84,7 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu Assumptions assumptions = graph().getAssumptions(); type = getConcreteType(getObject().stamp()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null), INVALID_COMPILATION_ID); + StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), AllowAssumptions.ifNonNull(assumptions)).build(); ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp()))); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java index b72577f8a5a..099363ba01e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.JavaKind; @@ -62,7 +62,7 @@ public class SHA2Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha2ImplCompressStub(bufAddr, stateAddr); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java index 0abda014a92..9e3b6f04706 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.JavaKind; @@ -62,7 +62,7 @@ public class SHA5Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha5ImplCompressStub(bufAddr, stateAddr); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java index 7d389f087c2..c375eca5404 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.JavaKind; @@ -62,7 +62,7 @@ public class SHASubstitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.shaImplCompressStub(bufAddr, stateAddr); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java index 434ae81a515..b88e0d88c65 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.debug.StringToBytesNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -73,8 +74,8 @@ public class StringToBytesSnippets implements Snippets { private final SnippetInfo create; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); create = snippet(StringToBytesSnippets.class, "transform", NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java index 99fb04dde2d..fa272831c5e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java @@ -45,7 +45,10 @@ import org.graalvm.compiler.word.Word; @ClassSubstitution(Thread.class) public class ThreadSubstitutions { - @MethodSubstitution(isStatic = false) + /** + * hidden in 9. + */ + @MethodSubstitution(isStatic = false, optional = true) public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { Word javaThread = CurrentJavaThreadNode.get(); Object thread = javaThread.readObject(threadObjectOffset(INJECTED_VMCONFIG), JAVA_THREAD_THREAD_OBJECT_LOCATION); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java index b112d1ae3b9..47e256d50dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.METASPACE_ARRAY_LENGTH_LOCATION; @@ -47,6 +46,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.word.Word; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -59,44 +59,44 @@ import jdk.vm.ci.meta.MetaAccessProvider; */ public class TypeCheckSnippetUtils { - static boolean checkSecondarySubType(KlassPointer t, KlassPointer s) { + static boolean checkSecondarySubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // if (S.cache == T) return true - if (s.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { - cacheHit.inc(); + if (sNonNull.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { + counters.cacheHit.inc(); return true; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - static boolean checkUnknownSubType(KlassPointer t, KlassPointer s) { + static boolean checkUnknownSubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // int off = T.offset int superCheckOffset = t.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(INJECTED_VMCONFIG); // if (T = S[off]) return true - if (s.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { + if (sNonNull.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { if (primary) { - cacheHit.inc(); + counters.cacheHit.inc(); } else { - displayHit.inc(); + counters.displayHit.inc(); } return true; } // if (off != &cache) return false if (primary) { - displayMiss.inc(); + counters.displayMiss.inc(); return false; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s) { + private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s, Counters counters) { // if (T == S) return true if (s.equal(t)) { - T_equals_S.inc(); + counters.equalsSecondary.inc(); return true; } @@ -106,14 +106,43 @@ public class TypeCheckSnippetUtils { for (int i = 0; i < length; i++) { if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { s.writeKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), t, SECONDARY_SUPER_CACHE_LOCATION); - secondariesHit.inc(); + counters.secondariesHit.inc(); return true; } } - secondariesMiss.inc(); + counters.secondariesMiss.inc(); return false; } + static class Counters { + final SnippetCounter hintsHit; + final SnippetCounter hintsMiss; + final SnippetCounter exactHit; + final SnippetCounter exactMiss; + final SnippetCounter isNull; + final SnippetCounter cacheHit; + final SnippetCounter secondariesHit; + final SnippetCounter secondariesMiss; + final SnippetCounter displayHit; + final SnippetCounter displayMiss; + final SnippetCounter equalsSecondary; + + Counters(SnippetCounter.Group.Factory factory) { + Group group = factory.createSnippetCounterGroup("TypeCheck"); + hintsHit = new SnippetCounter(group, "hintsHit", "hit a hint type"); + hintsMiss = new SnippetCounter(group, "hintsMiss", "missed a hint type"); + exactHit = new SnippetCounter(group, "exactHit", "exact type test succeeded"); + exactMiss = new SnippetCounter(group, "exactMiss", "exact type test failed"); + isNull = new SnippetCounter(group, "isNull", "object tested was null"); + cacheHit = new SnippetCounter(group, "cacheHit", "secondary type cache hit"); + secondariesHit = new SnippetCounter(group, "secondariesHit", "secondaries scan succeeded"); + secondariesMiss = new SnippetCounter(group, "secondariesMiss", "secondaries scan failed"); + displayHit = new SnippetCounter(group, "displayHit", "primary type test succeeded"); + displayMiss = new SnippetCounter(group, "displayMiss", "primary type test failed"); + equalsSecondary = new SnippetCounter(group, "T_equals_S", "object type was equal to secondary type"); + } + } + /** * A set of type check hints ordered by decreasing probabilities. */ @@ -158,18 +187,4 @@ public class TypeCheckSnippetUtils { static KlassPointer loadSecondarySupersElement(Word metaspaceArray, int index) { return KlassPointer.fromWord(metaspaceArray.readWord(metaspaceArrayBaseOffset(INJECTED_VMCONFIG) + index * wordSize(), SECONDARY_SUPERS_ELEMENT_LOCATION)); } - - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null; - static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type"); - static final SnippetCounter hintsMiss = new SnippetCounter(counters, "hintsMiss", "missed a hint type"); - static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded"); - static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed"); - static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null"); - static final SnippetCounter cacheHit = new SnippetCounter(counters, "cacheHit", "secondary type cache hit"); - static final SnippetCounter secondariesHit = new SnippetCounter(counters, "secondariesHit", "secondaries scan succeeded"); - static final SnippetCounter secondariesMiss = new SnippetCounter(counters, "secondariesMiss", "secondaries scan failed"); - static final SnippetCounter displayHit = new SnippetCounter(counters, "displayHit", "primary type test succeeded"); - static final SnippetCounter displayMiss = new SnippetCounter(counters, "displayMiss", "primary type test failed"); - static final SnippetCounter T_equals_S = new SnippetCounter(counters, "T_equals_S", "object type was equal to secondary type"); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java index 0eef6871a4e..12543b80c54 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java @@ -28,9 +28,10 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -55,11 +56,11 @@ public class UnsafeLoadSnippets implements Snippets { private final SnippetInfo unsafeLoad = snippet(UnsafeLoadSnippets.class, "lowerUnsafeLoad"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } - public void lower(UnsafeLoadNode load, LoweringTool tool) { + public void lower(RawLoadNode load, LoweringTool tool) { Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", load.object()); args.add("offset", load.offset()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java index 526e9a572c9..c075b7f8081 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; @@ -43,16 +43,15 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_P import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.CompressionNode; @@ -65,6 +64,7 @@ import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.StructuredGraph; @@ -78,13 +78,14 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.DirectStoreNode; import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Unsigned; @@ -96,24 +97,38 @@ import jdk.vm.ci.meta.JavaKind; public class WriteBarrierSnippets implements Snippets { - private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; - private static final SnippetCounter serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); - private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); - private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); - private static final SnippetCounter g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); - private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); - private static final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the XOR test)"); - private static final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the NULL test)"); - private static final SnippetCounter g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group countersWriteBarriers = factory.createSnippetCounterGroup("WriteBarriers"); + serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); + g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); + g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); + g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); + g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); + g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the XOR test)"); + g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the NULL test)"); + g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + + } + + final SnippetCounter serialWriteBarrierCounter; + final SnippetCounter g1AttemptedPreWriteBarrierCounter; + final SnippetCounter g1EffectivePreWriteBarrierCounter; + final SnippetCounter g1ExecutedPreWriteBarrierCounter; + final SnippetCounter g1AttemptedPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter; + final SnippetCounter g1ExecutedPostWriteBarrierCounter; + } public static final LocationIdentity GC_CARD_LOCATION = NamedLocationIdentity.mutable("GC-Card"); public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log"); public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index"); - private static void serialWriteBarrier(Pointer ptr) { - serialWriteBarrierCounter.inc(); + private static void serialWriteBarrier(Pointer ptr, Counters counters) { + counters.serialWriteBarrierCounter.inc(); final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress(); Word base = (Word) ptr.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG)); if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) { @@ -124,13 +139,13 @@ public class WriteBarrierSnippets implements Snippets { } @Snippet - public static void serialImpreciseWriteBarrier(Object object) { - serialWriteBarrier(Word.objectToTrackedPointer(object)); + public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.objectToTrackedPointer(object), counters); } @Snippet - public static void serialPreciseWriteBarrier(Address address) { - serialWriteBarrier(Word.fromAddress(address)); + public static void serialPreciseWriteBarrier(Address address, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.fromAddress(address), counters); } @Snippet @@ -154,7 +169,7 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck, - @ConstantParameter Register threadRegister, @ConstantParameter boolean trace) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) { if (nullCheck) { NullCheckNode.nullCheck(address); } @@ -173,7 +188,7 @@ public class WriteBarrierSnippets implements Snippets { log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); } - g1AttemptedPreWriteBarrierCounter.inc(); + counters.g1AttemptedPreWriteBarrierCounter.inc(); // If the concurrent marker is enabled, the barrier is issued. if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. @@ -185,10 +200,10 @@ public class WriteBarrierSnippets implements Snippets { verifyOop(previousOop.toObject()); } } - g1EffectivePreWriteBarrierCounter.inc(); + counters.g1EffectivePreWriteBarrierCounter.inc(); // If the previous value is null the barrier should not be issued. if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { - g1ExecutedPreWriteBarrierCounter.inc(); + counters.g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG)); @@ -209,7 +224,7 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter Register threadRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter Counters counters) { Word thread = registerAsWord(threadRegister); Object fixedValue = FixedValueAnchorNode.getObject(value); verifyOop(object); @@ -245,14 +260,14 @@ public class WriteBarrierSnippets implements Snippets { } Word cardAddress = (Word) cardBase.add(displacement); - g1AttemptedPostWriteBarrierCounter.inc(); + counters.g1AttemptedPostWriteBarrierCounter.inc(); if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) { - g1EffectiveAfterXORPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterXORPostWriteBarrierCounter.inc(); // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); - g1EffectiveAfterNullPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc(); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) { @@ -261,7 +276,7 @@ public class WriteBarrierSnippets implements Snippets { if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue(INJECTED_VMCONFIG))) { log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); - g1ExecutedPostWriteBarrierCounter.inc(); + counters.g1ExecutedPostWriteBarrierCounter.inc(); // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. @@ -386,10 +401,12 @@ public class WriteBarrierSnippets implements Snippets { private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION); private final CompressEncoding oopEncoding; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { + super(options, providers, providers.getSnippetReflection(), target); this.oopEncoding = oopEncoding; + this.counters = new Counters(factory); } public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) { @@ -402,6 +419,7 @@ public class WriteBarrierSnippets implements Snippets { OffsetAddressNode address = (OffsetAddressNode) writeBarrier.getAddress(); args.add("object", address.getBase()); } + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); } @@ -433,7 +451,8 @@ public class WriteBarrierSnippets implements Snippets { args.addConst("doLoad", writeBarrierPre.doLoad()); args.addConst("nullCheck", writeBarrierPre.getNullCheck()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(writeBarrierPre.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); } @@ -457,7 +476,8 @@ public class WriteBarrierSnippets implements Snippets { args.addConst("doLoad", readBarrier.doLoad()); args.addConst("nullCheck", false); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(readBarrier.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); } @@ -486,7 +506,8 @@ public class WriteBarrierSnippets implements Snippets { args.addConst("usePrecise", writeBarrierPost.usePrecise()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(writeBarrierPost.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); } @@ -530,9 +551,9 @@ public class WriteBarrierSnippets implements Snippets { } } - public static boolean traceBarrier() { - return GraalOptions.GCDebugStartCycle.getValue() > 0 && - ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0) > GraalOptions.GCDebugStartCycle.getValue()); + public static boolean traceBarrier(StructuredGraph graph) { + return GraalOptions.GCDebugStartCycle.getValue(graph.getOptions()) > 0 && + ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0) > GraalOptions.GCDebugStartCycle.getValue(graph.getOptions())); } /** @@ -544,7 +565,7 @@ public class WriteBarrierSnippets implements Snippets { public static void validateObject(Object parent, Object child) { if (verifyOops(INJECTED_VMCONFIG) && child != null && !validateOop(VALIDATE_OBJECT, parent, child)) { log(true, "Verification ERROR, Parent: %p Child: %p\n", Word.objectToTrackedPointer(parent).rawValue(), Word.objectToTrackedPointer(child).rawValue()); - DirectObjectStoreNode.storeObject(null, 0, 0, null, LocationIdentity.any(), JavaKind.Object); + VMErrorNode.vmError("Verification ERROR, Parent: %p\n", Word.objectToTrackedPointer(parent).rawValue()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java index 7b0f000f6ed..72c655042f3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +114,8 @@ public class ResolveConstantSnippets implements Snippets { private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java index 08eab361382..6bd7465c9fa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION; @@ -39,7 +38,6 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probabil import java.lang.reflect.Method; import java.util.EnumMap; -import java.util.Map; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; @@ -60,19 +58,22 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; +import org.graalvm.util.UnmodifiableEconomicMap; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -85,64 +86,64 @@ import jdk.vm.ci.meta.ResolvedJavaType; public class ArrayCopySnippets implements Snippets { - private static int checkArrayType(KlassPointer hub) { - int layoutHelper = readLayoutHelper(hub); + private static int checkArrayType(KlassPointer nonNullHub) { + int layoutHelper = readLayoutHelper(nonNullHub); if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return layoutHelper; } - private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { + private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length, Counters counters) { if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, length < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, srcPos > ArrayLengthNode.arrayLength(src) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos > ArrayLengthNode.arrayLength(dest) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkSuccessCounter.inc(); + counters.checkSuccessCounter.inc(); } @Snippet - public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); - zeroLengthStaticCounter.inc(); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); + counters.zeroLengthStaticCounter.inc(); } @Snippet public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter, - @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @@ -152,7 +153,7 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -160,33 +161,33 @@ public class ArrayCopySnippets implements Snippets { if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @Snippet public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc)); KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest)); if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) { counter.inc(); copiedCounter.add(length); - predictedObjectArrayCopyFastPathCounter.inc(); - predictedObjectArrayCopyFastPathCopiedCounter.add(length); + counters.predictedObjectArrayCopyFastPathCounter.inc(); + counters.predictedObjectArrayCopyFastPathCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { - predictedObjectArrayCopySlowPathCounter.inc(); - predictedObjectArrayCopySlowPathCopiedCounter.add(length); + counters.predictedObjectArrayCopySlowPathCounter.inc(); + counters.predictedObjectArrayCopySlowPathCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -198,19 +199,19 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopySlowPathIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, KlassPointer predictedKlass, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument) { + @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopySlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, predictedKlass, elementKind, slowPath, slowPathArgument); } @@ -219,34 +220,35 @@ public class ArrayCopySnippets implements Snippets { * Snippet for unrolled arraycopy. */ @Snippet - public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind) { + public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind, + @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopyUnrollNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, unrolledLength, elementKind); } @Snippet - public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length) { + public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer destKlass = loadHub(nonNullDest); KlassPointer srcKlass = loadHub(nonNullSrc); if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) { // no storecheck required. - objectCheckcastSameTypeCounter.inc(); - objectCheckcastSameTypeCopiedCounter.add(length); + counters.objectCheckcastSameTypeCounter.inc(); + counters.objectCheckcastSameTypeCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION); Word superCheckOffset = Word.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); - objectCheckcastCounter.inc(); - objectCheckcastCopiedCounter.add(length); + counters.objectCheckcastCounter.inc(); + counters.objectCheckcastCopiedCounter.add(length); int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false); if (copiedElements != 0) { /* @@ -261,7 +263,7 @@ public class ArrayCopySnippets implements Snippets { } @Snippet - public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -269,19 +271,19 @@ public class ArrayCopySnippets implements Snippets { if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { int layoutHelper = checkArrayType(srcHub); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace(INJECTED_VMCONFIG)) == 0); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { - genericObjectExactCallCounter.inc(); - genericObjectExactCallCopiedCounter.add(length); + counters.genericObjectExactCallCounter.inc(); + counters.genericObjectExactCallCopiedCounter.add(length); ArrayCopyCallNode.disjointArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, JavaKind.Object); } else { - genericPrimitiveCallCounter.inc(); - genericPrimitiveCallCopiedCounter.add(length); + counters.genericPrimitiveCallCounter.inc(); + counters.genericPrimitiveCallCopiedCounter.add(length); UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper); } } else { - SystemArraycopyCounter.inc(); - SystemArraycopyCopiedCounter.add(length); + counters.systemArraycopyCounter.inc(); + counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -302,8 +304,8 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i >= 0) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i -= scale; } } @@ -313,78 +315,103 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i < end) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i += scale; } } } } - private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null; - private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); - private static final SnippetCounter checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + static class Counters { + final SnippetCounter checkSuccessCounter; + final SnippetCounter checkAIOOBECounter; - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null; + final SnippetCounter objectCheckcastCounter; + final SnippetCounter objectCheckcastSameTypeCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCounter; - private static final SnippetCounter objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + final SnippetCounter genericPrimitiveCallCounter; + final SnippetCounter genericObjectExactCallCounter; + final SnippetCounter systemArraycopyCounter; - private static final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter zeroLengthStaticCounter; + final SnippetCounter zeroLengthDynamicCounter; + final SnippetCounter nonZeroLengthDynamicCounter; - private static final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter nonZeroLengthDynamicCopiedCounter; + final SnippetCounter genericPrimitiveCallCopiedCounter; + final SnippetCounter genericObjectExactCallCopiedCounter; + final SnippetCounter systemArraycopyCopiedCounter; - static void createArraycopyCounter(JavaKind kind) { - arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final SnippetCounter objectCheckcastCopiedCounter; + final SnippetCounter objectCheckcastSameTypeCopiedCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter; - arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + + final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + + Counters(SnippetCounter.Group.Factory factory) { + final Group checkCounters = factory.createSnippetCounterGroup("System.arraycopy checkInputs"); + final Group counters = factory.createSnippetCounterGroup("System.arraycopy"); + final Group copiedCounters = factory.createSnippetCounterGroup("System.arraycopy copied elements"); + final Group lengthCounters = factory.createSnippetCounterGroup("System.arraycopy 0-length checks"); + + checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); + checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + + objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); + + zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); + zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); + nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + + nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); + + objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", + "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + createArraycopyCounter(JavaKind.Byte, counters, copiedCounters); + createArraycopyCounter(JavaKind.Boolean, counters, copiedCounters); + createArraycopyCounter(JavaKind.Char, counters, copiedCounters); + createArraycopyCounter(JavaKind.Short, counters, copiedCounters); + createArraycopyCounter(JavaKind.Int, counters, copiedCounters); + createArraycopyCounter(JavaKind.Long, counters, copiedCounters); + createArraycopyCounter(JavaKind.Float, counters, copiedCounters); + createArraycopyCounter(JavaKind.Double, counters, copiedCounters); + createArraycopyCounter(JavaKind.Object, counters, copiedCounters); + } + + void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) { + arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + + arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + } } - static { - createArraycopyCounter(JavaKind.Byte); - createArraycopyCounter(JavaKind.Boolean); - createArraycopyCounter(JavaKind.Char); - createArraycopyCounter(JavaKind.Short); - createArraycopyCounter(JavaKind.Int); - createArraycopyCounter(JavaKind.Long); - createArraycopyCounter(JavaKind.Float); - createArraycopyCounter(JavaKind.Double); - createArraycopyCounter(JavaKind.Object); - } - - private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter.Group lengthCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy 0-length checks") : null; - - private static final SnippetCounter zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); - private static final SnippetCounter zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); - private static final SnippetCounter nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - - private static final SnippetCounter.Group copiedCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy copied elements") : null; - - private static final SnippetCounter nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - private static final SnippetCounter genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", - "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); - public static class Templates extends SnippetTemplate.AbstractTemplates { - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } private ResolvedJavaMethod originalArraycopy() throws GraalError { @@ -414,6 +441,8 @@ public class ArrayCopySnippets implements Snippets { private final SnippetInfo arraycopyUnrolledWorkSnippet = snippet("arraycopyUnrolledWork"); + private final Counters counters; + protected SnippetInfo snippet(String methodName) { SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, LocationIdentity.any()); info.setOriginalMethod(originalArraycopy()); @@ -538,9 +567,10 @@ public class ArrayCopySnippets implements Snippets { } else if (snippetInfo == arraycopyExactIntrinsicSnippet || snippetInfo == arraycopyPredictedExactIntrinsicSnippet) { assert componentKind != null; args.addConst("elementKind", componentKind); - args.addConst("counter", arraycopyCallCounters.get(componentKind)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(componentKind)); + args.addConst("counter", counters.arraycopyCallCounters.get(componentKind)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(componentKind)); } + args.addConst("counters", counters); instantiate(args, arraycopy); } @@ -564,8 +594,9 @@ public class ArrayCopySnippets implements Snippets { } if (snippetInfo == arraycopyPredictedObjectWorkSnippet) { args.add("objectArrayKlass", arraycopy.getPredictedKlass()); - args.addConst("counter", arraycopyCallCounters.get(JavaKind.Object)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counter", counters.arraycopyCallCounters.get(JavaKind.Object)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counters", counters); } instantiate(args, arraycopy); } @@ -597,8 +628,8 @@ public class ArrayCopySnippets implements Snippets { private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) { StructuredGraph graph = arraycopy.graph(); SnippetTemplate template = template(args); - Map replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); - for (Node originalNode : replacements.keySet()) { + UnmodifiableEconomicMap replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); + for (Node originalNode : replacements.getKeys()) { if (originalNode instanceof Invoke) { Invoke invoke = (Invoke) replacements.get(originalNode); assert invoke.asNode().graph() == graph; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java index 69cb5730036..5cf7505f463 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java @@ -39,20 +39,21 @@ import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.extended.UnsafeCopyNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.word.ObjectAccess; import org.graalvm.compiler.word.Unsigned; import org.graalvm.compiler.word.Word; @@ -205,7 +206,7 @@ public class UnsafeArrayCopySnippets implements Snippets { /** * For this kind, Object, we want to avoid write barriers between writes, but instead have them - * at the end of the snippet. This is done by using {@link DirectObjectStoreNode}, and rely on + * at the end of the snippet. This is done by using {@link RawStoreNode}, and rely on * {@link WriteBarrierAdditionPhase} to put write barriers after the {@link UnsafeArrayCopyNode} * with kind Object. */ @@ -218,14 +219,14 @@ public class UnsafeArrayCopySnippets implements Snippets { if (src == dest && srcPos < destPos) { // bad aliased case long start = (long) (length - 1) * scale; for (long i = start; i >= 0; i -= scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } else { long end = (long) length * scale; for (long i = 0; i < end; i += scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } } @@ -284,8 +285,8 @@ public class UnsafeArrayCopySnippets implements Snippets { private final SnippetInfo[] arraycopySnippets; private final SnippetInfo genericPrimitiveSnippet; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); arraycopySnippets = new SnippetInfo[JavaKind.values().length]; arraycopySnippets[JavaKind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java index 87ce20ab8f9..28822a2aa9a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +114,8 @@ public class ProbabilisticProfileSnippets implements Snippets { private final SnippetInfo profileBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileBackedgeWithProbability"); private final SnippetInfo profileConditionalBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileConditionalBackedgeWithProbability"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java index 98c5588b4d5..4b63201c786 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -95,8 +96,8 @@ public class ProfileSnippets implements Snippets { private final SnippetInfo profileBackedge = snippet(ProfileSnippets.class, "profileBackedge"); private final SnippetInfo profileConditionalBackedge = snippet(ProfileSnippets.class, "profileConditionalBackedge"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java index 9877dc7cd94..bff470d18a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ArrayStoreExceptionStub extends CreateExceptionStub { - public ArrayStoreExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createArrayStoreException", providers, linkage); + public ArrayStoreExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createArrayStoreException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ArrayStoreExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createArrayStoreException(Object object, @ConstantParameter Register threadRegister) { + private static Object createArrayStoreException(@Snippet.NonNullParameter Object object, @ConstantParameter Register threadRegister) { KlassPointer klass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ArrayStoreException.class, klass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java index d9a7aa18f1d..57ccd5dcefe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ClassCastExceptionStub extends CreateExceptionStub { - public ClassCastExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createClassCastException", providers, linkage); + public ClassCastExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createClassCastException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ClassCastExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createClassCastException(Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { + private static Object createClassCastException(@Snippet.NonNullParameter Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { KlassPointer objKlass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ClassCastException.class, objKlass, targetKlass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java index 64360137f71..9a20bde0746 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.CStringConstant; import org.graalvm.compiler.word.Word; @@ -50,8 +51,8 @@ import jdk.vm.ci.code.Register; */ public class CreateExceptionStub extends SnippetStub { - protected CreateExceptionStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetMethodName, providers, linkage); + protected CreateExceptionStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetMethodName, options, providers, linkage); } @Fold diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java deleted file mode 100644 index acfb4e151e6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode.fetchUnrollInfo; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; -import static org.graalvm.compiler.hotspot.stubs.UncommonTrapStub.STACK_BANG_LOCATION; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Deoptimization stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *
  11. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
  12. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
  13. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
  14. deallocate the deoptimization frame - * - *
  15. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
  16. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
  17. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
  18. deallocate the dummy unpack_frame - * - *
  19. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

    - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class DeoptimizationStub extends SnippetStub { - - private final TargetDescription target; - - public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(DeoptimizationStub.class, "deoptimizationHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Deoptimization handler for normal deoptimization - * {@link GraalHotSpotVMConfig#deoptimizationUnpackDeopt}. - */ - @Snippet - private static void deoptimizationHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final Word unrollBlock = fetchUnrollInfo(registerSaver, deoptimizationUnpackDeopt(INJECTED_VMCONFIG)); - - deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - static void deoptimizationCommon(Register stackPointerRegister, final Word thread, final long registerSaver, final Word unrollBlock) { - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame - // 2: deoptimizing frame - // 3: caller of deoptimizing frame (could be compiled/interpreted). - - // Pop self-frame. - LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver); - - // Load the initial info we should save (e.g. frame pointer). - final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset(INJECTED_VMCONFIG)); - - // Pop deoptimized frame. - final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(INJECTED_VMCONFIG)); - LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); - - /* - * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for - * total size of the interpreter frames plus shadow page size. Bang one page at a time - * because large sizes can bang beyond yellow and red zones. - * - * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. - */ - final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset(INJECTED_VMCONFIG)); - final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(INJECTED_VMCONFIG); - Word stackPointer = readRegister(stackPointerRegister); - - for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt((-i * pageSize()) + stackBias(INJECTED_VMCONFIG), 0, STACK_BANG_LOCATION); - } - - // Load number of interpreter frames. - final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame sizes. - final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame PCs. - final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset(INJECTED_VMCONFIG)); - - /* - * Get the current stack pointer (sender's original SP) before adjustment so that we can - * save it in the skeletal interpreter frame. - */ - Word senderSp = readRegister(stackPointerRegister); - - // Adjust old interpreter frame to make space for new frame's extra Java locals. - final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset(INJECTED_VMCONFIG)); - writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); - - for (int i = 0; i < numberOfFrames; i++) { - final Word frameSize = frameSizes.readWord(i * wordSize()); - final Word framePc = framePcs.readWord(i * wordSize()); - - // Push an interpreter frame onto the stack. - PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); - - // Get the current stack pointer (sender SP) and pass it to next frame. - senderSp = readRegister(stackPointerRegister); - } - - // Get final return address. - final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); - - /* - * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an - * unknown alignment we need to align it here before calling C++ code. - */ - final Word senderFp = initialInfo; - EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver); - - final int mode = unrollBlock.readInt(deoptimizationUnrollBlockUnpackKindOffset(INJECTED_VMCONFIG)); - unpackFrames(UNPACK_FRAMES, thread, mode); - - LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockUnpackKindOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockUnpackKindOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java index bd435f90a32..363448792d4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java @@ -41,6 +41,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -48,6 +49,7 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -62,8 +64,8 @@ import jdk.vm.ci.code.Register; */ public class ExceptionHandlerStub extends SnippetStub { - public ExceptionHandlerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("exceptionHandler", providers, linkage); + public ExceptionHandlerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("exceptionHandler", options, providers, linkage); } /** @@ -78,18 +80,21 @@ public class ExceptionHandlerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister) { + private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Word thread = registerAsWord(threadRegister); checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); writeExceptionOop(thread, exception); writeExceptionPc(thread, exceptionPc); - if (logging()) { + if (logging(options)) { printf("handling exception %p (", Word.objectToTrackedPointer(exception).rawValue()); decipher(Word.objectToTrackedPointer(exception).rawValue()); printf(") at %p (", exceptionPc.rawValue()); @@ -102,7 +107,7 @@ public class ExceptionHandlerStub extends SnippetStub { Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at %p is at %p (", Word.objectToTrackedPointer(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue()); decipher(handlerPc.rawValue()); printf(")\n"); @@ -136,23 +141,18 @@ public class ExceptionHandlerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceExceptionHandlerStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceExceptionHandlerStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link ExceptionHandlerStub} or if this - * is a HotSpot build where the ASSERT mechanism is enabled. - *

    - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.ENABLED || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java index ef51bbdf472..0123001acc8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java @@ -47,8 +47,9 @@ import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.replacements.GraphKit; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.word.Word; @@ -99,9 +100,10 @@ public class ForeignCallStub extends Stub { * be re-executed. * @param killedLocations the memory locations killed by the stub call */ - public ForeignCallStub(HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, + public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, + Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { - super(providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, + super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); this.jvmciRuntime = runtime; this.prependThread = prependThread; @@ -224,7 +226,7 @@ public class ForeignCallStub extends Stub { Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn()); - StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options).name(toString()).compilationId(compilationId).build(); graph.disableUnsafeAccessTracking(); GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins()); @@ -245,6 +247,8 @@ public class ForeignCallStub extends Stub { kit.inlineInvokes(); + new RemoveValueProxyPhase().apply(graph); + if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Stub graph before compilation"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java index c30dda95f4c..655cf4eb868 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java @@ -31,7 +31,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH; @@ -57,6 +57,7 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -70,8 +71,8 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; */ public class NewArrayStub extends SnippetStub { - public NewArrayStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newArray", providers, linkage); + public NewArrayStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newArray", options, providers, linkage); } @Override @@ -81,14 +82,16 @@ public class NewArrayStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(3, "intArrayHub"); assert checkConstArg(4, "threadRegister"); + assert checkConstArg(5, "options"); args[3] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[4] = providers.getRegisters().getThreadRegister(); + args[5] = options; return args; } @Fold - static boolean logging() { - return StubOptions.TraceNewArrayStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewArrayStub.getValue(options); } /** @@ -101,13 +104,14 @@ public class NewArrayStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { - int layoutHelper = loadKlassLayoutHelperIntrinsic(hub); + private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options) { + int layoutHelper = readLayoutHelper(hub); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int elementKind = (layoutHelper >> layoutHelperElementTypeShift(INJECTED_VMCONFIG)) & layoutHelperElementTypeMask(INJECTED_VMCONFIG); int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize); - if (logging()) { + if (logging(options)) { printf("newArray: element kind %d\n", elementKind); printf("newArray: array length %d\n", length); printf("newArray: array size %d\n", sizeInBytes); @@ -118,16 +122,16 @@ public class NewArrayStub extends SnippetStub { Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); if (inlineContiguousAllocationSupported && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { - if (logging()) { + if (logging(options)) { printf("newArray: allocated new array at %p\n", memory.rawValue()); } return verifyObject( - formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, false)); + formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, null)); } } - if (logging()) { + if (logging(options)) { printf("newArray: calling new_array_c\n"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java index b6a64dc4b8a..1b804beaff7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.stubs; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_END_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_TOP_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; @@ -37,7 +36,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeTlab; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.log2WordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd; @@ -64,7 +63,6 @@ import static org.graalvm.compiler.hotspot.stubs.StubUtil.printf; import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; - import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; @@ -79,7 +77,7 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -94,8 +92,8 @@ import jdk.vm.ci.meta.JavaKind; */ public class NewInstanceStub extends SnippetStub { - public NewInstanceStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newInstance", providers, linkage); + public NewInstanceStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newInstance", options, providers, linkage); } @Override @@ -105,8 +103,10 @@ public class NewInstanceStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(1, "intArrayHub"); assert checkConstArg(2, "threadRegister"); + assert checkConstArg(3, "options"); args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[2] = providers.getRegisters().getThreadRegister(); + args[3] = options; return args; } @@ -126,8 +126,8 @@ public class NewInstanceStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceNewInstanceStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewInstanceStub.getValue(options); } /** @@ -138,17 +138,17 @@ public class NewInstanceStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { + private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { /* * The type is known to be an instance so Klass::_layout_helper is the instance size as a * raw number */ - int sizeInBytes = loadKlassLayoutHelperIntrinsic(hub); Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); - if (!forceSlowPath() && inlineContiguousAllocationSupported) { + if (!forceSlowPath(options) && inlineContiguousAllocationSupported) { if (isInstanceKlassFullyInitialized(hub)) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + int sizeInBytes = readLayoutHelper(hub); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord); @@ -157,7 +157,7 @@ public class NewInstanceStub extends SnippetStub { } } - if (logging()) { + if (logging(options)) { printf("newInstance: calling new_instance_c\n"); } @@ -229,7 +229,7 @@ public class NewInstanceStub extends SnippetStub { // an int int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; - NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, false); + NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, null); long allocated = thread.readLong(threadAllocatedBytesOffset(INJECTED_VMCONFIG), TLAB_THREAD_ALLOCATED_BYTES_LOCATION); allocated = allocated + top.subtract(readTlabStart(thread)).rawValue(); @@ -291,16 +291,15 @@ public class NewInstanceStub extends SnippetStub { if (newHeapTop.aboveThan(heapEnd)) { return Word.zero(); } - - if (compareAndSwap(RawAddressNode.address(heapTopAddress), heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) { + if (heapTopAddress.logicCompareAndSwapWord(0, heapTop, newHeapTop, HEAP_TOP_LOCATION)) { return heapTop; } } } @Fold - static boolean forceSlowPath() { - return StubOptions.ForceUseOfNewInstanceStub.getValue(); + static boolean forceSlowPath(OptionValues options) { + return StubOptions.ForceUseOfNewInstanceStub.getValue(options); } public static final ForeignCallDescriptor NEW_INSTANCE_C = newDescriptor(NewInstanceStub.class, "newInstanceC", void.class, Word.class, KlassPointer.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java index b5ba143de37..662bce4c731 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -35,8 +36,8 @@ import jdk.vm.ci.code.Register; */ public class NullPointerExceptionStub extends CreateExceptionStub { - public NullPointerExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createNullPointerException", providers, linkage); + public NullPointerExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createNullPointerException", options, providers, linkage); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java index 095680062ee..c162328ae94 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.AllocaNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -37,8 +38,8 @@ import jdk.vm.ci.code.Register; */ public class OutOfBoundsExceptionStub extends CreateExceptionStub { - public OutOfBoundsExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createOutOfBoundsException", providers, linkage); + public OutOfBoundsExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createOutOfBoundsException", options, providers, linkage); } private static final int MAX_INT_STRING_SIZE = Integer.toString(Integer.MIN_VALUE).length(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java index b645d8944d2..28265e0f2fc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java @@ -22,31 +22,35 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Method; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; import org.graalvm.compiler.replacements.SnippetTemplate; @@ -71,8 +75,8 @@ public abstract class SnippetStub extends Stub implements Snippets { * this object * @param linkage linkage details for a call to the stub */ - public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - this(null, snippetMethodName, providers, linkage); + public SnippetStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + this(null, snippetMethodName, options, providers, linkage); } /** @@ -84,21 +88,12 @@ public abstract class SnippetStub extends Stub implements Snippets { * {@code snippetDeclaringClass} * @param linkage linkage details for a call to the stub */ - public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(providers, linkage); + public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(options, providers, linkage); Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal SnippetGraphUnderConstruction = assertionsEnabled() ? new ThreadLocal<>() : null; - @Override @SuppressWarnings("try") protected StructuredGraph getGraph(CompilationIdentifier compilationId) { @@ -112,29 +107,25 @@ public abstract class SnippetStub extends Stub implements Snippets { // Stubs cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. - final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, NO_PROFILING_INFO, compilationId); + final StructuredGraph graph = new StructuredGraph.Builder(options).method(method).compilationId(compilationId).build(); try (Scope outer = Debug.scope("SnippetStub", graph)) { graph.disableUnsafeAccessTracking(); - if (SnippetGraphUnderConstruction != null) { - assert SnippetGraphUnderConstruction.get() == null : SnippetGraphUnderConstruction.get().toString() + " " + graph; - SnippetGraphUnderConstruction.set(graph); - } + IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING); + GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), + providers.getConstantReflection(), providers.getConstantFieldProvider(), + config, OptimisticOptimizations.NONE, + initialIntrinsicContext); + instance.apply(graph); - try { - IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, providers.getReplacements().getReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), - providers.getConstantReflection(), providers.getConstantFieldProvider(), - config, OptimisticOptimizations.NONE, - initialIntrinsicContext); - instance.apply(graph); - - } finally { - if (SnippetGraphUnderConstruction != null) { - SnippetGraphUnderConstruction.set(null); + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { + int index = param.index(); + if (method.getParameterAnnotation(NonNullParameter.class, index) != null) { + param.setStamp(param.stamp().join(StampFactory.objectNonNull())); } } + new RemoveValueProxyPhase().apply(graph); graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); PhaseContext context = new PhaseContext(providers); @@ -147,6 +138,10 @@ public abstract class SnippetStub extends Stub implements Snippets { return graph; } + protected BytecodeProvider getReplacementsBytecodeProvider() { + return providers.getReplacements().getReplacementBytecodeProvider(); + } + protected boolean checkConstArg(int index, String expectedName) { assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); LocalVariableTable lvt = method.getLocalVariableTable(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index 8857bd417a6..aac65f2a272 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -26,13 +26,9 @@ import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; +import static org.graalvm.util.CollectionsUtil.allMatch; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.ListIterator; -import java.util.Set; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -50,9 +46,11 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.profiling.MoveProfilingPhase; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; @@ -77,8 +75,6 @@ import jdk.vm.ci.meta.TriState; */ public abstract class Stub { - private static final List stubs = new ArrayList<>(); - /** * The linkage information for a call to this stub from compiled code. */ @@ -92,11 +88,21 @@ public abstract class Stub { /** * The registers destroyed by this stub (from the caller's perspective). */ - private Set destroyedCallerRegisters; + private EconomicSet destroyedCallerRegisters; - public void initDestroyedCallerRegisters(Set registers) { + private static boolean checkRegisterSetEquivalency(EconomicSet a, EconomicSet b) { + if (a == b) { + return true; + } + if (a.size() != b.size()) { + return false; + } + return allMatch(a, e -> b.contains(e)); + } + + public void initDestroyedCallerRegisters(EconomicSet registers) { assert registers != null; - assert destroyedCallerRegisters == null || registers.equals(destroyedCallerRegisters) : "cannot redefine"; + assert destroyedCallerRegisters == null || checkRegisterSetEquivalency(registers, destroyedCallerRegisters) : "cannot redefine"; destroyedCallerRegisters = registers; } @@ -104,7 +110,7 @@ public abstract class Stub { * Gets the registers destroyed by this stub from a caller's perspective. These are the * temporaries of this stub and must thus be caller saved by a callers of this stub. */ - public Set getDestroyedCallerRegisters() { + public EconomicSet getDestroyedCallerRegisters() { assert destroyedCallerRegisters != null : "not yet initialized"; return destroyedCallerRegisters; } @@ -117,6 +123,7 @@ public abstract class Stub { return true; } + protected final OptionValues options; protected final HotSpotProviders providers; /** @@ -124,17 +131,10 @@ public abstract class Stub { * * @param linkage linkage details for a call to the stub */ - public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { this.linkage = linkage; + this.options = options; this.providers = providers; - stubs.add(this); - } - - /** - * Gets an immutable view of all stubs that have been created. - */ - public static Collection getStubs() { - return Collections.unmodifiableList(stubs); } /** @@ -178,6 +178,7 @@ public abstract class Stub { if (code == null) { try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { CodeCacheProvider codeCache = providers.getCodeCache(); + CompilationResult compResult = buildCompilationResult(backend); try (Scope s = Debug.scope("CodeInstall", compResult)) { assert destroyedCallerRegisters != null; @@ -199,7 +200,7 @@ public abstract class Stub { @SuppressWarnings("try") private CompilationResult buildCompilationResult(final Backend backend) { - CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue()); + CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options)); final StructuredGraph graph = getGraph(getStubCompilationId()); // Stubs cannot be recompiled so they cannot be compiled with assumptions @@ -275,12 +276,12 @@ public abstract class Stub { } protected Suites createSuites() { - Suites defaultSuites = providers.getSuites().getDefaultSuites(); + Suites defaultSuites = providers.getSuites().getDefaultSuites(options); return new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier()); } protected LIRSuites createLIRSuites() { - LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites()); + LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites(options)); ListIterator> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfilingPhase.class); if (moveProfiling != null) { moveProfiling.remove(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java index 87425f72781..c4db6e94c01 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.hotspot.stubs; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; //JaCoCo Exclude @@ -37,18 +37,18 @@ import org.graalvm.compiler.options.OptionValue; public class StubOptions { // @formatter:off @Option(help = "Trace execution of stub used to handle an exception thrown by a callee.", type = OptionType.Debug) - static final OptionValue TraceExceptionHandlerStub = new OptionValue<>(false); + static final OptionKey TraceExceptionHandlerStub = new OptionKey<>(false); @Option(help = "Trace execution of the stub that routes an exception to a handler in the calling frame.", type = OptionType.Debug) - static final OptionValue TraceUnwindStub = new OptionValue<>(false); + static final OptionKey TraceUnwindStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for array allocation.", type = OptionType.Debug) - static final OptionValue TraceNewArrayStub = new OptionValue<>(false); + static final OptionKey TraceNewArrayStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for non-array object allocation.", type = OptionType.Debug) - static final OptionValue TraceNewInstanceStub = new OptionValue<>(false); + static final OptionKey TraceNewInstanceStub = new OptionKey<>(false); @Option(help = "Force non-array object allocation to always use the slow path.", type = OptionType.Debug) - static final OptionValue ForceUseOfNewInstanceStub = new OptionValue<>(false); + static final OptionKey ForceUseOfNewInstanceStub = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java index 169a03ede3f..600e773b2ba 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java @@ -43,11 +43,11 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.word.Pointer; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java deleted file mode 100644 index 2c981eaee79..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readPendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writePendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Uncommon trap stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *

  20. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
  21. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
  22. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
  23. deallocate the deoptimization frame - * - *
  24. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
  25. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
  26. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
  27. deallocate the dummy unpack_frame - * - *
  28. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

    - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class UncommonTrapStub extends SnippetStub { - - public static final LocationIdentity STACK_BANG_LOCATION = NamedLocationIdentity.mutable("stack bang"); - - private final TargetDescription target; - - public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(UncommonTrapStub.class, "uncommonTrapHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Uncommon trap handler. - * - * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This - * routine captures the return values and returns a structure which describes the current frame - * size and the sizes of all replacement frames. The current frame is compiled code and may - * contain many inlined functions, each with their own JVM state. We pop the current frame, then - * push all the new frames. Then we call the C routine unpack_frames() to populate these frames. - * Finally unpack_frames() returns us the new target address. Notice that callee-save registers - * are BLOWN here; they have already been captured in the vframeArray at the time the return PC - * was patched. - */ - @Snippet - private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final int actionAndReason = readPendingDeoptimization(thread); - writePendingDeoptimization(thread, -1); - - final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason, deoptimizationUnpackUncommonTrap(INJECTED_VMCONFIG)); - - DeoptimizationStub.deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java index 5c8e0869c3d..0971bac61cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.checkExceptionNotNull; @@ -36,6 +37,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -43,6 +45,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.nodes.UnwindNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; @@ -54,8 +57,8 @@ import jdk.vm.ci.code.Register; */ public class UnwindExceptionToCallerStub extends SnippetStub { - public UnwindExceptionToCallerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("unwindExceptionToCaller", providers, linkage); + public UnwindExceptionToCallerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("unwindExceptionToCaller", options, providers, linkage); } /** @@ -69,14 +72,17 @@ public class UnwindExceptionToCallerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) { + private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Pointer exceptionOop = Word.objectToTrackedPointer(exception); - if (logging()) { + if (logging(options)) { printf("unwinding exception %p (", exceptionOop.rawValue()); decipher(exceptionOop.rawValue()); printf(") at %p (", returnAddress.rawValue()); @@ -84,12 +90,12 @@ public class UnwindExceptionToCallerStub extends SnippetStub { printf(")\n"); } Word thread = registerAsWord(threadRegister); - checkNoExceptionInThread(thread, assertionsEnabled(null)); - checkExceptionNotNull(assertionsEnabled(null), exception); + checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); + checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue()); decipher(handlerInCallerPc.rawValue()); printf(")\n"); @@ -99,23 +105,18 @@ public class UnwindExceptionToCallerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceUnwindStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceUnwindStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link UnwindExceptionToCallerStub} or - * if this is a HotSpot build where the ASSERT mechanism is enabled. - *

    - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.ENABLED || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java index ea11ef50079..dcd7442d462 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java @@ -28,14 +28,15 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; /** * Stub called via {@link HotSpotHostForeignCallsProvider#VERIFY_OOP}. */ public class VerifyOopStub extends SnippetStub { - public VerifyOopStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("verifyOop", providers, linkage); + public VerifyOopStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("verifyOop", options, providers, linkage); } @Snippet diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java index 434471c08b7..52ac6685b5d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java @@ -518,17 +518,6 @@ public abstract class MetaspacePointer { @Operation(opcode = Opcode.WRITE_POINTER) public abstract void writeWord(int offset, WordBase val, LocationIdentity locationIdentity); - /** - * Initializes the memory at address {@code (this + offset)}. Both the base address and offset - * are in bytes. The memory must be uninitialized or zero prior to this operation. - * - * @param offset the signed offset for the memory access - * @param locationIdentity the identity of the write - * @param val the value to be written to memory - */ - @Operation(opcode = Opcode.INITIALIZE) - public abstract void initializeLong(int offset, long val, LocationIdentity locationIdentity); - /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java index 725e6494bd5..19628d8152a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java @@ -81,7 +81,6 @@ import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -93,9 +92,11 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.CollectionsFactory; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.ExceptionHandler; @@ -157,7 +158,7 @@ public final class BciBlockMapping { public JSRData jsrData; public static class JSRData implements Cloneable { - public HashMap jsrAlternatives; + public EconomicMap jsrAlternatives; public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; public BciBlock jsrSuccessor; public int jsrReturnBci; @@ -361,7 +362,7 @@ public final class BciBlockMapping { } } - public HashMap getJsrAlternatives() { + public EconomicMap getJsrAlternatives() { if (this.jsrData == null) { return null; } else { @@ -372,7 +373,7 @@ public final class BciBlockMapping { public void initJsrAlternatives() { JSRData data = this.getOrCreateJSRData(); if (data.jsrAlternatives == null) { - data.jsrAlternatives = new HashMap<>(); + data.jsrAlternatives = EconomicMap.create(Equivalence.DEFAULT); } } @@ -415,7 +416,7 @@ public final class BciBlockMapping { public static class ExceptionDispatchBlock extends BciBlock { - private HashMap exceptionDispatch = new HashMap<>(); + private EconomicMap exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); public ExceptionHandler handler; public int deoptBci; @@ -458,13 +459,13 @@ public final class BciBlockMapping { /** * Builds the block map and conservative CFG and numbers blocks. */ - public void build(BytecodeStream stream) { + public void build(BytecodeStream stream, OptionValues options) { int codeSize = code.getCodeSize(); BciBlock[] blockMap = new BciBlock[codeSize]; makeExceptionEntries(blockMap); iterateOverBytecodes(blockMap, stream); if (hasJsrBytecodes) { - if (!SupportJsrBytecodes.getValue()) { + if (!SupportJsrBytecodes.getValue(options)) { throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); } createJsrAlternatives(blockMap, blockMap[0]); @@ -753,7 +754,14 @@ public final class BciBlockMapping { } } - private HashMap initialExceptionDispatch = CollectionsFactory.newMap(); + private EconomicMap initialExceptionDispatch; + + private EconomicMap getInitialExceptionDispatch() { + if (initialExceptionDispatch == null) { + initialExceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); + } + return initialExceptionDispatch; + } private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) { ExceptionDispatchBlock lastHandler = null; @@ -767,7 +775,7 @@ public final class BciBlockMapping { lastHandler = null; } - HashMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : initialExceptionDispatch; + EconomicMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : getInitialExceptionDispatch(); ExceptionDispatchBlock curHandler = exceptionDispatch.get(h); if (curHandler == null) { curHandler = new ExceptionDispatchBlock(); @@ -1040,9 +1048,9 @@ public final class BciBlockMapping { return loops; } - public static BciBlockMapping create(BytecodeStream stream, Bytecode code) { + public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options) { BciBlockMapping map = new BciBlockMapping(code); - map.build(stream); + map.build(stream, options); if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { Debug.dump(Debug.INFO_LOG_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 7ace642641e..3dcfbf272a1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -22,6 +22,18 @@ */ package org.graalvm.compiler.java; +import static java.lang.String.format; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; +import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; +import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; +import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; +import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL; @@ -227,38 +239,27 @@ import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH; import static org.graalvm.compiler.bytecode.Bytecodes.nameOf; import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation; import static org.graalvm.compiler.core.common.GraalOptions.ResolveClassBeforeStaticInvoke; +import static org.graalvm.compiler.core.common.GraalOptions.StressExplicitExceptionCode; import static org.graalvm.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull; import static org.graalvm.compiler.debug.GraalError.guarantee; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding; +import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins; import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull; -import static java.lang.String.format; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; -import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; -import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; -import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; -import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; -import java.lang.ref.Reference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Formatter; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; @@ -268,21 +269,21 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; +import org.graalvm.compiler.bytecode.Bytes; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; @@ -296,7 +297,6 @@ import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.java.BciBlockMapping.ExceptionDispatchBlock; -import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; @@ -361,12 +361,8 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; -import org.graalvm.compiler.nodes.debug.instrumentation.InstrumentationBeginNode; import org.graalvm.compiler.nodes.extended.AnchoringNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; -import org.graalvm.compiler.nodes.extended.GuardedNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; @@ -402,7 +398,10 @@ import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; @@ -582,6 +581,7 @@ public class BytecodeParser implements GraphBuilderContext { private final GraphBuilderPhase.Instance graphBuilderInstance; protected final StructuredGraph graph; + protected final OptionValues options; private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -606,8 +606,6 @@ public class BytecodeParser implements GraphBuilderContext { private FixedWithNextNode[] firstInstructionArray; private FrameStateBuilder[] entryStateArray; - private int lastBCI; // BCI of lastInstr. This field is for resolving instrumentation target. - private boolean finalBarrierRequired; private ValueNode originalReceiver; @@ -618,6 +616,7 @@ public class BytecodeParser implements GraphBuilderContext { this.method = code.getMethod(); this.graphBuilderInstance = graphBuilderInstance; this.graph = graph; + this.options = graph.getOptions(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; this.metaAccess = graphBuilderInstance.metaAccess; @@ -630,7 +629,6 @@ public class BytecodeParser implements GraphBuilderContext { this.intrinsicContext = intrinsicContext; this.entryBCI = entryBCI; this.parent = parent; - this.lastBCI = -1; assert code.getCode() != null : "method must contain bytecodes: " + method; @@ -675,7 +673,7 @@ public class BytecodeParser implements GraphBuilderContext { @SuppressWarnings("try") protected void build(FixedWithNextNode startInstruction, FrameStateBuilder startFrameState) { - if (PrintProfilingInformation.getValue() && profilingInfo != null) { + if (PrintProfilingInformation.getValue(options) && profilingInfo != null) { TTY.println("Profiling info for " + method.format("%H.%n(%p)")); TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } @@ -688,7 +686,7 @@ public class BytecodeParser implements GraphBuilderContext { } // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping newMapping = BciBlockMapping.create(stream, code); + BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()]; @@ -741,6 +739,8 @@ public class BytecodeParser implements GraphBuilderContext { } if (method.isSynchronized()) { + finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI); + // add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); frameState.clearNonLiveLocals(startBlock, liveness, true); @@ -754,7 +754,7 @@ public class BytecodeParser implements GraphBuilderContext { profilingPlugin.profileInvoke(this, method, stateBefore); } - finishPrepare(lastInstr); + finishPrepare(lastInstr, 0); genInfoPointNode(InfopointReason.METHOD_START, null); @@ -771,7 +771,7 @@ public class BytecodeParser implements GraphBuilderContext { processBlock(block); } - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue() && this.beforeReturnNode != startInstruction) { + if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue(options) && this.beforeReturnNode != startInstruction) { Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Bytecodes parsed: %s.%s", method.getDeclaringClass().getUnqualifiedName(), method.getName()); } } @@ -800,11 +800,12 @@ public class BytecodeParser implements GraphBuilderContext { } /** - * Hook for subclasses to modify the graph start instruction or append new instructions to it. + * Hook for subclasses to modify synthetic code (start nodes and unwind nodes). * - * @param startInstr the start instruction of the graph + * @param instruction the current last instruction + * @param bci the current bci */ - protected void finishPrepare(FixedWithNextNode startInstr) { + protected void finishPrepare(FixedWithNextNode instruction, int bci) { } protected void cleanupFinalGraph() { @@ -823,46 +824,13 @@ public class BytecodeParser implements GraphBuilderContext { Node predecessor = beginNode.predecessor(); if (predecessor instanceof ControlSplitNode) { // The begin node is necessary. - } else { - if (beginNode.hasUsages()) { - reanchorGuardedNodes(beginNode); - } + } else if (!beginNode.hasUsages()) { GraphUtil.unlinkFixedNode(beginNode); beginNode.safeDelete(); } } } - /** - * Removes {@link GuardedNode}s from {@code beginNode}'s usages and re-attaches them to an - * appropriate preceeding {@link GuardingNode}. - */ - protected void reanchorGuardedNodes(BeginNode beginNode) { - // Find the new guarding node - GuardingNode guarding = null; - Node pred = beginNode.predecessor(); - while (pred != null) { - if (pred instanceof BeginNode) { - if (pred.predecessor() instanceof ControlSplitNode) { - guarding = (GuardingNode) pred; - break; - } - } else if (pred.getNodeClass().getAllowedUsageTypes().contains(InputType.Guard)) { - guarding = (GuardingNode) pred; - break; - } - pred = pred.predecessor(); - } - - // Reset the guard for all of beginNode's usages - for (Node usage : beginNode.usages().snapshot()) { - GuardedNode guarded = (GuardedNode) usage; - assert guarded.getGuard() == beginNode; - guarded.setGuard(guarding); - } - assert beginNode.hasNoUsages() : beginNode; - } - /** * Creates the frame state after the start node of a graph for an {@link IntrinsicContext * intrinsic} that is the parse root (either for root compiling or for post-parse inlining). @@ -1234,12 +1202,13 @@ public class BytecodeParser implements GraphBuilderContext { } BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); AbstractBeginNode falseSucc = graph.add(new BeginNode()); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, receiver.stamp().join(objectNonNull()), falseSucc)); + PiNode nonNullReceiver = graph.unique(new PiNode(receiver, objectNonNull(), falseSucc)); append(new IfNode(graph.unique(IsNullNode.create(receiver)), exception, falseSucc, 0.01)); lastInstr = falseSucc; exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci())); + EXPLICIT_EXCEPTIONS.increment(); return nonNullReceiver; } @@ -1283,7 +1252,7 @@ public class BytecodeParser implements GraphBuilderContext { if (callTargetIsResolved(target)) { ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); - if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) { + if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue(options)) { handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode classInit = null; @@ -1402,6 +1371,11 @@ public class BytecodeParser implements GraphBuilderContext { } } + @Override + public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) { + createNonInlinedInvoke(callTarget, resultType, null); + } + private Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { ResolvedJavaMethod targetMethod = initialTargetMethod; InvokeKind invokeKind = initialInvokeKind; @@ -1415,7 +1389,7 @@ public class BytecodeParser implements GraphBuilderContext { } JavaKind resultType = targetMethod.getSignature().getReturnKind(); - if (DeoptALot.getValue()) { + if (!parsingIntrinsic() && DeoptALot.getValue(options)) { append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph)); return null; @@ -1426,7 +1400,7 @@ public class BytecodeParser implements GraphBuilderContext { returnType = returnType.resolve(targetMethod.getDeclaringClass()); } if (invokeKind.hasReceiver()) { - args[0] = emitExplicitExceptions(args[0], null); + args[0] = emitExplicitExceptions(args[0]); if (args[0].isNullConstant()) { append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); @@ -1439,15 +1413,15 @@ public class BytecodeParser implements GraphBuilderContext { currentInvokeReturnType = returnType; currentInvokeKind = invokeKind; if (tryNodePluginForInvocation(args, targetMethod)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; } - if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue() && !GeneratePIC.getValue())) { + if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) { if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; @@ -1466,7 +1440,7 @@ public class BytecodeParser implements GraphBuilderContext { } JavaTypeProfile profile = null; - if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { + if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { profile = profilingInfo.getTypeProfile(bci()); } return createNonInlinedInvoke(args, targetMethod, invokeKind, resultType, returnType, inlineInfo, profile); @@ -1481,16 +1455,7 @@ public class BytecodeParser implements GraphBuilderContext { } MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnStamp, profile)); - - Invoke invoke; - if (omitInvokeExceptionEdge(callTarget, inlineInfo)) { - invoke = createInvoke(callTarget, resultType); - } else { - invoke = createInvokeWithException(callTarget, resultType); - AbstractBeginNode beginNode = graph.add(new KillingBeginNode(LocationIdentity.any())); - invoke.setNext(beginNode); - lastInstr = beginNode; - } + Invoke invoke = createNonInlinedInvoke(callTarget, resultType, inlineInfo); for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { plugin.notifyNotInlined(this, targetMethod, invoke); @@ -1499,26 +1464,41 @@ public class BytecodeParser implements GraphBuilderContext { return invoke; } + protected Invoke createNonInlinedInvoke(CallTargetNode callTarget, JavaKind resultType, InlineInfo inlineInfo) { + if (omitInvokeExceptionEdge(callTarget, inlineInfo)) { + return createInvoke(callTarget, resultType); + } else { + Invoke invoke = createInvokeWithException(callTarget, resultType); + AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any())); + invoke.setNext(beginNode); + lastInstr = beginNode; + return invoke; + } + } + /** * If the method returns true, the invocation of the given {@link MethodCallTargetNode call * target} does not need an exception edge. * * @param callTarget The call target. */ - protected boolean omitInvokeExceptionEdge(MethodCallTargetNode callTarget, InlineInfo lastInlineInfo) { + protected boolean omitInvokeExceptionEdge(CallTargetNode callTarget, InlineInfo lastInlineInfo) { if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) { return false; } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) { return true; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) { return false; + } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) { + return false; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { return true; } else { assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile; // be conservative if information was not recorded (could result in endless // recompiles otherwise) - return (!StressInvokeWithExceptionNode.getValue() && optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE); + return (!StressInvokeWithExceptionNode.getValue(options) && optimisticOpts.useExceptionProbability(getOptions()) && profilingInfo != null && + profilingInfo.getExceptionSeen(bci()) == TriState.FALSE); } } @@ -1537,7 +1517,7 @@ public class BytecodeParser implements GraphBuilderContext { final Mark mark; InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { - guarantee(assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); + guarantee(Assertions.ENABLED, "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); this.plugin = plugin; this.targetMethod = targetMethod; this.args = args; @@ -1622,7 +1602,7 @@ public class BytecodeParser implements GraphBuilderContext { receiverType = targetMethod.getDeclaringClass(); } ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass()); - if (resolvedMethod == null || resolvedMethod == targetMethod) { + if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) { assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass()); Mark mark = graph.getMark(); FixedWithNextNode currentLastInstr = lastInstr; @@ -1634,7 +1614,7 @@ public class BytecodeParser implements GraphBuilderContext { LogicNode compare = graph.unique(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection)); JavaTypeProfile profile = null; - if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { + if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { profile = profilingInfo.getTypeProfile(bci()); if (profile != null) { JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod); @@ -1769,7 +1749,7 @@ public class BytecodeParser implements GraphBuilderContext { } } - InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; + InvocationPluginAssertions assertions = Assertions.ENABLED ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; if (plugin.execute(this, targetMethod, pluginReceiver, args)) { afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType); return true; @@ -1825,6 +1805,33 @@ public class BytecodeParser implements GraphBuilderContext { return null; } + private static final int ACCESSOR_BYTECODE_LENGTH = 5; + + /** + * Tries to inline {@code targetMethod} if it is an instance field accessor. This avoids the + * overhead of creating and using a nested {@link BytecodeParser} object. + */ + private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) { + byte[] bytecode = targetMethod.getCode(); + if (bytecode.length == ACCESSOR_BYTECODE_LENGTH && + Bytes.beU1(bytecode, 0) == ALOAD_0 && + Bytes.beU1(bytecode, 1) == GETFIELD) { + int b4 = Bytes.beU1(bytecode, 4); + if (b4 >= IRETURN && b4 <= ARETURN) { + int cpi = Bytes.beU2(bytecode, 2); + JavaField field = targetMethod.getConstantPool().lookupField(cpi, targetMethod, GETFIELD); + if (field instanceof ResolvedJavaField) { + ValueNode receiver = invocationPluginReceiver.init(targetMethod, args).get(); + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)"); + return true; + } + } + } + return false; + } + @Override public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { if (receiver != null) { @@ -1836,14 +1843,16 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) { - if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { - if (targetMethod.equals(inlinedMethod)) { - traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); - } else { - traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); - } - } + traceInlining(targetMethod, inlinedMethod); IntrinsicContext intrinsic = this.intrinsicContext; + + if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() && + targetMethod.equals(inlinedMethod) && + (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 && + tryFastInlineAccessor(args, targetMethod)) { + return true; + } + if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) { if (intrinsic.isCompilationRoot()) { // A root compiled intrinsic needs to deoptimize @@ -1888,8 +1897,18 @@ public class BytecodeParser implements GraphBuilderContext { return true; } + private void traceInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod) { + if (TraceInlineDuringParsing.getValue(options) || TraceParserPlugins.getValue(options)) { + if (targetMethod.equals(inlinedMethod)) { + traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); + } else { + traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); + } + } + } + private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) { - if (GraalOptions.HotSpotPrintInlining.getValue()) { + if (HotSpotPrintInlining.getValue(options)) { if (targetMethod.equals(inlinedMethod)) { Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s", msg); } else { @@ -2051,7 +2070,11 @@ public class BytecodeParser implements GraphBuilderContext { genInfoPointNode(InfopointReason.METHOD_END, x); if (finalBarrierRequired) { assert originalReceiver != null; - append(new FinalFieldBarrierNode(originalReceiver)); + /* + * When compiling an OSR with a final field store, don't bother tracking the original + * receiver since the receiver cannot be EA'ed. + */ + append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null)); } synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind); } @@ -2076,7 +2099,7 @@ public class BytecodeParser implements GraphBuilderContext { if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject))); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, escapedReturnValue)); + MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue)); monitorExit.setStateAfter(createFrameState(bci, monitorExit)); } @@ -2182,25 +2205,6 @@ public class BytecodeParser implements GraphBuilderContext { } private void updateLastInstruction(T v) { - if (UseGraalInstrumentation.getValue()) { - // resolve instrumentation target - if (v instanceof InstrumentationBeginNode) { - InstrumentationBeginNode begin = (InstrumentationBeginNode) v; - if (!begin.isAnchored() && lastBCI != -1) { - int currentBCI = stream.currentBCI(); - // temporarily set the bytecode stream to lastBCI - stream.setBCI(lastBCI); - // The instrumentation should be associated with the predecessor. In case of the - // predecessor being optimized away, e.g., inlining, we should not set the - // target. - if (stream.nextBCI() == currentBCI) { - begin.setTarget(lastInstr); - } - // restore the current BCI - stream.setBCI(currentBCI); - } - } - } if (v instanceof FixedNode) { FixedNode fixedNode = (FixedNode) v; lastInstr.setNext(fixedNode); @@ -2208,10 +2212,8 @@ public class BytecodeParser implements GraphBuilderContext { FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; lastInstr = fixedWithNextNode; - lastBCI = stream.currentBCI(); } else { lastInstr = null; - lastBCI = -1; } } } @@ -2433,7 +2435,7 @@ public class BytecodeParser implements GraphBuilderContext { if (block == blockMap.getReturnBlock()) { handleReturnBlock(); } else if (block == blockMap.getUnwindBlock()) { - handleUnwindBlock(); + handleUnwindBlock((ExceptionDispatchBlock) block); } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { @@ -2443,8 +2445,9 @@ public class BytecodeParser implements GraphBuilderContext { } } - private void handleUnwindBlock() { + private void handleUnwindBlock(ExceptionDispatchBlock block) { if (parent == null) { + finishPrepare(lastInstr, block.deoptBci); frameState.setRethrowException(false); createUnwind(); } else { @@ -2476,8 +2479,8 @@ public class BytecodeParser implements GraphBuilderContext { private void createUnwind() { assert frameState.stackSize() == 1 : frameState; - ValueNode exception = frameState.pop(JavaKind.Object); synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); + ValueNode exception = frameState.pop(JavaKind.Object); append(new UnwindNode(exception)); } @@ -2488,6 +2491,7 @@ public class BytecodeParser implements GraphBuilderContext { } genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); assert !frameState.rethrowException(); + finishPrepare(lastInstr, bci); } if (frameState.lockDepth(false) != 0) { throw bailout("unbalanced monitors: too few exits exiting frame"); @@ -2715,7 +2719,7 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean traceState() { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE && Debug.isLogEnabled()) { frameState.traceState(); } return true; @@ -2727,12 +2731,6 @@ public class BytecodeParser implements GraphBuilderContext { BciBlock trueBlock = currentBlock.getSuccessor(0); BciBlock falseBlock = currentBlock.getSuccessor(1); - FrameState stateBefore = null; - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - } - if (trueBlock == falseBlock) { // The target block is the same independent of the condition. appendGoto(trueBlock); @@ -2753,8 +2751,21 @@ public class BytecodeParser implements GraphBuilderContext { // Check whether the condition needs to negate the result. boolean negate = cond.canonicalNegate(); + genIf(condition, negate, trueBlock, falseBlock); + } + + protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) { + BciBlock trueBlock = trueBlockInput; + BciBlock falseBlock = falseBlockInput; + LogicNode condition = conditionInput; + FrameState stateBefore = null; + ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); + if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { + stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); + } // Remove a logic negation node and fold it into the negate boolean. + boolean negate = negateCondition; if (condition instanceof LogicNegationNode) { LogicNegationNode logicNegationNode = (LogicNegationNode) condition; negate = !negate; @@ -2815,13 +2826,6 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); postProcessIfNode(ifNode); append(ifNode); - if (parsingIntrinsic()) { - if (x instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) x).simplify(null); - } else if (y instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) y).simplify(null); - } - } } } @@ -3039,6 +3043,19 @@ public class BytecodeParser implements GraphBuilderContext { frameState.push(kind, value); } + public void loadLocalObject(int index) { + ValueNode value = frameState.loadLocal(index, JavaKind.Object); + + int nextBCI = stream.nextBCI(); + int nextBC = stream.readUByte(nextBCI); + if (nextBC == Bytecodes.GETFIELD) { + stream.next(); + genGetField(lookupField(stream.readCPI(), Bytecodes.GETFIELD), value); + } else { + frameState.push(JavaKind.Object, value); + } + } + public void storeLocal(JavaKind kind, int index) { ValueNode value = frameState.pop(kind); frameState.storeLocal(index, kind, value); @@ -3320,7 +3337,7 @@ public class BytecodeParser implements GraphBuilderContext { } private JavaTypeProfile getProfileForTypeCheck(TypeReference type) { - if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || type.isExact()) { + if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) { return null; } else { return profilingInfo.getTypeProfile(bci()); @@ -3348,7 +3365,7 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode castNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null && checkedType.getType().isAssignableFrom(singleType)) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3361,31 +3378,20 @@ public class BytecodeParser implements GraphBuilderContext { } } } + + boolean nonNull = ((ObjectStamp) object.stamp()).nonNull(); if (castNode == null) { LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null)); if (condition.isTautology()) { castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.object(checkedType), fixedGuard)); + castNode = append(new PiNode(object, StampFactory.object(checkedType, nonNull), fixedGuard)); } } frameState.push(JavaKind.Object, castNode); } - private ValueNode appendNullCheck(ValueNode object) { - if (object.stamp() instanceof AbstractPointerStamp) { - AbstractPointerStamp stamp = (AbstractPointerStamp) object.stamp(); - if (stamp.nonNull()) { - return object; - } - } - - LogicNode isNull = append(IsNullNode.create(object)); - FixedGuardNode fixedGuard = append(new FixedGuardNode(isNull, DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)); - return append(new PiNode(object, object.stamp().join(StampFactory.objectNonNull()), fixedGuard)); - } - private void genInstanceOf() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, INSTANCEOF); @@ -3407,7 +3413,7 @@ public class BytecodeParser implements GraphBuilderContext { LogicNode instanceOfNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3421,7 +3427,23 @@ public class BytecodeParser implements GraphBuilderContext { if (instanceOfNode == null) { instanceOfNode = createInstanceOf(resolvedType, object, null); } - frameState.push(JavaKind.Int, append(genConditional(genUnique(instanceOfNode)))); + LogicNode logicNode = genUnique(instanceOfNode); + + int next = getStream().nextBCI(); + int value = getStream().readUByte(next); + if (value == Bytecodes.IFEQ || value == Bytecodes.IFNE) { + getStream().next(); + BciBlock firstSucc = currentBlock.getSuccessor(0); + BciBlock secondSucc = currentBlock.getSuccessor(1); + if (firstSucc != secondSucc) { + genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc); + } else { + appendGoto(firstSucc); + } + } else { + // Most frequent for value is IRETURN, followed by ISTORE. + frameState.push(JavaKind.Int, append(genConditional(logicNode))); + } } void genNewInstance(int cpi) { @@ -3562,15 +3584,21 @@ public class BytecodeParser implements GraphBuilderContext { } private void genGetField(JavaField field) { - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genGetField(field, frameState.pop(JavaKind.Object)); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + private void genGetField(JavaField field, ValueNode receiverInput) { + ValueNode receiver = emitExplicitExceptions(receiverInput); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + } else { handleUnresolvedLoadField(field, receiver); - return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + } - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3580,8 +3608,8 @@ public class BytecodeParser implements GraphBuilderContext { } } - frameState.push(field.getJavaKind(), append(genLoadField(receiver, resolvedField))); - if (resolvedField.getName().equals("referent") && resolvedField.getDeclaringClass().equals(metaAccess.lookupJavaType(Reference.class))) { + frameState.push(resolvedField.getJavaKind(), append(genLoadField(receiver, resolvedField))); + if (resolvedField.getDeclaringClass().getName().equals("Ljava/lang/ref/Reference;") && resolvedField.getName().equals("referent")) { LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField); append(new MembarNode(0, referentIdentity)); } @@ -3591,51 +3619,62 @@ public class BytecodeParser implements GraphBuilderContext { * @param receiver the receiver of an object based operation * @param index the index of an array based operation that is to be tested for out of bounds. * This is null for a non-array operation. - * @return the receiver value possibly modified to have a tighter stamp + * @return the receiver value possibly modified to have a non-null stamp */ protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { - assert receiver != null; - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { - return receiver; - } - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile && (profilingInfo == null || - (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue()))) { - return receiver; - } - - ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); - if (index != null) { + if (needsExplicitException()) { + ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); ValueNode length = append(genArrayLength(nonNullReceiver)); emitExplicitBoundsCheck(index, length); + return nonNullReceiver; } - EXPLICIT_EXCEPTIONS.increment(); - return nonNullReceiver; + return receiver; + } + + protected ValueNode emitExplicitExceptions(ValueNode receiver) { + if (StampTool.isPointerNonNull(receiver) || !needsExplicitException()) { + return receiver; + } else { + return emitExplicitNullCheck(receiver); + } + } + + private boolean needsExplicitException() { + BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode(); + if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) { + return true; + } else if (exceptionMode == BytecodeExceptionMode.Profile && profilingInfo != null) { + return profilingInfo.getExceptionSeen(bci()) == TriState.TRUE; + } + return false; } private void genPutField(JavaField field) { - ValueNode value = frameState.pop(field.getJavaKind()); - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genPutField(field, frameState.pop(field.getJavaKind())); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - handleUnresolvedStoreField(field, value, receiver); - return; - } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + private void genPutField(JavaField field, ValueNode value) { + ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object)); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { - graph.recordField(resolvedField); - } - - for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { - if (plugin.handleStoreField(this, receiver, resolvedField, value)) { - return; + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { + graph.recordField(resolvedField); } - } - if (resolvedField.isFinal() && method.isConstructor()) { - finalBarrierRequired = true; + for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { + if (plugin.handleStoreField(this, receiver, resolvedField, value)) { + return; + } + } + + if (resolvedField.isFinal() && method.isConstructor()) { + finalBarrierRequired = true; + } + genStoreField(receiver, resolvedField, value); + } else { + handleUnresolvedStoreField(field, value, receiver); } - genStoreField(receiver, resolvedField, value); } private void genGetStatic(JavaField field) { @@ -3645,7 +3684,7 @@ public class BytecodeParser implements GraphBuilderContext { } ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3681,7 +3720,7 @@ public class BytecodeParser implements GraphBuilderContext { } ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3741,12 +3780,10 @@ public class BytecodeParser implements GraphBuilderContext { int nofCases = bs.numberOfCases(); double[] keyProbabilities = switchProbability(nofCases + 1, bci); - Map bciToBlockSuccessorIndex = new HashMap<>(); + EconomicMap bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT); for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); - } + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); } ArrayList actualSuccessors = new ArrayList<>(); @@ -3782,7 +3819,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean isNeverExecutedCode(double probability) { - return probability == 0 && optimisticOpts.removeNeverExecutedCode(); + return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions()); } protected double branchProbability() { @@ -3797,7 +3834,7 @@ public class BytecodeParser implements GraphBuilderContext { probability = 0.5; } - if (!optimisticOpts.removeNeverExecutedCode()) { + if (!optimisticOpts.removeNeverExecutedCode(getOptions())) { if (probability == 0) { probability = 0.0000001; } else if (probability == 1) { @@ -3863,7 +3900,7 @@ public class BytecodeParser implements GraphBuilderContext { case LLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Long); break; case FLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Float); break; case DLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Double); break; - case ALOAD : loadLocal(stream.readLocalIndex(), JavaKind.Object); break; + case ALOAD : loadLocalObject(stream.readLocalIndex()); break; case ILOAD_0 : // fall through case ILOAD_1 : // fall through case ILOAD_2 : // fall through @@ -3883,7 +3920,7 @@ public class BytecodeParser implements GraphBuilderContext { case ALOAD_0 : // fall through case ALOAD_1 : // fall through case ALOAD_2 : // fall through - case ALOAD_3 : loadLocal(opcode - ALOAD_0, JavaKind.Object); break; + case ALOAD_3 : loadLocalObject(opcode - ALOAD_0); break; case IALOAD : genLoadIndexed(JavaKind.Int ); break; case LALOAD : genLoadIndexed(JavaKind.Long ); break; case FALOAD : genLoadIndexed(JavaKind.Float ); break; @@ -4047,7 +4084,7 @@ public class BytecodeParser implements GraphBuilderContext { } private void genArrayLength() { - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object)); frameState.push(JavaKind.Int, append(genArrayLength(array))); } @@ -4066,7 +4103,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { traceInstructionHelper(bci, opcode, blockStart); } return true; @@ -4107,11 +4144,4 @@ public class BytecodeParser implements GraphBuilderContext { static String nSpaces(int n) { return n == 0 ? "" : format("%" + n + "s", ""); } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java index 9328c7614b0..15677ce5c25 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java @@ -24,8 +24,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to {@link BytecodeParser}. @@ -36,30 +35,30 @@ import org.graalvm.compiler.options.StableOptionValue; public class BytecodeParserOptions { // @formatter:off @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) - public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); + public static final OptionKey TraceBytecodeParserLevel = new OptionKey<>(0); @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineDuringParsing = new OptionKey<>(true); @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineIntrinsicsDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineIntrinsicsDuringParsing = new OptionKey<>(true); @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + public static final OptionKey TraceInlineDuringParsing = new OptionKey<>(false); @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); + public static final OptionKey TraceParserPlugins = new OptionKey<>(false); @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); + public static final OptionKey InlineDuringParsingMaxDepth = new OptionKey<>(10); @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); + public static final OptionKey DumpDuringGraphBuilding = new OptionKey<>(false); @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) - public static final OptionValue HideSubstitutionStates = new OptionValue<>(false); + public static final OptionKey HideSubstitutionStates = new OptionKey<>(false); @Option(help = "Use intrinsics guarded by a virtual dispatch test at indirect call sites.", type = OptionType.Debug) - public static final OptionValue UseGuardedIntrinsics = new OptionValue<>(true); + public static final OptionKey UseGuardedIntrinsics = new OptionKey<>(true); // @formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java index c2cc0ae369f..94bcf84ea10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.java; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -36,6 +34,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; +import org.graalvm.util.EconomicMap; public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { @@ -54,7 +53,11 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N @Override protected Double merge(AbstractMergeNode merge, List states) { // a merge has the sum of all predecessor probabilities - return states.stream().collect(Collectors.summingDouble(d -> d)); + double result = 0.0; + for (double d : states) { + result += d; + } + return result; } @Override @@ -65,10 +68,13 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N } @Override - protected Map processLoop(LoopBeginNode loop, Double initialState) { - Map exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; + protected EconomicMap processLoop(LoopBeginNode loop, Double initialState) { + EconomicMap exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; - double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum(); + double exitProbability = 0.0; + for (double d : exitStates.getValues()) { + exitProbability += d; + } exitProbability = Math.min(1D, exitProbability); if (exitProbability < ControlFlowGraph.MIN_PROBABILITY) { exitProbability = ControlFlowGraph.MIN_PROBABILITY; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java index 8be604a4a87..452bb7820f3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -41,8 +42,8 @@ public class DefaultSuitesProvider extends SuitesProviderBase { } @Override - public Suites createSuites() { - return Suites.createSuites(compilerConfiguration); + public Suites createSuites(OptionValues options) { + return Suites.createSuites(compilerConfiguration, options); } protected PhaseSuite createGraphBuilderSuite(Plugins plugins) { @@ -52,7 +53,7 @@ public class DefaultSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - return Suites.createLIRSuites(compilerConfiguration); + public LIRSuites createLIRSuites(OptionValues options) { + return Suites.createLIRSuites(compilerConfiguration, options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index 092d213d903..73d58188093 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -42,7 +42,8 @@ import java.util.function.Function; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.Debug; @@ -99,6 +100,7 @@ public final class FrameStateBuilder implements SideEffectsState { private MonitorIdNode[] monitorIds; private final StructuredGraph graph; + private final boolean clearNonLiveLocals; private FrameState outerFrameState; /** @@ -142,6 +144,7 @@ public final class FrameStateBuilder implements SideEffectsState { this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; + this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()); this.canVerifyKind = true; } @@ -263,6 +266,7 @@ public final class FrameStateBuilder implements SideEffectsState { assert other.graph != null; graph = other.graph; + clearNonLiveLocals = other.clearNonLiveLocals; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); assert locals.length == code.getMaxLocals(); @@ -347,7 +351,7 @@ public final class FrameStateBuilder implements SideEffectsState { public NodeSourcePosition createBytecodePosition(int bci) { BytecodeParser parent = parser.getParent(); - if (HideSubstitutionStates.getValue()) { + if (HideSubstitutionStates.getValue(parser.graph.getOptions())) { if (parser.parsingIntrinsic()) { // Attribute to the method being replaced return new NodeSourcePosition(constantReceiver, parent.getFrameStateBuilder().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1); @@ -624,7 +628,7 @@ public final class FrameStateBuilder implements SideEffectsState { * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with * Kind.Illegal, because the conflicting branch might not have been parsed. */ - if (!parser.graphBuilderConfig.clearNonLiveLocals()) { + if (!clearNonLiveLocals) { return; } if (liveIn) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java index 8baadb649e9..47e4b9333ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.java; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; public class JsrNotSupportedBailout extends PermanentBailoutException { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java index 025fe1f16c4..2244df3c80b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java @@ -23,8 +23,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; -import org.graalvm.compiler.options.DerivedOptionValue; -import org.graalvm.compiler.options.DerivedOptionValue.OptionSupplier; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; @@ -32,44 +31,11 @@ import org.graalvm.compiler.phases.tiers.SuitesCreator; public abstract class SuitesProviderBase implements SuitesCreator { - protected final DerivedOptionValue defaultSuites; protected PhaseSuite defaultGraphBuilderSuite; - protected final DerivedOptionValue defaultLIRSuites; - - private class SuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 2677805381215454728L; - - @Override - public Suites get() { - Suites suites = createSuites(); - suites.setImmutable(); - return suites; - } - - } - - private class LIRSuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 312070237227476252L; - - @Override - public LIRSuites get() { - LIRSuites lirSuites = createLIRSuites(); - lirSuites.setImmutable(); - return lirSuites; - } - - } - - public SuitesProviderBase() { - this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); - this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); - } @Override - public final Suites getDefaultSuites() { - return defaultSuites.getValue(); + public final Suites getDefaultSuites(OptionValues options) { + return createSuites(options); } @Override @@ -78,13 +44,13 @@ public abstract class SuitesProviderBase implements SuitesCreator { } @Override - public final LIRSuites getDefaultLIRSuites() { - return defaultLIRSuites.getValue(); + public final LIRSuites getDefaultLIRSuites(OptionValues options) { + return createLIRSuites(options); } @Override - public abstract LIRSuites createLIRSuites(); + public abstract LIRSuites createLIRSuites(OptionValues options); @Override - public abstract Suites createSuites(); + public abstract Suites createSuites(OptionValues options); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java index d240feec5ca..36807d30474 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java @@ -23,24 +23,23 @@ package org.graalvm.compiler.jtt; import static java.lang.reflect.Modifier.isStatic; - import java.util.Collections; import java.util.Set; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Base class for the JTT tests. @@ -65,8 +64,8 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); @@ -82,8 +81,8 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return super.getCode(method, graph, argsToBind != null); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, argsToBind != null, installAsDefault, options); } Double delta; @@ -104,14 +103,18 @@ public class JTTTest extends GraalCompilerTest { } protected void runTest(String name, Object... args) { - runTest(EMPTY, name, args); + runTest(getInitialOptions(), name, args); + } + + protected void runTest(OptionValues options, String name, Object... args) { + runTest(options, EMPTY, true, false, name, args); } protected void runTest(Set shouldNotDeopt, String name, Object... args) { - runTest(shouldNotDeopt, true, false, name, args); + runTest(getInitialOptions(), shouldNotDeopt, true, false, name, args); } - protected void runTest(Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { + protected void runTest(OptionValues options, Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; @@ -121,14 +124,14 @@ public class JTTTest extends GraalCompilerTest { method.reprofile(); } - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); if (args.length > 0 && bind) { if (noProfile) { method.reprofile(); } this.argsToBind = args; - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); this.argsToBind = null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java index f358e1008e3..d6fdc91ada2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java @@ -24,15 +24,13 @@ package org.graalvm.compiler.jtt.backend; import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; - +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; import java.lang.reflect.Method; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; public class ConstantPhiTest extends JTTTest { @@ -59,24 +57,18 @@ public class ConstantPhiTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 0, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 0, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run1() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", -1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", -1, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run2() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 1, 0xDEADDEAD); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java index a48e6cd4763..a856a9d518c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,54 +22,82 @@ */ package org.graalvm.compiler.jtt.backend; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; -import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.IFNE; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; -import static jdk.internal.org.objectweb.asm.Opcodes.LADD; -import static jdk.internal.org.objectweb.asm.Opcodes.LCMP; -import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; -import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; -import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.ACC_FINAL; +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ACC_SUPER; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.LRETURN; -import org.junit.BeforeClass; -import org.junit.Test; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.test.ExportingClassLoader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import junit.framework.AssertionFailedError; +/** + * This test let the compiler deal with a large amount of constant data in a method. This data is + * stored typically in the constant section of the native method. Especially on the SPARC platform + * the backend can address only 8k of memory with an immediate offset. Beyond this barrier, a + * different addressing mode must be used. + * + * In order to do this this test generates a large method containing a large switch statement in + * form of + * + * + * static long run(long a) { + * switch(a) { + * case 1: + * return 0xF0F0F0F0F0L + 1; + * case 2: + * return 0xF0F0F0F0F0L + 2; + * .... + * default: + * return 0; + * } + * + * } + * + * + */ +@RunWith(Parameterized.class) public class LargeConstantSectionTest extends JTTTest { private static final String NAME = "LargeConstantSection"; private static final long LARGE_CONSTANT = 0xF0F0F0F0F0L; private static LargeConstantClassLoader LOADER; + @Parameter(value = 0) public int numberBlocks; - @BeforeClass - public static void before() { + @Parameters(name = "{0}") + public static Collection data() { + List parameters = new ArrayList<>(); + for (int i = 4; i < 13; i += 2) { + parameters.add(new Object[]{1 << i}); + } + return parameters; + } + + @Before + public void before() { LOADER = new LargeConstantClassLoader(LargeConstantSectionTest.class.getClassLoader()); } - public abstract static class LargeConstantAbstract { - public abstract long run(long i); - } - - public static long test(LargeConstantAbstract a, long i) throws Exception { - return a.run(GraalDirectives.opaque(i)); - } - - public static class LargeConstantClassLoader extends ExportingClassLoader { + public class LargeConstantClassLoader extends ExportingClassLoader { public LargeConstantClassLoader(ClassLoader parent) { super(parent); } @@ -77,54 +105,38 @@ public class LargeConstantSectionTest extends JTTTest { @Override protected Class findClass(String name) throws ClassNotFoundException { if (name.equals(NAME)) { - String graalDirectivesClassName = GraalDirectives.class.getName().replace('.', '/'); - int numberIfBlocks = 1100; // Each if block contains three constants ClassWriter cw = new ClassWriter(0); MethodVisitor mv; - String abstractClassName = Type.getInternalName(LargeConstantAbstract.class); - cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, abstractClassName, null); + cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, "java/lang/Object", null); - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "run", "(I)J", null, null); mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, abstractClassName, "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC, "run", "(J)J", null, null); - mv.visitCode(); - Label nextIf = new Label(); - for (int i = 0; i < numberIfBlocks; i++) { - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitVarInsn(LLOAD, 1); + Label begin = new Label(); + mv.visitLabel(begin); + mv.visitVarInsn(ILOAD, 0); + Label[] labels = new Label[numberBlocks]; + int[] keys = new int[numberBlocks]; + for (int i = 0; i < labels.length; i++) { + labels[i] = new Label(); + keys[i] = i; + } + Label defaultLabel = new Label(); + mv.visitLookupSwitchInsn(defaultLabel, keys, labels); + for (int i = 0; i < labels.length; i++) { + mv.visitLabel(labels[i]); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); mv.visitLdcInsn(new Long(LARGE_CONSTANT + i)); - mv.visitInsn(LCMP); - nextIf = new Label(); - mv.visitJumpInsn(IFNE, nextIf); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks * 2)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitInsn(LADD); mv.visitInsn(LRETURN); } - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitInsn(LCONST_0); + mv.visitLabel(defaultLabel); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); + mv.visitLdcInsn(new Long(3L)); mv.visitInsn(LRETURN); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(4, 6); + Label end = new Label(); + mv.visitLabel(end); + mv.visitLocalVariable("a", "I", null, begin, end, 0); + mv.visitMaxs(2, 1); mv.visitEnd(); - - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); return defineClass(name, bytes, 0, bytes.length); } else { @@ -136,8 +148,20 @@ public class LargeConstantSectionTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() throws Exception { - try (OverrideScope os = OptionValue.override(GraalOptions.InlineEverything, true)) { - runTest("test", LOADER.findClass(NAME).newInstance(), 0L); + test("run", numberBlocks - 3); + } + + @Override + protected ResolvedJavaMethod getResolvedJavaMethod(String methodName) { + try { + for (Method method : LOADER.findClass(NAME).getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return asResolvedJavaMethod(method); + } + } + } catch (ClassNotFoundException e) { + throw new AssertionFailedError("Cannot find class " + NAME); } + throw GraalError.shouldNotReachHere(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java index 4545fdbc1b1..a2570035d21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java @@ -76,4 +76,20 @@ public class BC_instanceof extends JTTTest { runTest("test", 4); } + // Checkstyle: stop + // Need to stop checkstyle due to empty if constructs. + public static boolean testEmpty(Object obj) { + if (obj instanceof TestClass) { + } + + if (!(obj instanceof TestClass)) { + } + return true; + } + // Checkstyle: resume + + @Test + public void run5() throws Throwable { + runTest("testEmpty", object2); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java index 791ee24aed6..599dce74853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java @@ -26,8 +26,7 @@ import org.junit.Test; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; /** @@ -89,10 +88,8 @@ public class BC_instanceof01 extends JTTTest { @Override @SuppressWarnings("try") - protected Suites getSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.getSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java index 1753afa108a..783aa17506e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java @@ -47,7 +47,7 @@ public class BC_getfield1 extends JTTTest { @Test public void run1() throws Throwable { // tests that the null check isn't removed along with the read - runTest(EMPTY, true, true, "test", (Object) null); + runTest(getInitialOptions(), EMPTY, true, true, "test", (Object) null); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java index ac939571007..b140a67742e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java @@ -22,16 +22,14 @@ */ package org.graalvm.compiler.jtt.except; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; public class UntrustedInterfaces extends JTTTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java index df296683e2c..6a64c0ea57f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java @@ -24,15 +24,18 @@ package org.graalvm.compiler.jtt.hotspot; import java.util.ArrayList; -import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.core.common.util.ArraySet; import org.graalvm.compiler.jtt.JTTTest; // @formatter:off public class Test6186134 extends JTTTest { + @SuppressWarnings("serial") + public static final class MyArrayList extends ArrayList { + + } + public static class TestClass { int num = 0; @@ -45,8 +48,8 @@ public class Test6186134 extends JTTTest { return num-- > 0; } - public ArrayList test1() { - ArrayList res = new ArrayList<>(); + public MyArrayList test1() { + MyArrayList res = new MyArrayList<>(); int maxResults = Integer.MAX_VALUE; int n = 0; boolean more = more(); @@ -70,12 +73,6 @@ public class Test6186134 extends JTTTest { return 0; } - @Before - public void setUp() { - /* Ensure that ArrayList is _not_ a leaf class (otherwise code installation may fail due to a failed leaf type dependency). */ - UNSAFE.ensureClassInitialized(ArraySet.class); - } - @Test public void run0() throws Throwable { runTest("test", 100); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java index 2467c7753d7..304c6752f7d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.jtt.hotspot; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Test6959129 extends JTTTest { @@ -76,6 +75,7 @@ public class Test6959129 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java index 815110febe0..73906cd73b2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java @@ -24,30 +24,25 @@ package org.graalvm.compiler.jtt.jdk; import java.lang.reflect.Field; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /* */ public class UnsafeAccess01 extends JTTTest { private static int randomValue = 100; - private static final Unsafe unsafe; private static final long offset; private static Object staticObject = new TestClass(); static { - unsafe = getUnsafe(); Field field = null; try { field = TestClass.class.getDeclaredField("field"); } catch (NoSuchFieldException e) { } catch (SecurityException e) { } - offset = unsafe.objectFieldOffset(field); + offset = UNSAFE.objectFieldOffset(field); } private static class TestClass { @@ -56,20 +51,10 @@ public class UnsafeAccess01 extends JTTTest { public static int test() { final TestClass object = new TestClass(); - final int value = unsafe.getInt(object, offset); + final int value = UNSAFE.getInt(object, offset); return value; } - static Unsafe getUnsafe() { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - return (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } - @Test public void run0() throws Throwable { runTest("test"); @@ -86,11 +71,11 @@ public class UnsafeAccess01 extends JTTTest { final int oldValue = ((TestClass) object).field; if (randomValue == 100) { - unsafe.putInt(object, offset, 41); + UNSAFE.putInt(object, offset, 41); } else { - unsafe.putInt(object, offset, 40); + UNSAFE.putInt(object, offset, 40); } - unsafe.putInt(object, offset, 42); + UNSAFE.putInt(object, offset, 42); return oldValue; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java index 98f0f27cef7..2f1df0cc53e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java @@ -22,21 +22,17 @@ */ package org.graalvm.compiler.jtt.jdk; -import jdk.vm.ci.meta.ResolvedJavaMethod; - +import org.graalvm.compiler.jtt.JTTTest; import org.junit.Test; -import sun.misc.Unsafe; - -import org.graalvm.compiler.jtt.JTTTest; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class Unsafe_compareAndSwap extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -44,9 +40,9 @@ public class Unsafe_compareAndSwap extends JTTTest { public static String test(Unsafe_compareAndSwap u, Object o, String expected, String newValue) { // First arg is not an array - can use a field write barrier - unsafe.compareAndSwapObject(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(u, valueOffset, expected, newValue); // Not known if first arg is an array - different write barrier may be used - unsafe.compareAndSwapObject(o, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(o, valueOffset, expected, newValue); return instance.value; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index 5d109a8dda3..a69bf2d8059 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -22,19 +22,16 @@ */ package org.graalvm.compiler.jtt.jdk; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Assume; +import org.junit.Test; public class Unsafe_compareAndSwapNullCheck extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -46,11 +43,13 @@ public class Unsafe_compareAndSwapNullCheck extends JTTTest { public static void test(Unsafe_compareAndSwapNullCheck u, long expected, long newValue) { @SuppressWarnings("unused") long l = u.lng; - unsafe.compareAndSwapLong(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapLong(u, valueOffset, expected, newValue); } @Test public void run0() throws Throwable { - runTest(EMPTY, false, true, "test", null, 1L, 2L); + // GR-2921: Unsafe_compareAndSwapNullCheck test crashes on jdk9 + Assume.assumeTrue(Java8OrEarlier); + runTest(getInitialOptions(), EMPTY, false, true, "test", null, 1L, 2L); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java index cefbae2f970..b7ae49954f6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java @@ -22,21 +22,20 @@ */ package org.graalvm.compiler.jtt.lang; +import static org.graalvm.compiler.core.common.GraalOptions.InlineEverything; + import java.util.EnumSet; import java.util.function.IntBinaryOperator; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Test; + import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.Test; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - public class LambdaEagerTest extends GraalCompilerTest { private static final EnumSet UNRESOLVED_UNREACHED = EnumSet.of(DeoptimizationReason.Unresolved, DeoptimizationReason.UnreachedCode); @@ -81,9 +80,8 @@ public class LambdaEagerTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { - try (OverrideScope scope = OptionValue.override(GraalOptions.InlineEverything, true)) { - return super.getCode(installedCodeOwner, graph, forceCompile); - } + protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + assert graph == null; + return super.getCode(installedCodeOwner, graph, forceCompile, installAsDefault, new OptionValues(options, InlineEverything, true)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java new file mode 100644 index 00000000000..68dacfc81d3 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.junit.Assert; +import org.junit.Test; + +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.options.OptionValues; + +public class GuardMovement extends JTTTest { + + private static int staticValue; + + private static class A { + int x; + int y; + } + + public int foo(A a) { + Assert.assertNotEquals("a cannot be null, because a field of a is accessed before the call", a, null); + return 42; + } + + @SuppressWarnings("all") + public int test(A a) { + + int value; + int result = 0; + + // Use a condition that folds after floating guards and before guard lowering. + // After disabling PEA and read elimination, the following condition does the trick. + if (staticValue == staticValue) { + // Access a.x to generate a null checked value. + value = a.x; + result = foo(a); + } + + // Access a.y to generate another null checked value. + return result + a.y; + } + + @Test + public void run0() throws Throwable { + OptionValues options = new OptionValues(getInitialOptions(), MaximumInliningSize, -1, GraalOptions.TrivialInliningSize, -1, GraalOptions.PartialEscapeAnalysis, false, + GraalOptions.OptReadElimination, false); + runTest(options, "test", new A()); + runTest(options, "test", new Object[]{null}); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java index b479d7ec5c6..2fa90ad28af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,13 +39,13 @@ import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class NestedLoop_EA extends JTTTest { @Override - protected Suites createSuites() { - Suites suites = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); ListIterator> position = suites.getHighTier().findPhase(PartialEscapePhase.class); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); // incremental canonicalizer of PEA is missing some important canonicalization (TODO?) position.add(canonicalizer); - position.add(new PartialEscapePhase(true, canonicalizer)); + position.add(new PartialEscapePhase(true, canonicalizer, options)); return suites; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java index 929bb24b4c7..6275a2009d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java @@ -22,44 +22,30 @@ */ package org.graalvm.compiler.jtt.optimize; -import java.lang.reflect.Field; import java.nio.ByteBuffer; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; public class UnsafeDeopt extends JTTTest { - private static final Unsafe unsafe; - - static { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } public static int readWriteReadUnsafe(long addr, int m) { - int original = unsafe.getInt(addr); + int original = UNSAFE.getInt(addr); if (original != 0) { return -m; } - unsafe.putInt(addr, m); + UNSAFE.putInt(addr, m); if (m > 10) { if (m > 20) { GraalDirectives.deoptimize(); } - unsafe.putInt(addr + 4, m); + UNSAFE.putInt(addr + 4, m); } - return unsafe.getInt(addr); + return UNSAFE.getInt(addr); } public static int readWriteReadByteBuffer(ByteBuffer buffer, int m) { @@ -78,13 +64,13 @@ public class UnsafeDeopt extends JTTTest { } public long createBuffer() { - long addr = unsafe.allocateMemory(32); - unsafe.setMemory(addr, 32, (byte) 0); + long addr = UNSAFE.allocateMemory(32); + UNSAFE.setMemory(addr, 32, (byte) 0); return addr; } public void disposeBuffer(long addr) { - unsafe.freeMemory(addr); + UNSAFE.freeMemory(addr); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java index 4862d4c4c9f..e7ec7263a4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2017, 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 @@ -20,25 +20,31 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.handler; +package org.graalvm.compiler.jtt.optimize; -import java.io.IOException; +import org.junit.Test; -import org.graalvm.compiler.graph.Graph; -import org.graalvm.compiler.salver.dumper.GraphDumper; +import org.graalvm.compiler.jtt.JTTTest; -public class GraphDumpHandler extends AbstractGraalDumpHandler { +/* + * Tests optimization of float operations. + */ +public class VN_Double03 extends JTTTest { - @Override - protected GraphDumper createDumper() { - return new GraphDumper(); + public static double test(double arg) { + if (arg == -0.0d) { + return arg; + } + return 0; } - @Override - public void handle(Object obj, String msg) throws IOException { - if (obj instanceof Graph) { - ensureInitialized(); - dumper.dump((Graph) obj, msg); - } + @Test + public void run0() throws Throwable { + runTest("test", -0.0d); + } + + @Test + public void run1() throws Throwable { + runTest("test", 0.0d); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java index d42b57e7fe8..1065d5ca40c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public final class Monitor_contended01 extends JTTTest { @@ -77,6 +76,7 @@ public final class Monitor_contended01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java index 8c8978000a8..68ccc3e5823 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Monitor_notowner01 extends JTTTest { @@ -66,6 +65,7 @@ public class Monitor_notowner01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java index af35abebd89..b6b9ce0034a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public final class Monitorenter01 extends JTTTest { @@ -43,6 +42,7 @@ public final class Monitorenter01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java index f688227fc39..55a99386d00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public final class Monitorenter02 extends JTTTest { @@ -47,6 +46,7 @@ public final class Monitorenter02 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java index dc6eae1e25c..0354db97de6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Object_wait01 extends JTTTest { @@ -62,21 +61,25 @@ public class Object_wait01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } @Test(timeout = 20000) public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 3); } @Test(timeout = 20000) public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 15); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java index ccd61b3456b..aab1151976d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Object_wait02 extends JTTTest { @@ -63,16 +62,19 @@ public class Object_wait02 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } @Test(timeout = 20000) public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java index d8376621d5d..1e9ee964a89 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Object_wait03 extends JTTTest { @@ -69,16 +68,19 @@ public class Object_wait03 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } @Test(timeout = 20000) public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java index 925dada3ef5..31ab57d78c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Object_wait04 extends JTTTest { @@ -73,31 +72,37 @@ public class Object_wait04 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } @Test(timeout = 20000) public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } @Test(timeout = 20000) public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 3); } @Test(timeout = 20000) public void run4() throws Throwable { + initializeForTimeout(); runTest("test", 4); } @Test(timeout = 20000) public void run5() throws Throwable { + initializeForTimeout(); runTest("test", 5); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java index fdb58db5814..e8d717957d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /** * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}. @@ -55,6 +54,7 @@ public final class SynchronizedLoopExit01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java index 41edeed4e92..10a61460f81 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java @@ -26,11 +26,10 @@ package org.graalvm.compiler.jtt.threads; +import org.graalvm.compiler.jtt.JTTTest; import org.junit.Assert; import org.junit.Test; -import org.graalvm.compiler.jtt.JTTTest; - //Test all, mainly monitors public class Thread_isInterrupted02 extends JTTTest { @@ -105,11 +104,13 @@ public class Thread_isInterrupted02 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0, 0); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1, 500); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java index 6e2b3c291b4..5d1640980e2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /* */ @@ -71,6 +70,7 @@ public class Thread_isInterrupted03 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java index 9e70ded4d6b..218e722b045 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /* */ @@ -69,6 +68,7 @@ public class Thread_isInterrupted05 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java index 1937618b869..274251beb1b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Thread_join01 extends JTTTest { @@ -49,6 +48,7 @@ public class Thread_join01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java index 824ecf75b10..b950d8c2f1d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java @@ -27,9 +27,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Thread_join02 extends JTTTest { @@ -56,6 +55,7 @@ public class Thread_join02 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java index 1e815b64c7d..685ae60f3b7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java @@ -27,9 +27,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public class Thread_join03 extends JTTTest { @@ -53,6 +52,7 @@ public class Thread_join03 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java index e2245488715..d234c48c631 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public final class Thread_sleep01 extends JTTTest { @@ -38,16 +37,19 @@ public final class Thread_sleep01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 10); } @Test(timeout = 20000) public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 20); } @Test(timeout = 20000) public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 100); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java index 0c6380150a8..1460466639c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java @@ -24,9 +24,8 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; public final class Thread_yield01 extends JTTTest { @@ -37,6 +36,7 @@ public final class Thread_yield01 extends JTTTest { @Test(timeout = 20000) public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java index caf734f88e6..cbe7676a382 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java @@ -51,6 +51,7 @@ public enum AArch64ArithmeticOp { SUB(ARITHMETIC), SUBS(ARITHMETIC), MUL, + MULVS, DIV, SMULH, UMULH, @@ -176,6 +177,14 @@ public enum AArch64ArithmeticOp { assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); masm.sub(size, dst, src, (int) b.asLong()); break; + case ADDS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.adds(size, dst, src, (int) b.asLong()); + break; + case SUBS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.subs(size, dst, src, (int) b.asLong()); + break; case AND: // XXX Should this be handled somewhere else? if (size == 32 && b.asLong() == 0xFFFF_FFFFL) { @@ -291,6 +300,9 @@ public enum AArch64ArithmeticOp { case FDIV: masm.fdiv(size, dst, src1, src2); break; + case MULVS: + masm.mulvs(size, dst, src1, src2); + break; default: throw GraalError.shouldNotReachHere("op=" + op.name()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java new file mode 100644 index 00000000000..31476aff584 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static jdk.vm.ci.aarch64.AArch64.zr; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.Value; +import sun.misc.Unsafe; + +/** + * Emits code which compares two arrays of the same length. If the CPU supports any vector + * instructions specialized code is emitted to leverage these instructions. + */ +@Opcode("ARRAY_EQUALS") +public final class AArch64ArrayEqualsOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ArrayEqualsOp.class); + + private final JavaKind kind; + private final int arrayBaseOffset; + private final int arrayIndexScale; + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value array1Value; + @Alive({REG}) protected Value array2Value; + @Alive({REG}) protected Value lengthValue; + @Temp({REG}) protected Value temp1; + @Temp({REG}) protected Value temp2; + @Temp({REG}) protected Value temp3; + @Temp({REG}) protected Value temp4; + + public AArch64ArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + super(TYPE); + this.kind = kind; + + Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); + this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); + this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + + this.resultValue = result; + this.array1Value = array1; + this.array2Value = array2; + this.lengthValue = length; + + // Allocate some temporaries. + this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp3 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + this.temp4 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register result = asRegister(resultValue); + Register array1 = asRegister(temp1); + Register array2 = asRegister(temp2); + Register length = asRegister(temp3); + + Label breakLabel = new Label(); + + try (ScratchRegister sc1 = masm.getScratchRegister()) { + Register rscratch1 = sc1.getRegister(); + // Load array base addresses. + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(asRegister(array1Value), arrayBaseOffset)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(asRegister(array2Value), arrayBaseOffset)); + + // Get array length in bytes. + masm.mov(rscratch1, arrayIndexScale); + masm.smaddl(length, asRegister(lengthValue), rscratch1, zr); + masm.mov(64, result, length); // copy + + emit8ByteCompare(crb, masm, result, array1, array2, length, breakLabel, rscratch1); + emitTailCompares(masm, result, array1, array2, breakLabel, rscratch1); + + // Return: rscratch1 is non-zero iff the arrays differ + masm.bind(breakLabel); + masm.cmp(64, rscratch1, zr); + masm.cset(result, ConditionFlag.EQ); + } + } + + /** + * Vector size used in {@link #emit8ByteCompare}. + */ + private static final int VECTOR_SIZE = 8; + + /** + * Emits code that uses 8-byte vector compares. + * + */ + private void emit8ByteCompare(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, Register array1, Register array2, Register length, Label breakLabel, + Register rscratch1) { + Label loop = new Label(); + Label compareTail = new Label(); + + Register temp = asRegister(temp4); + + masm.and(64, result, result, VECTOR_SIZE - 1); // tail count (in bytes) + masm.ands(64, length, length, ~(VECTOR_SIZE - 1)); // vector count (in bytes) + masm.branchConditionally(ConditionFlag.EQ, compareTail); + + masm.lea(array1, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.lea(array2, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.sub(64, length, zr, length); + + // Align the main loop + masm.align(crb.target.wordSize * 2); + masm.bind(loop); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.cbnz(64, rscratch1, breakLabel); + masm.add(64, length, length, VECTOR_SIZE); + masm.cbnz(64, length, loop); + + masm.cbz(64, result, breakLabel); + + /* + * Compare the remaining bytes with an unaligned memory load aligned to the end of the + * array. + */ + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(array1, -VECTOR_SIZE)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(array2, -VECTOR_SIZE)); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, result, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, result, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.jmp(breakLabel); + + masm.bind(compareTail); + } + + /** + * Emits code to compare the remaining 1 to 4 bytes. + * + */ + private void emitTailCompares(AArch64MacroAssembler masm, Register result, Register array1, Register array2, Label breakLabel, Register rscratch1) { + Label compare2Bytes = new Label(); + Label compare1Byte = new Label(); + Label end = new Label(); + + Register temp = asRegister(temp4); + + if (kind.getByteCount() <= 4) { + // Compare trailing 4 bytes, if any. + masm.ands(32, zr, result, 4); + masm.branchConditionally(ConditionFlag.EQ, compare2Bytes); + masm.ldr(32, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 4)); + masm.ldr(32, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 4)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + if (kind.getByteCount() <= 2) { + // Compare trailing 2 bytes, if any. + masm.bind(compare2Bytes); + masm.ands(32, zr, result, 2); + masm.branchConditionally(ConditionFlag.EQ, compare1Byte); + masm.ldr(16, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 2)); + masm.ldr(16, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + // The one-byte tail compare is only required for boolean and byte arrays. + if (kind.getByteCount() <= 1) { + // Compare trailing byte, if any. + masm.bind(compare1Byte); + masm.ands(32, zr, result, 1); + masm.branchConditionally(ConditionFlag.EQ, end); + masm.ldr(8, temp, AArch64Address.createBaseRegisterOnlyAddress(array1)); + masm.ldr(8, rscratch1, AArch64Address.createBaseRegisterOnlyAddress(array2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + } else { + masm.bind(compare1Byte); + } + } else { + masm.bind(compare2Bytes); + } + } + masm.bind(end); + masm.mov(64, rscratch1, zr); + } + + private static final Unsafe UNSAFE = initUnsafe(); + + private static Unsafe initUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException se) { + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe", e); + } + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java index 31b6f4e6edf..45bd9330473 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.AllocatableValue; */ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public enum BitManipulationOpCode { - BSF, + CTZ, BSR, BSWP, CLZ, @@ -62,7 +62,7 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); Register src = asRegister(input); - final int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; + final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE; switch (opcode) { case CLZ: masm.clz(size, dst, src); @@ -73,9 +73,9 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { masm.neg(size, dst, dst); masm.add(size, dst, dst, size - 1); break; - case BSF: - // BSF == CLZ(rev(input)) - masm.rev(size, dst, src); + case CTZ: + // CTZ == CLZ(rbit(input)) + masm.rbit(size, dst, src); masm.clz(size, dst, dst); break; case BSWP: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java index 115e57882b8..5147d96cfcf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java @@ -24,11 +24,12 @@ package org.graalvm.compiler.lir.aarch64; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AArch64BlockEndOp extends AbstractBlockEndOp { +public abstract class AArch64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java new file mode 100644 index 00000000000..0eae02eae13 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +@Opcode("BSWAP") +public final class AArch64ByteSwapOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ByteSwapOp.class); + + @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; + @Use protected Value input; + + public AArch64ByteSwapOp(Value result, Value input) { + super(TYPE); + this.result = result; + this.input = input; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + switch ((AArch64Kind) input.getPlatformKind()) { + case DWORD: + masm.rev(32, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + case QWORD: + masm.rev(64, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java new file mode 100644 index 00000000000..b2fef6e1084 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +public final class AArch64CCall extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64CCall.class); + + @Def({REG, ILLEGAL}) protected Value result; + @Use({REG, STACK}) protected Value[] parameters; + @Use({REG}) protected Value functionPtr; + + public AArch64CCall(Value result, Value functionPtr, Value[] parameters) { + super(TYPE); + this.result = result; + this.functionPtr = functionPtr; + this.parameters = parameters; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + directCall(masm); + } + + private void directCall(AArch64MacroAssembler masm) { + Register reg = ValueUtil.asRegister(functionPtr); + masm.blr(reg); + masm.ensureUniquePC(); + } + + @Override + public boolean destroysCallerSavedRegisters() { + return true; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java index 60a6fc90eba..18c96278670 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java @@ -29,7 +29,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.calc.Condition; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java index 9604854e9e9..d06f4ccfa00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java @@ -24,16 +24,17 @@ package org.graalvm.compiler.lir.aarch64; import static jdk.vm.ci.code.ValueUtil.asAllocatableValue; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.PatchLabelKind; import org.graalvm.compiler.code.CompilationResult.JumpTable; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; @@ -234,61 +235,51 @@ public class AArch64ControlFlow { } } - public static class TableSwitchOp extends AArch64BlockEndOp implements StandardOp.BlockEndOp { + public static final class TableSwitchOp extends AArch64BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TableSwitchOp.class); - private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; - @Alive protected Variable keyValue; - @Temp protected Variable scratchValue; + @Use protected Value index; + @Temp({REG, HINT}) protected Value idxScratch; + @Temp protected Value scratch; - public TableSwitchOp(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Variable key, Variable scratch) { + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch) { super(TYPE); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; - this.keyValue = key; - this.scratchValue = scratch; + this.index = index; + this.scratch = scratch; + this.idxScratch = idxScratch; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - Register key = asRegister(keyValue); - Register scratch = asRegister(scratchValue); - if (lowKey != 0) { - if (AArch64MacroAssembler.isArithmeticImmediate(lowKey)) { - masm.sub(32, key, key, lowKey); - } else { - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(lowKey)); - AArch64Move.move(crb, masm, scratchValue, constVal); - masm.sub(32, key, key, scratch); - } - } + Register indexReg = asRegister(index, AArch64Kind.DWORD); + Register idxScratchReg = asRegister(idxScratch, AArch64Kind.DWORD); + Register scratchReg = asRegister(scratch, AArch64Kind.QWORD); + + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + masm.sub(32, idxScratchReg, indexReg, lowKey); + masm.cmp(32, idxScratchReg, highKey - lowKey); + + // Jump to default target if index is not within the jump table if (defaultTarget != null) { - // if key is not in table range, jump to default target if it exists. - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(targets.length)); - emitCompare(crb, masm, keyValue, scratchValue, constVal); - masm.branchConditionally(AArch64Assembler.ConditionFlag.HS, defaultTarget.label()); + masm.branchConditionally(ConditionFlag.HI, defaultTarget.label()); } - // Load the start address of the jump table - which starts 3 instructions after the adr - // - into scratch. - masm.adr(scratch, 4 * 3); - masm.ldr(32, scratch, AArch64Address.createRegisterOffsetAddress(scratch, key, /* scaled */true)); - masm.jmp(scratch); - int jumpTablePos = masm.position(); + Label jumpTable = new Label(); + masm.adr(scratchReg, jumpTable); + masm.add(64, scratchReg, scratchReg, idxScratchReg, ExtendType.UXTW, 2); + masm.jmp(scratchReg); + masm.bind(jumpTable); // emit jump table entries for (LabelRef target : targets) { - Label label = target.label(); - if (label.isBound()) { - masm.emitInt(target.label().position()); - } else { - label.addPatchAt(masm.position()); - masm.emitInt(PatchLabelKind.JUMP_ADDRESS.encoding); - } + masm.jmp(target.label()); } - JumpTable jt = new JumpTable(jumpTablePos, lowKey, lowKey + targets.length - 1, 4); + JumpTable jt = new JumpTable(jumpTable.position(), lowKey, highKey - 1, 4); crb.compilationResult.addAnnotation(jt); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index 0fb4e831102..f8d12722d33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -110,6 +110,7 @@ public class AArch64Move { super(TYPE); this.result = result; this.input = input; + assert !(isStackSlot(result) && isStackSlot(input)); } @Override @@ -182,9 +183,11 @@ public class AArch64Move { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - AArch64Address address = (AArch64Address) crb.asAddress(slot); - PlatformKind kind = AArch64Kind.QWORD; - masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + AArch64Address address = loadStackSlotAddress(crb, masm, (StackSlot) slot, addrReg.getRegister()); + PlatformKind kind = AArch64Kind.QWORD; + masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + } } } @@ -265,8 +268,7 @@ public class AArch64Move { int destSize = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; int srcSize = kind.getSizeInBytes() * Byte.SIZE; if (kind.isInteger()) { - // TODO How to load unsigned chars without the necessary information? - masm.ldrs(destSize, srcSize, dst, address); + masm.ldr(srcSize, dst, address); } else { assert srcSize == destSize; masm.fldr(srcSize, dst, address); @@ -412,6 +414,8 @@ public class AArch64Move { } else if (isStackSlot(input)) { if (isRegister(result)) { stack2reg(crb, masm, result, asAllocatableValue(input)); + } else if (isStackSlot(result)) { + emitStackMove(crb, masm, result, input); } else { throw GraalError.shouldNotReachHere(); } @@ -426,6 +430,24 @@ public class AArch64Move { } } + private static void emitStackMove(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { + try (ScratchRegister r1 = masm.getScratchRegister()) { + try (ScratchRegister r2 = masm.getScratchRegister()) { + Register rscratch1 = r1.getRegister(); + Register rscratch2 = r2.getRegister(); + PlatformKind kind = input.getPlatformKind(); + final int size = kind.getSizeInBytes() <= 4 ? 32 : 64; + + // Always perform stack -> stack copies through integer registers + crb.blockComment("[stack -> stack copy]"); + AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), rscratch2); + masm.ldr(size, rscratch1, src); + AArch64Address dst = loadStackSlotAddress(crb, masm, asStackSlot(result), rscratch2); + masm.str(size, rscratch1, dst); + } + } + } + private static void reg2reg(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { Register dst = asRegister(result); Register src = asRegister(input); @@ -524,15 +546,17 @@ public class AArch64Move { } private static void const2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value result, JavaConstant constant) { - if (constant.isDefaultForKind() || constant.isNull()) { - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); - const2reg(crb, masm, scratchRegisterValue, constant); - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + StackSlot slot = (StackSlot) result; + AArch64Address resultAddress = loadStackSlotAddress(crb, masm, slot, addrReg.getRegister()); + if (constant.isDefaultForKind() || constant.isNull()) { + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); + } else { + try (ScratchRegister sc = masm.getScratchRegister()) { + Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); + const2reg(crb, masm, scratchRegisterValue, constant); + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + } } } } @@ -552,9 +576,13 @@ public class AArch64Move { * @return AArch64Address of given StackSlot. Uses scratch register if necessary to do so. */ private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, AllocatableValue scratch) { + Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); + return loadStackSlotAddress(crb, masm, slot, scratchReg); + } + + private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, Register scratchReg) { int displacement = crb.frameMap.offsetForStackSlot(slot); int transferSize = slot.getPlatformKind().getSizeInBytes(); - Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); return masm.makeAddress(sp, displacement, scratchReg, transferSize, /* allowOverwrite */false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java index 47f4d99ca91..49a7b278757 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java @@ -54,6 +54,6 @@ public class AArch64SignExtendOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register result = asRegister(resultValue); Register input = asRegister(inputValue); - masm.sxt(toBits, fromBits, result, input); + masm.sxt(toBits <= 32 ? 32 : 64, fromBits, result, input); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java new file mode 100644 index 00000000000..29b1fb420ed --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * AARCH64 LIR instructions that have one input and one output. + */ +public class AArch64Unary { + + /** + * Instruction with a {@link AArch64AddressValue memory} operand. + */ + public static class MemoryOp extends AArch64LIRInstruction implements ImplicitNullCheck { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemoryOp.class); + + private final boolean isSigned; + + @Def({REG}) protected AllocatableValue result; + @Use({COMPOSITE}) protected AArch64AddressValue input; + + @State protected LIRFrameState state; + + private int targetSize; + private int srcSize; + + public MemoryOp(boolean isSigned, int targetSize, int srcSize, AllocatableValue result, AArch64AddressValue input, LIRFrameState state) { + super(TYPE); + this.targetSize = targetSize; + this.srcSize = srcSize; + this.isSigned = isSigned; + this.result = result; + this.input = input; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + AArch64Address address = input.toAddress(); + Register dst = asRegister(result); + if (isSigned) { + masm.ldrs(targetSize, srcSize, dst, address); + } else { + masm.ldr(srcSize, dst, address); + } + } + + @Override + public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { + int immediate = input.getImmediate(); + if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && immediate >= 0 && immediate < implicitNullCheckLimit) { + state = nullCheckState; + return true; + } + return false; + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java index d67920fb023..f3f8a92f6a6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java @@ -65,6 +65,14 @@ public final class AMD64AddressValue extends CompositeValue { assert scale != null; } + public AllocatableValue getBase() { + return base; + } + + public AllocatableValue getIndex() { + return index; + } + @Override public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); @@ -81,6 +89,10 @@ public final class AMD64AddressValue extends CompositeValue { proc.visitValue(inst, index, mode, flags); } + public AMD64AddressValue withKind(ValueKind newKind) { + return new AMD64AddressValue(newKind, base, index, scale, displacement); + } + private static Register toRegister(AllocatableValue value) { if (value.equals(Value.ILLEGAL)) { return Register.None; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java index cff91a19bac..d5419f74c30 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java @@ -32,7 +32,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java index 8669c5217de..5f8f04abc2b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java @@ -30,7 +30,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java index 4f09ee0292d..def894caee8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.amd64; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AMD64BlockEndOp extends AbstractBlockEndOp { +public abstract class AMD64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java index dbddbcb191c..348d22eda3c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java @@ -31,7 +31,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java index 67bcfe63357..174305a29ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.lir.amd64; import static jdk.vm.ci.code.ValueUtil.asStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.framemap.FrameMap; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index e2bdfd3f4df..9692e1bfd00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -35,7 +35,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java index f4758ce3d31..68e80e0a95a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java @@ -27,8 +27,6 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.Arrays; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRValueUtil; @@ -36,6 +34,7 @@ import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; @@ -61,16 +60,16 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg @Def(STACK) protected final AllocatableValue[] slots; /** - * Specifies if {@link #remove(Set)} should have an effect. + * Specifies if {@link #remove(EconomicSet)} should have an effect. */ protected final boolean supportsRemove; /** * * @param savedRegisters the registers saved by this operation which may be subject to - * {@linkplain #remove(Set) pruning} + * {@linkplain #remove(EconomicSet) pruning} * @param savedRegisterLocations the slots to which the registers are saved - * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned} + * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned} */ public AMD64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove); @@ -108,14 +107,14 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { if (!supportsRemove) { throw new UnsupportedOperationException(); } return prune(doNotSave, savedRegisters); } - static int prune(Set toRemove, Register[] registers) { + static int prune(EconomicSet toRemove, Register[] registers) { int pruned = 0; for (int i = 0; i < registers.length; i++) { if (registers[i] != null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java new file mode 100644 index 00000000000..aeb736b5588 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.amd64; + +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +/** + */ +@Opcode("AMD64_STRING_INDEX_OF") +public final class AMD64StringIndexOfOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64StringIndexOfOp.class); + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value charPtr1Value; + @Alive({REG}) protected Value charPtr2Value; + @Use({REG}) protected RegisterValue cnt1Value; + @Temp({REG}) protected RegisterValue cnt1ValueT; + @Use({REG}) protected RegisterValue cnt2Value; + @Temp({REG}) protected RegisterValue cnt2ValueT; + @Temp({REG}) protected Value temp1; + @Temp({REG, ILLEGAL}) protected Value vectorTemp1; + + private final int intCnt2; + + private final int vmPageSize; + + public AMD64StringIndexOfOp(LIRGeneratorTool tool, Value result, Value charPtr1, Value charPtr2, RegisterValue cnt1, RegisterValue cnt2, RegisterValue temp1, RegisterValue vectorTemp1, + int intCnt2, int vmPageSize) { + super(TYPE); + assert ((AMD64) tool.target().arch).getFeatures().contains(CPUFeature.SSE4_2); + resultValue = result; + charPtr1Value = charPtr1; + charPtr2Value = charPtr2; + /* + * The count values are inputs but are also killed like temporaries so need both Use and + * Temp annotations, which will only work with fixed registers. + */ + cnt1Value = cnt1; + cnt1ValueT = cnt1; + cnt2Value = cnt2; + cnt2ValueT = cnt2; + assert asRegister(cnt1).equals(rdx) && asRegister(cnt2).equals(rax) && asRegister(temp1).equals(rcx) : "fixed register usage required"; + + this.temp1 = temp1; + this.vectorTemp1 = vectorTemp1; + this.intCnt2 = intCnt2; + this.vmPageSize = vmPageSize; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + Register charPtr1 = asRegister(charPtr1Value); + Register charPtr2 = asRegister(charPtr2Value); + Register cnt1 = asRegister(cnt1Value); + Register cnt2 = asRegister(cnt2Value); + Register result = asRegister(resultValue); + Register vec = asRegister(vectorTemp1); + Register tmp = asRegister(temp1); + if (intCnt2 >= 8) { + masm.stringIndexofC8(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp); + } else { + masm.stringIndexOf(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp, vmPageSize); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java index 1345b49e2e2..134abcbb7ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java @@ -24,14 +24,13 @@ package org.graalvm.compiler.lir.amd64; import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; @@ -76,7 +75,7 @@ public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements Sa } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { return prune(doNotSave, zappedRegisters); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index 3eee2c46aa3..2d8cff20468 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64StackMove; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; -import org.graalvm.compiler.options.NestedBooleanOptionValue; +import org.graalvm.compiler.options.NestedBooleanOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; @@ -58,7 +58,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase public static class Options { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final NestedBooleanOptionValue LIROptStackMoveOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + public static final NestedBooleanOptionKey LIROptStackMoveOptimizer = new NestedBooleanOptionKey(LIROptimization, true); // @formatter:on } @@ -68,7 +68,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { - List instructions = lir.getLIRforBlock(block); + ArrayList instructions = lir.getLIRforBlock(block); new Closure().process(instructions); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java index 2f6cc407e45..ff5e3b8eca7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java @@ -27,7 +27,7 @@ import org.junit.Assume; import org.junit.Test; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java index 44edf5a51c4..4274f3833d9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -71,7 +71,7 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(5); @Opcode private final FloatConvert opcode; - @Def({REG, HINT}) protected Value result; + @Def({REG, HINT}) protected AllocatableValue result; @Use({REG}) protected Value x; public enum FloatConvert { @@ -81,7 +81,7 @@ public class SPARCArithmetic { D2L } - public FloatConvertOp(FloatConvert opcode, Value x, Value result) { + public FloatConvertOp(FloatConvert opcode, Value x, AllocatableValue result) { super(TYPE, SIZE); this.opcode = opcode; this.x = x; @@ -138,11 +138,11 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(4); @Opcode private final Rem opcode; - @Def({REG}) protected Value result; + @Def({REG}) protected AllocatableValue result; @Alive({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; @State protected LIRFrameState state; public enum Rem { @@ -150,7 +150,7 @@ public class SPARCArithmetic { LUREM } - public RemOp(Rem opcode, Value result, Value x, Value y, Value scratch1, Value scratch2, LIRFrameState state) { + public RemOp(Rem opcode, AllocatableValue result, Value x, Value y, AllocatableValue scratch1, AllocatableValue scratch2, LIRFrameState state) { super(TYPE, SIZE); this.opcode = opcode; this.result = result; @@ -221,11 +221,11 @@ public class SPARCArithmetic { public static final class SPARCIMulccOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCIMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(10); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; - public SPARCIMulccOp(Value result, Value x, Value y) { + public SPARCIMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y) { super(TYPE, SIZE); this.result = result; this.x = x; @@ -258,13 +258,13 @@ public class SPARCArithmetic { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(13); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; - public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) { + public SPARCLMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y, LIRGeneratorTool gen) { super(TYPE, SIZE); this.result = result; this.x = x; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java index 1a0be8840e5..78ef442a395 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; @@ -32,9 +35,6 @@ import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Equal; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Less; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -49,8 +49,8 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; import sun.misc.Unsafe; @@ -66,17 +66,17 @@ public final class SPARCArrayEqualsOp extends SPARCLIRInstruction { private final int arrayBaseOffset; private final int arrayIndexScale; - @Def({REG}) protected Value resultValue; - @Alive({REG}) protected Value array1Value; - @Alive({REG}) protected Value array2Value; - @Alive({REG}) protected Value lengthValue; - @Temp({REG}) protected Value temp1; - @Temp({REG}) protected Value temp2; - @Temp({REG}) protected Value temp3; - @Temp({REG}) protected Value temp4; - @Temp({REG}) protected Value temp5; + @Def({REG}) protected AllocatableValue resultValue; + @Alive({REG}) protected AllocatableValue array1Value; + @Alive({REG}) protected AllocatableValue array2Value; + @Alive({REG}) protected AllocatableValue lengthValue; + @Temp({REG}) protected AllocatableValue temp1; + @Temp({REG}) protected AllocatableValue temp2; + @Temp({REG}) protected AllocatableValue temp3; + @Temp({REG}) protected AllocatableValue temp4; + @Temp({REG}) protected AllocatableValue temp5; - public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, AllocatableValue result, AllocatableValue array1, AllocatableValue array2, AllocatableValue length) { super(TYPE, SIZE); this.kind = kind; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java index 1221cebba46..e296e65396e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.lir.sparc; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.core.common.LIRKind; @@ -40,7 +40,6 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.meta.Value; public final class SPARCBitManipulationOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBitManipulationOp.class); @@ -60,7 +59,7 @@ public final class SPARCBitManipulationOp extends SPARCLIRInstruction { @Opcode private final IntrinsicOpcode opcode; @Def protected AllocatableValue result; @Alive({REG}) protected AllocatableValue input; - @Temp({REG}) protected Value scratch; + @Temp({REG}) protected AllocatableValue scratch; public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) { super(TYPE, opcode.size); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java index ed551fce119..71617b952d0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.sparc; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class SPARCBlockEndOp extends AbstractBlockEndOp implements SPARCLIRInstructionMixin { +public abstract class SPARCBlockEndOp extends LIRInstruction implements BlockEndOp, SPARCLIRInstructionMixin { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBlockEndOp.class); private final SPARCLIRInstructionMixinStore store; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java index 4679dacc6c1..e497ef90232 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCAssembler.Asi; @@ -43,19 +43,18 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; @Opcode("BSWAP") public final class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCByteSwapOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(3); - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value input; - @Temp({REG}) protected Value tempIndex; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + @Temp({REG}) protected AllocatableValue tempIndex; @Use({STACK, UNINITIALIZED}) protected AllocatableValue tmpSlot; - public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) { + public SPARCByteSwapOp(LIRGeneratorTool tool, AllocatableValue result, AllocatableValue input) { super(TYPE, SIZE); this.result = result; this.input = input; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java index a7823bb46ba..bd5eb048711 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -76,14 +76,11 @@ import static jdk.vm.ci.sparc.SPARCKind.XWORD; import java.util.ArrayList; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.sparc.SPARCAssembler; import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict; import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; @@ -101,6 +98,8 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -144,7 +143,7 @@ public class SPARCControlFlow { public static final SizeEstimate SIZE = SizeEstimate.create(3); static final EnumSet SUPPORTED_KINDS = EnumSet.of(XWORD, WORD); - @Use({REG}) protected Value x; + @Use({REG}) protected AllocatableValue x; @Use({REG, CONST}) protected Value y; private ConditionFlag conditionFlag; protected final LabelRef trueDestination; @@ -157,7 +156,8 @@ public class SPARCControlFlow { private int delaySlotPosition = -1; private double trueDestinationProbability; - public CompareBranchOp(Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, double trueDestinationProbability) { + public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, + double trueDestinationProbability) { super(TYPE, SIZE); this.x = x; this.y = y; @@ -426,15 +426,16 @@ public class SPARCControlFlow { @Alive({REG, ILLEGAL}) protected Value constantTableBase; @Temp({REG}) protected Value scratch; protected final SwitchStrategy strategy; - private final Map labelHints; + private final EconomicMap labelHints; private final List