提交 cd2ffae5 编写于 作者: K Kuai Wei 提交者: 云矅

[JWarmUp] port jwarmup to dragonwell 8u

Summary:
  Port jwarmup to dragonwell 8u hotspot

ref T19299187

Test Plan:
test/hotspot/jtreg/jwarmup/Issue11272598.java
test/hotspot/jtreg/jwarmup/TestDisableNCE.java
test/hotspot/jtreg/jwarmup/TestNotDeoptJITMethod.sh
test/hotspot/jtreg/jwarmup/issue9780156.sh
test/hotspot/jtreg/jwarmup/TestEagerCompilation.java
test/hotspot/jtreg/jwarmup/TestNotifyDeopt.sh
test/hotspot/jtreg/jwarmup/TestCheckIfCompilationIsComplete.sh
test/hotspot/jtreg/jwarmup/TestFlagAssertion.java
test/hotspot/jtreg/jwarmup/TestReadLogfile.java
test/hotspot/jtreg/jwarmup/TestClassInitChain.java
test/hotspot/jtreg/jwarmup/TestLogFlush.java
test/hotspot/jtreg/jwarmup/TestRecordNullMethodCounter.java
test/hotspot/jtreg/jwarmup/TestThrowInitializaitonException.java
test/hotspot/jtreg/jwarmup/TestDisableMethodData.sh
test/hotspot/jtreg/jwarmup/TestMethodRecorder.java
test/hotspot/jtreg/jwarmup/TestTieredCompilationInRecording.sh

Reviewers: 传胜, 三红, yumin.qi

Reviewed By: 传胜, 三红

Subscribers: 麦庶

Differential Revision: https://aone.alibaba-inc.com/code/D852146
上级 45188b6d
...@@ -40,6 +40,7 @@ SUNWprivate_1.1 { ...@@ -40,6 +40,7 @@ SUNWprivate_1.1 {
JVM_AssertionStatusDirectives; JVM_AssertionStatusDirectives;
JVM_Available; JVM_Available;
JVM_Bind; JVM_Bind;
JVM_CheckJWarmUpCompilationIsComplete;
JVM_ClassDepth; JVM_ClassDepth;
JVM_ClassLoaderDepth; JVM_ClassLoaderDepth;
JVM_Clone; JVM_Clone;
...@@ -205,6 +206,8 @@ SUNWprivate_1.1 { ...@@ -205,6 +206,8 @@ SUNWprivate_1.1 {
JVM_NewArray; JVM_NewArray;
JVM_NewInstanceFromConstructor; JVM_NewInstanceFromConstructor;
JVM_NewMultiArray; JVM_NewMultiArray;
JVM_NotifyApplicationStartUpIsDone;
JVM_NotifyJVMDeoptWarmUpMethods;
JVM_OnExit; JVM_OnExit;
JVM_Open; JVM_Open;
JVM_RaiseSignal; JVM_RaiseSignal;
......
...@@ -40,6 +40,7 @@ SUNWprivate_1.1 { ...@@ -40,6 +40,7 @@ SUNWprivate_1.1 {
JVM_AssertionStatusDirectives; JVM_AssertionStatusDirectives;
JVM_Available; JVM_Available;
JVM_Bind; JVM_Bind;
JVM_CheckJWarmUpCompilationIsComplete;
JVM_ClassDepth; JVM_ClassDepth;
JVM_ClassLoaderDepth; JVM_ClassLoaderDepth;
JVM_Clone; JVM_Clone;
...@@ -205,6 +206,8 @@ SUNWprivate_1.1 { ...@@ -205,6 +206,8 @@ SUNWprivate_1.1 {
JVM_NewArray; JVM_NewArray;
JVM_NewInstanceFromConstructor; JVM_NewInstanceFromConstructor;
JVM_NewMultiArray; JVM_NewMultiArray;
JVM_NotifyApplicationStartUpIsDone;
JVM_NotifyJVMDeoptWarmUpMethods;
JVM_OnExit; JVM_OnExit;
JVM_Open; JVM_Open;
JVM_RaiseSignal; JVM_RaiseSignal;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "interpreter/interpreterGenerator.hpp" #include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreterRuntime.hpp" #include "interpreter/interpreterRuntime.hpp"
#include "interpreter/templateTable.hpp" #include "interpreter/templateTable.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "oops/arrayOop.hpp" #include "oops/arrayOop.hpp"
#include "oops/methodData.hpp" #include "oops/methodData.hpp"
#include "oops/method.hpp" #include "oops/method.hpp"
...@@ -334,6 +335,24 @@ void InterpreterGenerator::generate_counter_incr( ...@@ -334,6 +335,24 @@ void InterpreterGenerator::generate_counter_incr(
__ incrementl(Address(rax, __ incrementl(Address(rax,
MethodCounters::interpreter_invocation_counter_offset())); MethodCounters::interpreter_invocation_counter_offset()));
} }
#ifdef _LP64
// JitWarmUp support, record method first invocation's initialization order
if (CompilationWarmUpRecording) {
Label skip_record;
JitWarmUp* jitwarmup = JitWarmUp::instance();
assert(jitwarmup != NULL, "jitwarmup should not be NULL");
const ExternalAddress current_init_order(jitwarmup->recorder()->current_init_order_addr());
__ movl(rcx, Address(rax,
MethodCounters::interpreter_invocation_counter_offset()));
__ cmp32(rcx, 1);
__ jcc(Assembler::above, skip_record);
__ mov32(rcx, current_init_order);
__ movl(Address(rbx, Method::first_invoke_init_order_offset()), rcx);
__ bind(skip_record);
}
#endif
// Update standard invocation counters // Update standard invocation counters
__ movl(rcx, invocation_counter); __ movl(rcx, invocation_counter);
__ incrementl(rcx, InvocationCounter::count_increment); __ incrementl(rcx, InvocationCounter::count_increment);
......
...@@ -672,6 +672,63 @@ ciField* ciEnv::get_field_by_index(ciInstanceKlass* accessor, ...@@ -672,6 +672,63 @@ ciField* ciEnv::get_field_by_index(ciInstanceKlass* accessor,
GUARDED_VM_ENTRY(return get_field_by_index_impl(accessor, index);) GUARDED_VM_ENTRY(return get_field_by_index_impl(accessor, index);)
} }
// ------------------------------------------------------------------
// ciEnv::check_field_resolved
//
// Check whether this field has been resolved.
bool ciEnv::check_field_resolved(ciInstanceKlass* accessor,
int index) {
GUARDED_VM_ENTRY(
ciConstantPoolCache* cache = accessor->field_cache();
if (cache != NULL) {
ciField* field = (ciField*)cache->get(index);
if (field != NULL) {
return true;
}
}
CompilerThread *thread = CompilerThread::current();
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before using its constant-pool");
constantPoolHandle cpool(thread, accessor->get_instanceKlass()->constants());
// Get the field's name, signature, and type.
Symbol* name = cpool->name_ref_at(index);
if (name == NULL) {
return false;
}
int name_index = cpool->name_and_type_ref_index_at(index);
int sig_index = cpool->signature_ref_index_at(name_index);
Symbol* signature = cpool->symbol_at(sig_index);
if (signature == NULL) {
return false;
}
return true;
)
}
// ------------------------------------------------------------------
//
// Check if all fields needed by this method in ConstantPool are resolved
bool ciEnv::check_method_fields_all_resolved(ciMethod* method) {
ciInstanceKlass* klass = method->holder();
ciBytecodeStream str(method);
int start = 0;
int limit = method->code_size();
str.reset_to_bci(start);
Bytecodes::Code code;
while ((code = str.next()) != ciBytecodeStream::EOBC() &&
str.cur_bci() < limit) {
if (code == Bytecodes::_getfield ||
code == Bytecodes::_getstatic ||
code == Bytecodes::_putfield ||
code == Bytecodes::_putstatic) {
if (!check_field_resolved(klass, str.get_index_u2_cpcache())) {
return false;
}
}
}
return true;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciEnv::lookup_method // ciEnv::lookup_method
// //
......
...@@ -126,6 +126,8 @@ private: ...@@ -126,6 +126,8 @@ private:
ciInstanceKlass* accessor); ciInstanceKlass* accessor);
ciField* get_field_by_index(ciInstanceKlass* loading_klass, ciField* get_field_by_index(ciInstanceKlass* loading_klass,
int field_index); int field_index);
bool check_field_resolved(ciInstanceKlass* accessor,
int index);
ciMethod* get_method_by_index(constantPoolHandle cpool, ciMethod* get_method_by_index(constantPoolHandle cpool,
int method_index, Bytecodes::Code bc, int method_index, Bytecodes::Code bc,
ciInstanceKlass* loading_klass); ciInstanceKlass* loading_klass);
...@@ -317,6 +319,9 @@ public: ...@@ -317,6 +319,9 @@ public:
// Return state of appropriate compilability // Return state of appropriate compilability
int compilable() { return _compilable; } int compilable() { return _compilable; }
// Check if all fields needed by this method in ConstantPool are resolved
bool check_method_fields_all_resolved(ciMethod* method);
const char* retry_message() const { const char* retry_message() const {
switch (_compilable) { switch (_compilable) {
case ciEnv::MethodCompilable_not_at_tier: case ciEnv::MethodCompilable_not_at_tier:
......
...@@ -975,6 +975,10 @@ bool ciMethod::ensure_method_data(methodHandle h_m) { ...@@ -975,6 +975,10 @@ bool ciMethod::ensure_method_data(methodHandle h_m) {
if (is_native() || is_abstract() || h_m()->is_accessor()) { if (is_native() || is_abstract() || h_m()->is_accessor()) {
return true; return true;
} }
if (CompilationWarmUp && CURRENT_ENV->task()->is_jwarmup_compilation()) {
_method_data = CURRENT_ENV->get_empty_methodData();
return false;
}
if (h_m()->method_data() == NULL) { if (h_m()->method_data() == NULL) {
Method::build_interpreter_method_data(h_m, THREAD); Method::build_interpreter_method_data(h_m, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
...@@ -1015,7 +1019,9 @@ ciMethodData* ciMethod::method_data() { ...@@ -1015,7 +1019,9 @@ ciMethodData* ciMethod::method_data() {
Thread* my_thread = JavaThread::current(); Thread* my_thread = JavaThread::current();
methodHandle h_m(my_thread, get_Method()); methodHandle h_m(my_thread, get_Method());
if (h_m()->method_data() != NULL) { if (CompilationWarmUp && CURRENT_ENV->task()->is_jwarmup_compilation()) {
_method_data = CURRENT_ENV->get_empty_methodData();
} else if (h_m()->method_data() != NULL) {
_method_data = CURRENT_ENV->get_method_data(h_m()->method_data()); _method_data = CURRENT_ENV->get_method_data(h_m()->method_data());
_method_data->load_data(); _method_data->load_data();
} else { } else {
......
...@@ -4133,6 +4133,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4133,6 +4133,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass->set_has_default_methods(has_default_methods); this_klass->set_has_default_methods(has_default_methods);
this_klass->set_declares_default_methods(declares_default_methods); this_klass->set_declares_default_methods(declares_default_methods);
if (CompilationWarmUp || CompilationWarmUpRecording) {
if (_stream->source() == NULL) {
this_klass->set_source_file_path(NULL);
} else {
this_klass->set_source_file_path(SymbolTable::new_symbol(_stream->source(), THREAD));
}
}
if (!host_klass.is_null()) { if (!host_klass.is_null()) {
assert (this_klass->is_anonymous(), "should be the same"); assert (this_klass->is_anonymous(), "should be the same");
this_klass->set_host_klass(host_klass()); this_klass->set_host_klass(host_klass());
...@@ -4270,6 +4278,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4270,6 +4278,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
instanceKlassHandle this_klass (THREAD, preserve_this_klass); instanceKlassHandle this_klass (THREAD, preserve_this_klass);
debug_only(this_klass->verify();) debug_only(this_klass->verify();)
if (CompilationWarmUp || CompilationWarmUpRecording) {
unsigned int crc32 = ClassLoader::crc32(0, (char*)(_stream->buffer()), _stream->length());
unsigned int class_bytes_size = _stream->length();
this_klass->set_crc32(crc32);
this_klass->set_bytes_size(class_bytes_size);
}
// Clear class if no error has occurred so destructor doesn't deallocate it // Clear class if no error has occurred so destructor doesn't deallocate it
_klass = NULL; _klass = NULL;
return this_klass; return this_klass;
......
...@@ -763,6 +763,14 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, boo ...@@ -763,6 +763,14 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, boo
ClassLoaderData* prev = NULL; ClassLoaderData* prev = NULL;
bool seen_dead_loader = false; bool seen_dead_loader = false;
// Unload PreloadClassChain
if (CompilationWarmUp) {
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "santiy check");
PreloadClassChain* chain = jwp->preloader()->chain();
chain->do_unloading(is_alive_closure);
}
// Save previous _unloading pointer for CMS which may add to unloading list before // Save previous _unloading pointer for CMS which may add to unloading list before
// purging and we don't want to rewalk the previously unloaded class loader data. // purging and we don't want to rewalk the previously unloaded class loader data.
_saved_unloading = _unloading; _saved_unloading = _unloading;
......
...@@ -273,6 +273,29 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name, ...@@ -273,6 +273,29 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
return k; return k;
} }
class SuperClassResolvingMark : public StackObj {
public:
SuperClassResolvingMark() {
initialize(Thread::current());
}
SuperClassResolvingMark(Thread* thread) {
initialize(thread);
}
~SuperClassResolvingMark() {
assert(CompilationWarmUp, "wrong usage");
_thread->super_class_resolving_recursive_dec();
}
protected:
void initialize(Thread* thread) {
assert(CompilationWarmUp, "wrong usage");
_thread = thread;
_thread->super_class_resolving_recursive_inc();
}
private:
Thread* _thread;
};
// Must be called for any super-class or super-interface resolution // Must be called for any super-class or super-interface resolution
// during class definition to allow class circularity checking // during class definition to allow class circularity checking
...@@ -373,11 +396,21 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, ...@@ -373,11 +396,21 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
// java.lang.Object should have been found above // java.lang.Object should have been found above
assert(class_name != NULL, "null super class for resolving"); assert(class_name != NULL, "null super class for resolving");
// Resolve the super class or interface, check results on return // Resolve the super class or interface, check results on return
Klass* superk = SystemDictionary::resolve_or_null(class_name, Klass* superk = NULL;
class_loader, if (CompilationWarmUp) {
protection_domain, SuperClassResolvingMark scrm;
THREAD); superk =
SystemDictionary::resolve_or_null(class_name,
class_loader,
protection_domain,
THREAD);
} else {
superk =
SystemDictionary::resolve_or_null(class_name,
class_loader,
protection_domain,
THREAD);
}
KlassHandle superk_h(THREAD, superk); KlassHandle superk_h(THREAD, superk);
// Clean up of placeholders moved so that each classloadAction registrar self-cleans up // Clean up of placeholders moved so that each classloadAction registrar self-cleans up
...@@ -868,6 +901,14 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, ...@@ -868,6 +901,14 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
} }
#endif #endif
if (CompilationWarmUp) {
if (!class_has_been_loaded) {
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "sanity check");
jwp->preloader()->resolve_loaded_klass(k());
}
}
// return if the protection domain in NULL // return if the protection domain in NULL
if (protection_domain() == NULL) return k(); if (protection_domain() == NULL) return k();
...@@ -1155,6 +1196,12 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, ...@@ -1155,6 +1196,12 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
} }
} ); } );
if (CompilationWarmUp) {
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "sanity check");
jwp->preloader()->resolve_loaded_klass(k());
}
return k(); return k();
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "classfile/classFileStream.hpp" #include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp" #include "classfile/classLoader.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "oops/objArrayOop.hpp" #include "oops/objArrayOop.hpp"
#include "oops/symbol.hpp" #include "oops/symbol.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"
...@@ -201,6 +202,8 @@ class SymbolPropertyTable; ...@@ -201,6 +202,8 @@ class SymbolPropertyTable;
class SystemDictionary : AllStatic { class SystemDictionary : AllStatic {
friend class VMStructs; friend class VMStructs;
friend class SystemDictionaryHandles; friend class SystemDictionaryHandles;
friend class JitWarmUp;
friend class PreloadJitInfo;
public: public:
enum WKID { enum WKID {
......
...@@ -410,6 +410,7 @@ ...@@ -410,6 +410,7 @@
template(signers_name, "signers_name") \ template(signers_name, "signers_name") \
template(loader_data_name, "loader_data") \ template(loader_data_name, "loader_data") \
template(dependencies_name, "dependencies") \ template(dependencies_name, "dependencies") \
template(jwarmup_dummy_name, "dummy") \
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \ template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
template(getFileURL_name, "getFileURL") \ template(getFileURL_name, "getFileURL") \
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \ template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "compiler/compilerOracle.hpp" #include "compiler/compilerOracle.hpp"
#include "compiler/disassembler.hpp" #include "compiler/disassembler.hpp"
#include "interpreter/bytecode.hpp" #include "interpreter/bytecode.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "oops/methodData.hpp" #include "oops/methodData.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/jvmtiImpl.hpp" #include "prims/jvmtiImpl.hpp"
...@@ -649,6 +650,10 @@ nmethod* nmethod::new_nmethod(methodHandle method, ...@@ -649,6 +650,10 @@ nmethod* nmethod::new_nmethod(methodHandle method,
DEBUG_ONLY(nm->verify();) DEBUG_ONLY(nm->verify();)
nm->log_new_nmethod(); nm->log_new_nmethod();
} }
if (CompilationWarmUpRecording && nm != NULL && comp_level >= CompilationWarmUpRecordMinLevel) {
int bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
JitWarmUp::instance()->recorder()->add_method(nm->method(), bci);
}
return nm; return nm;
} }
......
...@@ -331,6 +331,8 @@ void CompileTask::initialize(int compile_id, ...@@ -331,6 +331,8 @@ void CompileTask::initialize(int compile_id,
_comment = comment; _comment = comment;
_failure_reason = NULL; _failure_reason = NULL;
_is_jwarmup_compilation = false;
if (LogCompilation) { if (LogCompilation) {
_time_queued = os::elapsed_counter(); _time_queued = os::elapsed_counter();
if (hot_method.not_null()) { if (hot_method.not_null()) {
...@@ -1594,6 +1596,9 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue, ...@@ -1594,6 +1596,9 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
new_task->initialize(compile_id, method, osr_bci, comp_level, new_task->initialize(compile_id, method, osr_bci, comp_level,
hot_method, hot_count, comment, hot_method, hot_count, comment,
blocking); blocking);
if (strcmp(comment, "JitWarmUp") == 0) {
new_task->mark_jwarmup_compilation();
}
queue->add(new_task); queue->add(new_task);
return new_task; return new_task;
} }
......
...@@ -65,6 +65,7 @@ class CompileTask : public CHeapObj<mtCompiler> { ...@@ -65,6 +65,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
int _hot_count; // information about its invocation counter int _hot_count; // information about its invocation counter
const char* _comment; // more info about the task const char* _comment; // more info about the task
const char* _failure_reason; const char* _failure_reason;
bool _is_jwarmup_compilation;
public: public:
CompileTask() { CompileTask() {
...@@ -84,6 +85,8 @@ class CompileTask : public CHeapObj<mtCompiler> { ...@@ -84,6 +85,8 @@ class CompileTask : public CHeapObj<mtCompiler> {
bool is_complete() const { return _is_complete; } bool is_complete() const { return _is_complete; }
bool is_blocking() const { return _is_blocking; } bool is_blocking() const { return _is_blocking; }
bool is_success() const { return _is_success; } bool is_success() const { return _is_success; }
bool is_jwarmup_compilation() const { return _is_jwarmup_compilation; }
void mark_jwarmup_compilation() { _is_jwarmup_compilation = true; }
nmethodLocker* code_handle() const { return _code_handle; } nmethodLocker* code_handle() const { return _code_handle; }
void set_code_handle(nmethodLocker* l) { _code_handle = l; } void set_code_handle(nmethodLocker* l) { _code_handle = l; }
......
此差异已折叠。
此差异已折叠。
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_JWARMUP_JITWARMUPLOG_HPP
#define SHARE_VM_JWARMUP_JITWARMUPLOG_HPP
/*
* We use this file to be compatible with log framework in JDK11
* To avoid conflict with jfr log, it's only used by jitWarmUp.cpp
*/
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
#ifdef log_error
#undef log_error
#endif
#ifdef log_warning
#undef log_warning
#endif
#ifdef log_info
#undef log_info
#endif
#ifdef log_debug
#undef log_debug
#endif
#ifdef log_trace
#undef log_trace
#endif
#ifdef log_is_enabled
#undef log_is_enabled
#endif
#define log_error(...) (!log_is_enabled(Error, __VA_ARGS__)) ? (void)0 : tty->print_cr
#define log_warning(...) (!log_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : tty->print_cr
#define log_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : tty->print_cr
#define log_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : tty->print_cr
#define log_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : tty->print_cr
#define log_is_enabled(level, ...) (LogImplWarmUp::is_level(LogLevel::level))
class LogImplWarmUp {
public:
static bool is_level(LogLevelType level) {
if (PrintCompilationWarmUpDetail || level >= (jint)LogLevel::Info) {
return true;
}
return false;
}
};
#endif
/*
* Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
* 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. Alibaba 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.
*/
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "jwarmup/jitWarmUpThread.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.hpp"
JitWarmUpFlushThread* JitWarmUpFlushThread::_jwp_thread = NULL;
JitWarmUpFlushThread::JitWarmUpFlushThread(unsigned int sec) : NamedThread() {
set_name("JitWarmUp Flush Thread");
set_sleep_sec(sec);
if (os::create_thread(this, os::vm_thread)) {
os::set_priority(this, MaxPriority);
} else {
tty->print_cr("[JitWarmUp] ERROR : failed to create JitWarmUpFlushThread");
vm_exit(-1);
}
}
JitWarmUpFlushThread::~JitWarmUpFlushThread() {
// do nothing
}
void JitWarmUpFlushThread::run() {
assert(_jwp_thread == this, "sanity check");
this->record_stack_base_and_size();
this->_has_started = true;
os::sleep(this, 1000 * sleep_sec(), false);
JitWarmUp::instance()->flush_logfile();
{
MutexLockerEx mu(JitWarmUpPrint_lock);
_jwp_thread = NULL;
}
}
void JitWarmUpFlushThread::spawn_wait_for_flush(unsigned int sec) {
JitWarmUpFlushThread* t = new JitWarmUpFlushThread(sec);
_jwp_thread = t;
Thread::start(t);
}
void JitWarmUpFlushThread::print_jwarmup_threads_on(outputStream* st) {
MutexLockerEx mu(JitWarmUpPrint_lock);
if (_jwp_thread == NULL || !_jwp_thread->has_started()) {
return;
}
st->print("\"%s\" ", _jwp_thread->name());
_jwp_thread->print_on(st);
st->cr();
}
/*
* Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
* 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. Alibaba 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.
*/
#ifndef SHARE_VM_JWARMUP_JITWARMUPTHREAD_HPP
#define SHARE_VM_JWARMUP_JITWARMUPTHREAD_HPP
#include "runtime/thread.hpp"
class JitWarmUpFlushThread : public NamedThread {
protected:
JitWarmUpFlushThread(unsigned int sec);
virtual ~JitWarmUpFlushThread();
public:
virtual void run();
bool has_started() { return _has_started; }
unsigned int sleep_sec() { return _sleep_sec; }
void set_sleep_sec(unsigned int sec) { _sleep_sec = sec; }
static void spawn_wait_for_flush(unsigned int sec);
static void print_jwarmup_threads_on(outputStream* st);
private:
volatile bool _has_started;
unsigned int _sleep_sec;
static JitWarmUpFlushThread* _jwp_thread;
};
#endif //SHARE_VM_JWARMUP_JITWARMUPTHREAD_HPP
...@@ -330,6 +330,31 @@ int hashstr(const void *t) { ...@@ -330,6 +330,31 @@ int hashstr(const void *t) {
return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size
} }
// compute hash from char array with given length
int hashstr2(const char *s, int len) {
char c, k = 0;
int32_t sum = 0;
int cnt = 0;
// make sure xsum array is initialized
if( !initflag ) { // Not initializated yet?
xsum[0] = (1<<shft[0])+1; // Initialize
for(int i = 1; i < MAXID; i++) {
xsum[i] = (1<<shft[i])+1+xsum[i-1];
}
initflag = 1; // Never again
}
while(cnt < len) { // Get characters till null or MAXID-1
c = *s++;
c = (c<<1) + 1; // Characters are always odd!
sum += c + (c<<shft[k++]); // Universal hash function
k %= MAXID;
cnt++;
}
return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size
}
//------------------------------hashptr-------------------------------------- //------------------------------hashptr--------------------------------------
// Slimey cheap hash function; no guaranteed performance. Better than the // Slimey cheap hash function; no guaranteed performance. Better than the
// default for pointers, especially on MS-DOS machines. // default for pointers, especially on MS-DOS machines.
......
...@@ -89,6 +89,7 @@ class Dict : public ResourceObj { // Dictionary structure ...@@ -89,6 +89,7 @@ class Dict : public ResourceObj { // Dictionary structure
// Hashing functions // Hashing functions
int hashstr(const void *s); // Nice string hash int hashstr(const void *s); // Nice string hash
int hashstr2(const char *s, int len); // hash string with given length
// Slimey cheap hash function; no guaranteed performance. Better than the // Slimey cheap hash function; no guaranteed performance. Better than the
// default for pointers, especially on MS-DOS machines. // default for pointers, especially on MS-DOS machines.
int hashptr(const void *key); int hashptr(const void *key);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/heapInspection.hpp" #include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp" #include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
...@@ -41,6 +42,8 @@ ...@@ -41,6 +42,8 @@
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "runtime/signature.hpp" #include "runtime/signature.hpp"
#include "runtime/vframe.hpp" #include "runtime/vframe.hpp"
#include "utilities/stack.hpp"
#include "utilities/stack.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
...@@ -56,12 +59,19 @@ ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, T ...@@ -56,12 +59,19 @@ ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, T
// the resolved_references array, which is recreated at startup time. // the resolved_references array, which is recreated at startup time.
// But that could be moved to InstanceKlass (although a pain to access from // But that could be moved to InstanceKlass (although a pain to access from
// assembly code). Maybe it could be moved to the cpCache which is RW. // assembly code). Maybe it could be moved to the cpCache which is RW.
return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags); if (CompilationWarmUp) {
Array<u1>* jwp_tags = NULL;
jwp_tags = MetadataFactory::new_array<u1>(loader_data, length, 0, CHECK_NULL);
return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags, jwp_tags);
} else {
return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
}
} }
ConstantPool::ConstantPool(Array<u1>* tags) { ConstantPool::ConstantPool(Array<u1>* tags) {
set_length(tags->length()); set_length(tags->length());
set_tags(NULL); set_tags(NULL);
set_jwp_tags(NULL);
set_cache(NULL); set_cache(NULL);
set_reference_map(NULL); set_reference_map(NULL);
set_resolved_references(NULL); set_resolved_references(NULL);
...@@ -81,6 +91,37 @@ ConstantPool::ConstantPool(Array<u1>* tags) { ...@@ -81,6 +91,37 @@ ConstantPool::ConstantPool(Array<u1>* tags) {
set_tags(tags); set_tags(tags);
} }
ConstantPool::ConstantPool(Array<u1>* tags, Array<u1>* jwp_tags) {
assert(CompilationWarmUp, "must in CompilationWarmUp");
assert(jwp_tags != NULL, "invariant");
assert(jwp_tags->length() == tags->length(), "invariant");
set_length(tags->length());
set_tags(NULL);
set_jwp_tags(NULL);
set_cache(NULL);
set_reference_map(NULL);
set_resolved_references(NULL);
set_operands(NULL);
set_pool_holder(NULL);
set_flags(0);
// only set to non-zero if constant pool is merged by RedefineClasses
set_version(0);
set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
// initialize tag array
int length = tags->length();
for (int index = 0; index < length; index++) {
tags->at_put(index, JVM_CONSTANT_Invalid);
}
set_tags(tags);
for (int i = 0; i < jwp_tags->length(); i++) {
jwp_tags->at_put(i, _jwp_has_not_been_traversed);
}
set_jwp_tags(jwp_tags);
}
void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) { void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
MetadataFactory::free_metadata(loader_data, cache()); MetadataFactory::free_metadata(loader_data, cache());
set_cache(NULL); set_cache(NULL);
...@@ -95,6 +136,12 @@ void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) { ...@@ -95,6 +136,12 @@ void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
// free tag array // free tag array
MetadataFactory::free_array<u1>(loader_data, tags()); MetadataFactory::free_array<u1>(loader_data, tags());
set_tags(NULL); set_tags(NULL);
if (CompilationWarmUp) {
assert(jwp_tags() != NULL, "should not be NULL");
MetadataFactory::free_array<u1>(loader_data, jwp_tags());
set_jwp_tags(NULL);
}
} }
void ConstantPool::release_C_heap_structures() { void ConstantPool::release_C_heap_structures() {
...@@ -1899,6 +1946,88 @@ void ConstantPool::preload_and_initialize_all_classes(ConstantPool* obj, TRAPS) ...@@ -1899,6 +1946,88 @@ void ConstantPool::preload_and_initialize_all_classes(ConstantPool* obj, TRAPS)
#endif #endif
void ConstantPool::preload_jwarmup_classes(TRAPS) {
constantPoolHandle cp(THREAD, this);
guarantee(cp->pool_holder() != NULL, "must be fully loaded");
if (THREAD->in_eagerly_loading_class()) {
return;
}
THREAD->set_in_eagerly_loading_class(true);
Stack<InstanceKlass*, mtClass> s;
s.push(cp->pool_holder());
preload_jwarmup_classes_impl(s, THREAD);
THREAD->set_in_eagerly_loading_class(false);
}
// should not be guarded in PreloadClassChain_lock
Klass* ConstantPool::resolve_class_from_slot(int which, TRAPS) {
assert(THREAD->is_Java_thread(), "must be a Java thread");
if (CompilationWarmUpResolveClassEagerly) {
Klass* k = klass_at(which, CHECK_NULL);
return k;
} else {
// Create a handle for the mirror. This will preserve the resolved class
// until the loader_data is registered.
Handle mirror_handle;
constantPoolHandle this_oop(THREAD, this);
Symbol* name = NULL;
Handle loader;
{
if (this_oop->tag_at(which).is_unresolved_klass()) {
if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
return NULL;
} else {
name = this_oop->klass_name_at(which);
loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
}
}
}
oop protection_domain = this_oop->pool_holder()->protection_domain();
Handle h_prot (THREAD, protection_domain);
Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
return k_oop;
}
}
// use bfs instead recusive
void ConstantPool::preload_jwarmup_classes_impl(Stack<InstanceKlass*, mtClass>& s,
TRAPS) {
JitWarmUp* jwp = JitWarmUp::instance();
while (!s.is_empty()) {
constantPoolHandle cp(s.pop()->constants());
for (int i = 0; i< cp->length(); i++) {
bool is_unresolved = false;
Symbol* name = NULL;
{
if (cp->tag_at(i).is_unresolved_klass() && !cp->jwarmup_traversed_at(i)) {
name = cp->klass_name_at(i);
is_unresolved = true;
cp->jwarmup_has_traversed_at(i);
}
}
if (is_unresolved) {
if (name != NULL && !jwp->preloader()->should_load_class_eagerly(name)) {
continue;
}
// Load class from ConstantPool slot, if flag CompilationWarmUpResolveClassEagerly
// is on, update ConstantPool status accordingly and assign to that slot.
Klass* klass = cp->resolve_class_from_slot(i, THREAD);
if (HAS_PENDING_EXCEPTION) {
ResourceMark rm;
tty->print_cr("[JitWarmUp] WARNING : resolve %s from constant pool failed",
name->as_C_string());
// ignore LinkageError in loading class
if (PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
CLEAR_PENDING_EXCEPTION;
}
}
if (klass != NULL && klass->oop_is_instance()) {
s.push((InstanceKlass*)klass);
}
} // end of if is_unresolved
} // end of loop
} // end of while
}
// Printing // Printing
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "oops/typeArrayOop.hpp" #include "oops/typeArrayOop.hpp"
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "utilities/constantTag.hpp" #include "utilities/constantTag.hpp"
#include "utilities/stack.hpp"
#ifdef TARGET_ARCH_x86 #ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp" # include "bytes_x86.hpp"
#endif #endif
...@@ -96,6 +97,13 @@ class ConstantPool : public Metadata { ...@@ -96,6 +97,13 @@ class ConstantPool : public Metadata {
jobject _resolved_references; jobject _resolved_references;
Array<u2>* _reference_map; Array<u2>* _reference_map;
enum {
_jwp_has_not_been_traversed = 0,
_jwp_has_been_traversed = 1
};
Array<u1>* _jwp_tags; // the jwp tag array records the corresponding tag whether is traversed
enum { enum {
_has_preresolution = 1, // Flags _has_preresolution = 1, // Flags
_on_stack = 2 _on_stack = 2
...@@ -114,6 +122,7 @@ class ConstantPool : public Metadata { ...@@ -114,6 +122,7 @@ class ConstantPool : public Metadata {
Monitor* _lock; Monitor* _lock;
void set_tags(Array<u1>* tags) { _tags = tags; } void set_tags(Array<u1>* tags) { _tags = tags; }
void set_jwp_tags(Array<u1>* tags) { _jwp_tags = tags; }
void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); } void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); }
void release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); } void release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); }
...@@ -164,6 +173,8 @@ class ConstantPool : public Metadata { ...@@ -164,6 +173,8 @@ class ConstantPool : public Metadata {
} }
ConstantPool(Array<u1>* tags); ConstantPool(Array<u1>* tags);
// for JWarmUP
ConstantPool(Array<u1>* tags, Array<u1>* jwp_tags);
ConstantPool() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } ConstantPool() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
public: public:
static ConstantPool* allocate(ClassLoaderData* loader_data, int length, TRAPS); static ConstantPool* allocate(ClassLoaderData* loader_data, int length, TRAPS);
...@@ -173,6 +184,18 @@ class ConstantPool : public Metadata { ...@@ -173,6 +184,18 @@ class ConstantPool : public Metadata {
Array<u1>* tags() const { return _tags; } Array<u1>* tags() const { return _tags; }
Array<u2>* operands() const { return _operands; } Array<u2>* operands() const { return _operands; }
Array<u1>* jwp_tags() const { return _jwp_tags; }
bool jwarmup_traversed_at(int which) {
assert(0 < which && which < jwp_tags()->length(), "out of bound");
return jwp_tags()->at(which) == _jwp_has_been_traversed;
}
void jwarmup_has_traversed_at(int which) {
assert(which < jwp_tags()->length(), "out of bound");
jwp_tags()->at_put(which, _jwp_has_been_traversed);
}
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
void set_has_preresolution() { _flags |= _has_preresolution; } void set_has_preresolution() { _flags |= _has_preresolution; }
...@@ -887,6 +910,13 @@ class ConstantPool : public Metadata { ...@@ -887,6 +910,13 @@ class ConstantPool : public Metadata {
// Compile the world support // Compile the world support
static void preload_and_initialize_all_classes(ConstantPool* constant_pool, TRAPS); static void preload_and_initialize_all_classes(ConstantPool* constant_pool, TRAPS);
#endif #endif
void preload_jwarmup_classes(TRAPS);
Klass* resolve_class_from_slot(int which, TRAPS);
private:
void preload_jwarmup_classes_impl(Stack<InstanceKlass*, mtClass>& s, TRAPS);
}; };
class SymbolHashMapEntry : public CHeapObj<mtSymbol> { class SymbolHashMapEntry : public CHeapObj<mtSymbol> {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "interpreter/oopMapCache.hpp" #include "interpreter/oopMapCache.hpp"
#include "interpreter/rewriter.hpp" #include "interpreter/rewriter.hpp"
#include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmti.h"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/genOopClosures.inline.hpp" #include "memory/genOopClosures.inline.hpp"
#include "memory/heapInspection.hpp" #include "memory/heapInspection.hpp"
#include "memory/iterator.inline.hpp" #include "memory/iterator.inline.hpp"
...@@ -322,6 +323,14 @@ InstanceKlass::InstanceKlass(int vtable_len, ...@@ -322,6 +323,14 @@ InstanceKlass::InstanceKlass(int vtable_len,
// Set temporary value until parseClassFile updates it with the real instance // Set temporary value until parseClassFile updates it with the real instance
// size. // size.
set_layout_helper(Klass::instance_layout_helper(0, true)); set_layout_helper(Klass::instance_layout_helper(0, true));
set_jwarmup_recorded(false);
#ifndef PRODUCT
set_initialize_order(-1);
#endif
set_crc32(0);
set_bytes_size(0);
set_source_file_path(NULL);
} }
...@@ -376,6 +385,13 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { ...@@ -376,6 +385,13 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// Need to take this class off the class loader data list. // Need to take this class off the class loader data list.
loader_data->remove_class(this); loader_data->remove_class(this);
if (CompilationWarmUp || CompilationWarmUpRecording) {
if (source_file_path() != NULL) {
source_file_path()->decrement_refcount();
set_source_file_path(NULL);
}
}
// The array_klass for this class is created later, after error handling. // The array_klass for this class is created later, after error handling.
// For class redefinition, we keep the original class so this scratch class // For class redefinition, we keep the original class so this scratch class
// doesn't have an array class. Either way, assert that there is nothing // doesn't have an array class. Either way, assert that there is nothing
...@@ -884,6 +900,9 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { ...@@ -884,6 +900,9 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
this_oop->set_init_state(being_initialized); this_oop->set_init_state(being_initialized);
this_oop->set_init_thread(self); this_oop->set_init_thread(self);
} }
if (CompilationWarmUpRecording) {
JitWarmUp::instance()->recorder()->assign_class_init_order(this_oop());
}
// Step 7 // Step 7
// Next, if C is a class rather than an interface, initialize its super class and super // Next, if C is a class rather than an interface, initialize its super class and super
......
...@@ -208,6 +208,21 @@ class InstanceKlass: public Klass { ...@@ -208,6 +208,21 @@ class InstanceKlass: public Klass {
// if this class is unloaded. // if this class is unloaded.
Symbol* _array_name; Symbol* _array_name;
// if not using JWarmUP, default value is 0
unsigned int _crc32;
// if not using JWarmUP, default value is 0
unsigned int _class_bytes_size;
// CompilationWarmUp eager init support
bool _is_jwarmup_recorded;
// source file path, e.g. /home/xxx/liba.jar
Symbol* _source_file_path;
#ifndef PRODUCT
int _initialize_order;
#endif
// Number of heapOopSize words used by non-static fields in this klass // Number of heapOopSize words used by non-static fields in this klass
// (including inherited fields but after header_size()). // (including inherited fields but after header_size()).
int _nonstatic_field_size; int _nonstatic_field_size;
...@@ -656,6 +671,23 @@ class InstanceKlass: public Klass { ...@@ -656,6 +671,23 @@ class InstanceKlass: public Klass {
Symbol* array_name() { return _array_name; } Symbol* array_name() { return _array_name; }
void set_array_name(Symbol* name) { assert(_array_name == NULL || name == NULL, "name already created"); _array_name = name; } void set_array_name(Symbol* name) { assert(_array_name == NULL || name == NULL, "name already created"); _array_name = name; }
// JWarmUP support
unsigned int crc32() { return _crc32; }
void set_crc32(unsigned int crc32) { _crc32 = crc32; }
unsigned int bytes_size() { return _class_bytes_size; }
void set_bytes_size(unsigned int size) { _class_bytes_size = size; }
bool is_jwarmup_recorded() { return _is_jwarmup_recorded; }
void set_jwarmup_recorded(bool value) { _is_jwarmup_recorded = value; }
Symbol* source_file_path() { return _source_file_path; }
void set_source_file_path(Symbol* value) { _source_file_path = value; }
#ifndef PRODUCT
unsigned int initialize_order() { return _initialize_order; }
void set_initialize_order(int order) { _initialize_order = order; }
#endif
// nonstatic oop-map blocks // nonstatic oop-map blocks
static int nonstatic_oop_map_size(unsigned int oop_map_count) { static int nonstatic_oop_map_size(unsigned int oop_map_count) {
return oop_map_count * OopMapBlock::size_in_words(); return oop_map_count * OopMapBlock::size_in_words();
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "interpreter/bytecodes.hpp" #include "interpreter/bytecodes.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp" #include "interpreter/oopMapCache.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/gcLocker.hpp" #include "memory/gcLocker.hpp"
#include "memory/generation.hpp" #include "memory/generation.hpp"
#include "memory/heapInspection.hpp" #include "memory/heapInspection.hpp"
...@@ -96,6 +97,13 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) { ...@@ -96,6 +97,13 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) {
clear_method_counters(); clear_method_counters();
set_vtable_index(Method::garbage_vtable_index); set_vtable_index(Method::garbage_vtable_index);
set_first_invoke_init_order(INVALID_FIRST_INVOKE_INIT_ORDER);
set_compiled_by_jwarmup(false);
#ifndef PRODUCT
set_deopted_by_jwarmup(false);
#endif
// Fix and bury in Method* // Fix and bury in Method*
set_interpreter_entry(NULL); // sets i2i entry and from_int set_interpreter_entry(NULL); // sets i2i entry and from_int
set_adapter_entry(NULL); set_adapter_entry(NULL);
......
...@@ -136,6 +136,12 @@ class Method : public Metadata { ...@@ -136,6 +136,12 @@ class Method : public Metadata {
nmethod* volatile _code; // Points to the corresponding piece of native code nmethod* volatile _code; // Points to the corresponding piece of native code
volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
int _first_invoke_init_order; // record class initialize order when this method first been invoked
bool _compiled_by_jwarmup;
#ifndef PRODUCT
bool _deopted_by_jwarmup;
#endif
// Constructor // Constructor
Method(ConstMethod* xconst, AccessFlags access_flags, int size); Method(ConstMethod* xconst, AccessFlags access_flags, int size);
public: public:
...@@ -202,6 +208,21 @@ class Method : public Metadata { ...@@ -202,6 +208,21 @@ class Method : public Metadata {
return constMethod()->type_annotations(); return constMethod()->type_annotations();
} }
int first_invoke_init_order() { return _first_invoke_init_order; }
void set_first_invoke_init_order(int value) { _first_invoke_init_order = value; }
bool compiled_by_jwarmup() { return _compiled_by_jwarmup; }
void set_compiled_by_jwarmup(bool value) { _compiled_by_jwarmup = value; }
#ifndef PRODUCT
bool deopted_by_jwarmup() { return _deopted_by_jwarmup; }
void set_deopted_by_jwarmup(bool value) { _deopted_by_jwarmup = value; }
#endif
static ByteSize first_invoke_init_order_offset() {
return byte_offset_of(Method, _first_invoke_init_order);
}
// Helper routine: get klass name + "." + method name + signature as // Helper routine: get klass name + "." + method name + signature as
// C string, for the purpose of providing more useful NoSuchMethodErrors // C string, for the purpose of providing more useful NoSuchMethodErrors
// and fatal error handling. The string is allocated in resource // and fatal error handling. The string is allocated in resource
......
...@@ -282,6 +282,8 @@ class ProfileData : public ResourceObj { ...@@ -282,6 +282,8 @@ class ProfileData : public ResourceObj {
friend class TypeEntries; friend class TypeEntries;
friend class ReturnTypeEntry; friend class ReturnTypeEntry;
friend class TypeStackSlotEntries; friend class TypeStackSlotEntries;
friend class ProfileRecorder;
friend class PreloadJitInfo;
private: private:
#ifndef PRODUCT #ifndef PRODUCT
enum { enum {
......
...@@ -207,7 +207,8 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) { ...@@ -207,7 +207,8 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
if (!UseInlineCaches || !ImplicitNullChecks || !os::zero_page_read_protected() || if (!UseInlineCaches || !ImplicitNullChecks || !os::zero_page_read_protected() ||
((ImplicitNullCheckThreshold > 0) && caller_md && ((ImplicitNullCheckThreshold > 0) && caller_md &&
(caller_md->trap_count(Deoptimization::Reason_null_check) (caller_md->trap_count(Deoptimization::Reason_null_check)
>= (uint)ImplicitNullCheckThreshold))) { >= (uint)ImplicitNullCheckThreshold)) ||
(CompilationWarmUp && kit.C->env()->task()->is_jwarmup_compilation())) {
// Make an explicit receiver null_check as part of this call. // Make an explicit receiver null_check as part of this call.
// Since we share a map with the caller, his JVMS gets adjusted. // Since we share a map with the caller, his JVMS gets adjusted.
receiver = kit.null_check_receiver_before_call(method()); receiver = kit.null_check_receiver_before_call(method());
......
...@@ -728,6 +728,14 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -728,6 +728,14 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
print_compile_messages(); print_compile_messages();
if (CompilationWarmUp) {
bool fields_resolved = ci_env->check_method_fields_all_resolved(method());
if (!fields_resolved) {
_failure_reason = "fields needed by method are not all resolved";
return;
}
}
_ilt = InlineTree::build_inline_tree_root(); _ilt = InlineTree::build_inline_tree_root();
// Even if NO memory addresses are used, MergeMem nodes must have at least 1 slice // Even if NO memory addresses are used, MergeMem nodes must have at least 1 slice
......
...@@ -2749,9 +2749,14 @@ bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) { ...@@ -2749,9 +2749,14 @@ bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) {
&& obj != null() // And not the -Xcomp stupid case? && obj != null() // And not the -Xcomp stupid case?
&& !too_many_traps(Deoptimization::Reason_null_check) && !too_many_traps(Deoptimization::Reason_null_check)
) { ) {
if (data == NULL) bool compiledByWarmUp = CompilationWarmUp && this->C->env()->task()->is_jwarmup_compilation();
if (data == NULL) {
if (compiledByWarmUp) {
return false;
}
// Edge case: no mature data. Be optimistic here. // Edge case: no mature data. Be optimistic here.
return true; return true;
}
// If the profile has not seen a null, assume it won't happen. // If the profile has not seen a null, assume it won't happen.
assert(java_bc() == Bytecodes::_checkcast || assert(java_bc() == Bytecodes::_checkcast ||
java_bc() == Bytecodes::_instanceof || java_bc() == Bytecodes::_instanceof ||
...@@ -2821,6 +2826,12 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj, ...@@ -2821,6 +2826,12 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
bool not_null) { bool not_null) {
// type == NULL if profiling tells us this object is always null // type == NULL if profiling tells us this object is always null
if (type != NULL) { if (type != NULL) {
if (CompilationWarmUp) {
if (this->C->env()->task()->is_jwarmup_compilation()) {
return obj;
}
}
Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check;
Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check;
if (!too_many_traps(null_reason) && !too_many_recompiles(null_reason) && if (!too_many_traps(null_reason) && !too_many_recompiles(null_reason) &&
......
...@@ -96,6 +96,9 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo ...@@ -96,6 +96,9 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
// mechanism exists (yet) to set the switches at an os_cpu level // mechanism exists (yet) to set the switches at an os_cpu level
if( !ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(0)) return; if( !ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(0)) return;
// to reduce deoptimization, disable implicit_null_check for jwarmup compilation
if (CompilationWarmUp && this->C->env()->task()->is_jwarmup_compilation()) return;
// Make sure the ptr-is-null path appears to be uncommon! // Make sure the ptr-is-null path appears to be uncommon!
float f = block->end()->as_MachIf()->_prob; float f = block->end()->as_MachIf()->_prob;
if( proj->Opcode() == Op_IfTrue ) f = 1.0f - f; if( proj->Opcode() == Op_IfTrue ) f = 1.0f - f;
......
...@@ -35,8 +35,10 @@ ...@@ -35,8 +35,10 @@
#include "classfile/systemDictionaryShared.hpp" #include "classfile/systemDictionaryShared.hpp"
#endif #endif
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "gc_interface/collectedHeap.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/bytecode.hpp" #include "interpreter/bytecode.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "memory/referenceType.hpp" #include "memory/referenceType.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
...@@ -51,6 +53,7 @@ ...@@ -51,6 +53,7 @@
#include "prims/nativeLookup.hpp" #include "prims/nativeLookup.hpp"
#include "prims/privilegedStack.hpp" #include "prims/privilegedStack.hpp"
#include "runtime/arguments.hpp" #include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/dtraceJSDT.hpp" #include "runtime/dtraceJSDT.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/init.hpp" #include "runtime/init.hpp"
...@@ -4682,3 +4685,66 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i ...@@ -4682,3 +4685,66 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
info->is_attachable = AttachListener::is_attach_supported(); info->is_attachable = AttachListener::is_attach_supported();
} }
JVM_END JVM_END
JVM_ENTRY(void, JVM_NotifyApplicationStartUpIsDone(JNIEnv* env, jclass clz))
{
JVMWrapper("JVM_NotifyApplicationStartUpIsDone");
if (!CompilationWarmUp) {
tty->print_cr("CompilationWarmUp is off, "
"notifyApplicationStartUpIsDone is invalid");
return;
}
Handle mirror(THREAD, JNIHandles::resolve_non_null(clz));
assert(mirror() != NULL, "sanity check");
Klass* k = java_lang_Class::as_Klass(mirror());
Method* dummy_method = k->lookup_method(vmSymbols::jwarmup_dummy_name(), vmSymbols::void_method_signature());
assert(dummy_method != NULL, "Cannot find dummy method in com.alibaba.jwarmup.JWarmUp");
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "sanity check");
jwp->set_dummy_method(dummy_method);
jwp->preloader()->notify_application_startup_is_done();
}
JVM_END
JVM_ENTRY(jboolean, JVM_CheckJWarmUpCompilationIsComplete(JNIEnv *env, jclass ignored))
{
JVMWrapper("JVM_CheckJWarmUpCompilationIsComplete");
if (!CompilationWarmUp) {
tty->print_cr("CompilationWarmUp is off, "
"checkIfCompilationIsComplete is invalid");
return JNI_TRUE;
}
JitWarmUp* jwp = JitWarmUp::instance();
Method* dm = jwp->dummy_method();
assert(dm != NULL, "sanity check");
if (dm->code() != NULL) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
JVM_END
JVM_ENTRY(void, JVM_NotifyJVMDeoptWarmUpMethods(JNIEnv *env, jclass clazz))
{
JVMWrapper("JVM_NotifyJVMDeoptWarmUpMethods");
if (!(CompilationWarmUp && CompilationWarmUpExplicitDeopt)) {
tty->print_cr("CompilationWarmUp or CompilationWarmUpExplicitDeopt is off, "
"notifyJVMDeoptWarmUpMethods is invalid");
return;
}
JitWarmUp* jwp = JitWarmUp::instance();
Method* dm = jwp->dummy_method();
if (dm != NULL && dm->code() != NULL) {
PreloadClassChain* chain = jwp->preloader()->chain();
assert(chain != NULL, "sanity check");
if (chain->notify_deopt_signal()) {
tty->print_cr("JitWarmUp: receive signal to deoptimize warmup methods");
} else {
tty->print_cr("JitWarmUp: deoptimize signal is ignore");
}
} else {
tty->print_cr("JitWarmUp: deoptimize signal is ignore because warmup is not finished");
}
}
JVM_END
...@@ -1705,6 +1705,15 @@ typedef struct JDK1_1InitArgs { ...@@ -1705,6 +1705,15 @@ typedef struct JDK1_1InitArgs {
jint debugPort; jint debugPort;
} JDK1_1InitArgs; } JDK1_1InitArgs;
JNIEXPORT void JNICALL
JVM_NotifyApplicationStartUpIsDone(JNIEnv* env, jclass clz);
JNIEXPORT jboolean JNICALL
JVM_CheckJWarmUpCompilationIsComplete(JNIEnv* env, jclass ignored);
JNIEXPORT void JNICALL
JVM_NotifyJVMDeoptWarmUpMethods(JNIEnv* env, jclass clz);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif /* __cplusplus */ #endif /* __cplusplus */
......
...@@ -1121,6 +1121,288 @@ WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o)) ...@@ -1121,6 +1121,288 @@ WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
os::print_os_info(tty); os::print_os_info(tty);
WB_END WB_END
WB_ENTRY(jobjectArray, WB_GetClassInitOrderList(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_String()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
if (!CompilationWarmUpRecording) {
return NULL;
}
LinkedListImpl<ClassSymbolEntry>* lst =
JitWarmUp::instance()->recorder()->class_init_list();
if (lst == NULL) {
return NULL;
}
jsize size = (jsize)lst->size();
jobjectArray result = NULL;
result = env->NewObjectArray(size, clazz, NULL);
if (result == NULL) {
return result;
}
int idx = 0;
LinkedListNode<ClassSymbolEntry>* node = lst->head();
while(node != NULL) {
ResourceMark rm_inner(THREAD);
Symbol* class_name = node->peek()->class_name();
jobject obj = env->NewStringUTF(class_name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
assert(idx < size, "index out of bound");
env->SetObjectArrayElement(result, idx, obj);
idx++;
node = node->next();
}
return result;
WB_END
WB_ENTRY(jobjectArray, WB_GetClassChainSymbolList(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_String()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
if (!CompilationWarmUp) {
return NULL;
}
PreloadClassChain* chain = JitWarmUp::instance()->preloader()->chain();
if (chain == NULL) {
return NULL;
}
jsize size = (jsize)chain->length();
jobjectArray result = NULL;
result = env->NewObjectArray(size, clazz, NULL);
if (result == NULL) {
return result;
}
for (int i = 0; i < size; i++) {
ResourceMark rm_inner(THREAD);
Symbol* name = chain->at(i)->class_name();
if (name == NULL) {
continue;
}
jobject obj = env->NewStringUTF(name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetObjectArrayElement(result, i, obj);
}
return result;
WB_END
WB_ENTRY(jintArray, WB_GetClassChainStateList(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
CHECK_JNI_EXCEPTION_(env, NULL);
if (!CompilationWarmUp) {
return NULL;
}
PreloadClassChain* chain = JitWarmUp::instance()->preloader()->chain();
if (chain == NULL) {
return NULL;
}
jsize size = (jsize)chain->length();
jintArray result = NULL;
result = env->NewIntArray(size);
if (result == NULL) {
return result;
}
jint* arr = env->GetIntArrayElements(result, NULL);
for (int i = 0; i < size; i++) {
arr[i] = chain->at(i)->state();
}
env->ReleaseIntArrayElements(result, arr, 0);
return result;
WB_END
WB_ENTRY(jobjectArray, WB_GetCompiledMethodList(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_String()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
if (!CompilationWarmUpRecording) {
return NULL;
}
ProfileRecordDictionary* dict = JitWarmUp::instance()->recorder()->dict();
if (dict == NULL) {
return NULL;
}
jsize size = (jsize)dict->count();
jobjectArray result = NULL;
result = env->NewObjectArray(size, clazz, NULL);
if (result == NULL) {
return result;
}
int count = 0;
for (int index = 0; index < dict->table_size(); index++) {
for (ProfileRecorderEntry* entry = dict->bucket(index);
entry != NULL;
entry = entry->next()) {
ResourceMark rm_inner(THREAD);
Symbol* method_name = entry->literal()->name();
jobject obj = env->NewStringUTF(method_name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
if (count >= size) {
break;
}
env->SetObjectArrayElement(result, count, obj);
count++;
}
}
return result;
WB_END
WB_ENTRY(jobjectArray, WB_GetClassListFromLogfile(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_String()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
JitWarmUp* jwp = JitWarmUp::instance();
if (jwp == NULL) {
return NULL;
}
PreloadJitInfo* preloader = jwp->preloader();
if (preloader == NULL) {
return NULL;
}
PreloadClassDictionary* dict = preloader->dict();
if (dict == NULL) {
return NULL;
}
int entry_count = 0;
for (int index = 0; index < dict->table_size(); index++) {
for (PreloadClassEntry* entry = dict->bucket(index);
entry != NULL;
entry = entry->next()) {
entry_count++;
}
}
jsize size = (jsize)entry_count;
jobjectArray result = NULL;
result = env->NewObjectArray(size, clazz, NULL);
if (result == NULL) {
return result;
}
int count = 0;
for (int index = 0; index < dict->table_size(); index++) {
for (PreloadClassEntry* entry = dict->bucket(index);
entry != NULL;
entry = entry->next()) {
ResourceMark rm_inner(THREAD);
Symbol* class_name = entry->literal();
jobject obj = env->NewStringUTF(class_name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
//assert(index < size, "index out of bound");
if (count >= size) {
break;
}
env->SetObjectArrayElement(result, count, obj);
count++;
}
}
return result;
WB_END
WB_ENTRY(jobjectArray, WB_GetMethodListFromLogfile(JNIEnv* env, jobject o))
ResourceMark rm(THREAD);
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_String()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
JitWarmUp* jwp = JitWarmUp::instance();
if (jwp == NULL) {
return NULL;
}
PreloadJitInfo* preloader = jwp->preloader();
if (preloader == NULL) {
return NULL;
}
PreloadClassDictionary* dict = preloader->dict();
if (dict == NULL) {
return NULL;
}
jsize size = (jsize)preloader->loaded_count();
jobjectArray result = NULL;
result = env->NewObjectArray(size, clazz, NULL);
if (result == NULL) {
return result;
}
int count = 0;
for (int index = 0; index < dict->table_size(); index++) {
for (PreloadClassEntry* entry = dict->bucket(index);
entry != NULL;
entry = entry->next()) {
for (PreloadClassHolder* holder = entry->head_holder();
holder != NULL;
holder = holder->next()) {
GrowableArray<PreloadMethodHolder*>* arr = holder->method_list();
if (arr == NULL) {
continue;
}
int arr_len = arr->length();
for (int i = 0; i < arr_len; i++ ) {
PreloadMethodHolder* mh = arr->at(i);
ResourceMark rm_inner(THREAD);
Symbol* method_name = mh->name();
jobject obj = env->NewStringUTF(method_name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
//assert(index < size, "index out of bound");
if (count >= size) {
break;
}
env->SetObjectArrayElement(result, count, obj);
count++;
} // end of method list loop
} // end of class holder loop
} // end of entry bucket loop
} // end of table size loop
return result;
WB_END
WB_ENTRY(jboolean, WB_TestFixDanglingPointerInDeopt(JNIEnv* env, jobject o, jstring name))
Handle h_name(THREAD, JNIHandles::resolve(name));
if (h_name.is_null()) return false;
Symbol* sym = java_lang_String::as_symbol(h_name(), CHECK_false);
JitWarmUp* jwp = JitWarmUp::instance();
PreloadClassChain* chain = jwp->preloader()->chain();
assert(chain != NULL, "sanity check");
int index = chain->length() - 1;
PreloadMethodHolder* begin_holder = NULL;
while (index > 0 && begin_holder == NULL) {
PreloadClassChain::PreloadClassChainEntry* entry = chain->at(index);
begin_holder = entry->method_holder();
index--;
}
if (begin_holder == NULL) {
return false;
}
MethodHolderIterator iter(chain, begin_holder, index);
while (*iter != NULL) {
PreloadMethodHolder* pmh = *iter;
if (pmh->name()->fast_compare(sym) == 0) {
if (pmh->resolved_method() != NULL) {
return false;
}
}
iter.next();
}
return true;
WB_END
#define CC (char*) #define CC (char*)
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {
...@@ -1243,6 +1525,20 @@ static JNINativeMethod methods[] = { ...@@ -1243,6 +1525,20 @@ static JNINativeMethod methods[] = {
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo }, {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
{CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment}, {CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment},
{CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob }, {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob },
{CC"getClassListFromLogfile", CC"()[Ljava/lang/String;",
(void*)&WB_GetClassListFromLogfile },
{CC"getMethodListFromLogfile", CC"()[Ljava/lang/String;",
(void*)&WB_GetMethodListFromLogfile },
{CC"getCompiledMethodList", CC"()[Ljava/lang/String;",
(void*)&WB_GetCompiledMethodList },
{CC"getClassChainSymbolList", CC"()[Ljava/lang/String;",
(void*)&WB_GetClassChainSymbolList },
{CC"getClassChainStateList", CC"()[I",
(void*)&WB_GetClassChainStateList },
{CC"testFixDanglingPointerInDeopt",
CC"(Ljava/lang/String;)Z", (void*)&WB_TestFixDanglingPointerInDeopt},
{CC"getClassInitOrderList", CC"()[Ljava/lang/String;",
(void*)&WB_GetClassInitOrderList }
}; };
#undef CC #undef CC
......
...@@ -4026,6 +4026,51 @@ class CommandLineFlags { ...@@ -4026,6 +4026,51 @@ class CommandLineFlags {
"Print JFR log ") \ "Print JFR log ") \
\ \
product(bool, EnableJFR, false, "Enable JFR feature") \ product(bool, EnableJFR, false, "Enable JFR feature") \
\
lp64_product(bool, CompilationWarmUpRecording, false, \
"Collect profiling information for JWarmUP") \
\
lp64_product(bool, CompilationWarmUp, false, \
"Enable CompilationWarmUp from a log file") \
\
manageable(bool, PrintCompilationWarmUpDetail, false, \
"Print detail information for jitWarmUp") \
\
lp64_product(ccstr, CompilationWarmUpLogfile, NULL, \
"Log file name for JWarmUP") \
\
lp64_product(uintx, CompilationWarmUpRecordTime, 0, \
"Sleep time (in seconds) before flushing profling " \
"information to log file ") \
\
lp64_product(uintx, CompilationWarmUpAppID, 0, \
"Application ID written in log file for verification ") \
\
lp64_product(ccstr, CompilationWarmUpExclude, NULL, \
"CompilationWarmUp excluding list ") \
\
lp64_product(bool, CompilationWarmUpExplicitDeopt, false, \
"Deoptimize JWarmUP methods by explicit api") \
\
lp64_product(uintx, CompilationWarmUpDeoptTime, 1200, \
"Sleep time (in seconds) before deoptimizing methods " \
"compiled by JWarmUP ") \
\
diagnostic(uintx, CompilationWarmUpDeoptMinInterval, 5, \
"JWarmUp method deoptimization minimum interval (in seconds)") \
\
diagnostic(uintx, CompilationWarmUpDeoptNumOfMethodsPerIter, 10, \
"The max number of methods marked for " \
"deoptimization per iteration") \
\
diagnostic(bool, CompilationWarmUpResolveClassEagerly, true, \
"resolve class from constant pool eagerly") \
\
lp64_product(bool, DeoptimizeBeforeWarmUp, false, \
"Deoptimize recorded methods before JWarmUP compilation") \
\
lp64_product(intx, CompilationWarmUpRecordMinLevel, 3, \
"Minimal compilation level recorded in JWarmUP recording phase") \
/* /*
* Macros for factoring of globals * Macros for factoring of globals
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "code/icBuffer.hpp" #include "code/icBuffer.hpp"
#include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.hpp"
#include "interpreter/bytecodes.hpp" #include "interpreter/bytecodes.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
...@@ -106,6 +107,14 @@ jint init_globals() { ...@@ -106,6 +107,14 @@ jint init_globals() {
if (status != JNI_OK) if (status != JNI_OK)
return status; return status;
if (CompilationWarmUpRecording) {
JitWarmUp* jwp = JitWarmUp::create_instance();
jwp->init_for_recording();
if (!jwp->is_valid()) {
tty->print_cr("[JitWarmUp] ERROR: init error.");
vm_exit(-1);
}
}
interpreter_init(); // before any methods loaded interpreter_init(); // before any methods loaded
invocationCounter_init(); // before any methods loaded invocationCounter_init(); // before any methods loaded
marksweep_init(); marksweep_init();
...@@ -113,6 +122,14 @@ jint init_globals() { ...@@ -113,6 +122,14 @@ jint init_globals() {
templateTable_init(); templateTable_init();
InterfaceSupport_init(); InterfaceSupport_init();
SharedRuntime::generate_stubs(); SharedRuntime::generate_stubs();
if (CompilationWarmUp) {
JitWarmUp* jwp = JitWarmUp::create_instance();
jwp->init_for_warmup();
if (!jwp->is_valid()) {
tty->print_cr("[JitWarmUp] ERROR: init error.");
vm_exit(-1);
}
}
universe2_init(); // dependent on codeCache_init and stubRoutines_init1 universe2_init(); // dependent on codeCache_init and stubRoutines_init1
referenceProcessor_init(); referenceProcessor_init();
jni_handles_init(); jni_handles_init();
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
Mutex* Patching_lock = NULL; Mutex* Patching_lock = NULL;
Monitor* SystemDictionary_lock = NULL; Monitor* SystemDictionary_lock = NULL;
Mutex* ProfileRecorder_lock = NULL;
Mutex* PreloadClassChain_lock = NULL;
Mutex* JitWarmUpPrint_lock = NULL;
Mutex* PackageTable_lock = NULL; Mutex* PackageTable_lock = NULL;
Mutex* CompiledIC_lock = NULL; Mutex* CompiledIC_lock = NULL;
Mutex* InlineCacheBuffer_lock = NULL; Mutex* InlineCacheBuffer_lock = NULL;
...@@ -218,6 +221,9 @@ void mutex_init() { ...@@ -218,6 +221,9 @@ void mutex_init() {
def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs. def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs.
def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread
def(ProfileRecorder_lock , Mutex , nonleaf+2, true ); // used for JitWarmUp
def(PreloadClassChain_lock , Mutex , max_nonleaf, true ); // used for JitWarmUp
def(JitWarmUpPrint_lock , Mutex , max_nonleaf, true ); // used for JitWarmUp
def(PackageTable_lock , Mutex , leaf, false); def(PackageTable_lock , Mutex , leaf, false);
def(InlineCacheBuffer_lock , Mutex , leaf, true ); def(InlineCacheBuffer_lock , Mutex , leaf, true );
def(VMStatistic_lock , Mutex , leaf, false); def(VMStatistic_lock , Mutex , leaf, false);
......
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
extern Mutex* Patching_lock; // a lock used to guard code patching of compiled code extern Mutex* Patching_lock; // a lock used to guard code patching of compiled code
extern Monitor* SystemDictionary_lock; // a lock on the system dictonary extern Monitor* SystemDictionary_lock; // a lock on the system dictonary
extern Mutex* ProfileRecorder_lock; // a lock on the JWarmUP class ProfileRecorder
extern Mutex* PreloadClassChain_lock; // a lock on the JWarmUP preload class chain
extern Mutex* JitWarmUpPrint_lock; // a lock on the JWarmUP jstack print
extern Mutex* PackageTable_lock; // a lock on the class loader package table extern Mutex* PackageTable_lock; // a lock on the class loader package table
extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access
extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "code/scopeDesc.hpp" #include "code/scopeDesc.hpp"
#include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
...@@ -602,6 +603,15 @@ void SafepointSynchronize::do_cleanup_tasks() { ...@@ -602,6 +603,15 @@ void SafepointSynchronize::do_cleanup_tasks() {
event_safepoint_cleanup_task_commit(event, name); event_safepoint_cleanup_task_commit(event, name);
} }
if (CompilationWarmUp) {
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "sanity check");
PreloadClassChain* chain = jwp->preloader()->chain();
if (chain->should_deoptimize_methods()) {
chain->deoptimize_methods();
}
}
// rotate log files? // rotate log files?
if (UseGCLogFileRotation) { if (UseGCLogFileRotation) {
const char* name = "rotate gc log"; const char* name = "rotate gc log";
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "interpreter/oopMapCache.hpp" #include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp" #include "jvmtifiles/jvmtiEnv.hpp"
#include "jwarmup/jitWarmUp.hpp"
#include "jwarmup/jitWarmUpThread.hpp"
#include "memory/gcLocker.inline.hpp" #include "memory/gcLocker.inline.hpp"
#include "memory/metaspaceShared.hpp" #include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
...@@ -230,6 +232,7 @@ Thread::Thread() { ...@@ -230,6 +232,7 @@ Thread::Thread() {
set_active_handles(NULL); set_active_handles(NULL);
set_free_handle_block(NULL); set_free_handle_block(NULL);
set_last_handle_mark(NULL); set_last_handle_mark(NULL);
set_in_eagerly_loading_class(false);
// This initial value ==> never claimed. // This initial value ==> never claimed.
_oops_do_parity = 0; _oops_do_parity = 0;
...@@ -251,6 +254,7 @@ Thread::Thread() { ...@@ -251,6 +254,7 @@ Thread::Thread() {
_current_pending_monitor = NULL; _current_pending_monitor = NULL;
_current_pending_monitor_is_from_java = true; _current_pending_monitor_is_from_java = true;
_current_waiting_monitor = NULL; _current_waiting_monitor = NULL;
_super_class_resolving_recursive_count = 0;
_num_nested_signal = 0; _num_nested_signal = 0;
omFreeList = NULL ; omFreeList = NULL ;
omFreeCount = 0 ; omFreeCount = 0 ;
...@@ -3689,6 +3693,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { ...@@ -3689,6 +3693,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
BiasedLocking::init(); BiasedLocking::init();
if (CompilationWarmUp) {
JitWarmUp* jwp = JitWarmUp::instance();
assert(jwp != NULL, "sanity check");
jwp->preloader()->jvm_booted_is_done();
}
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
RTMLockingCounters::init(); RTMLockingCounters::init();
#endif #endif
...@@ -4376,6 +4386,11 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format ...@@ -4376,6 +4386,11 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format
st->cr(); st->cr();
} }
CompileBroker::print_compiler_threads_on(st); CompileBroker::print_compiler_threads_on(st);
if (CompilationWarmUpRecording) {
JitWarmUpFlushThread::print_jwarmup_threads_on(st);
st->cr();
}
st->flush(); st->flush();
} }
......
...@@ -211,6 +211,18 @@ class Thread: public ThreadShadow { ...@@ -211,6 +211,18 @@ class Thread: public ThreadShadow {
void leave_signal_handler() { _num_nested_signal--; } void leave_signal_handler() { _num_nested_signal--; }
bool is_inside_signal_handler() const { return _num_nested_signal > 0; } bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
// JWarmUP support
private:
int _super_class_resolving_recursive_count;
bool _in_eagerly_loading_class;
public:
bool in_eagerly_loading_class() { return _in_eagerly_loading_class; }
void set_in_eagerly_loading_class(bool value) { _in_eagerly_loading_class = value; }
void super_class_resolving_recursive_inc() { _super_class_resolving_recursive_count++; }
void super_class_resolving_recursive_dec() { _super_class_resolving_recursive_count--; }
bool in_super_class_resolving() const { return _super_class_resolving_recursive_count > 0; }
private: private:
// Debug tracing // Debug tracing
static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN; static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN;
......
...@@ -390,6 +390,7 @@ template class BasicHashtable<mtGC>; ...@@ -390,6 +390,7 @@ template class BasicHashtable<mtGC>;
template class Hashtable<ConstantPool*, mtClass>; template class Hashtable<ConstantPool*, mtClass>;
template class RehashableHashtable<Symbol*, mtSymbol>; template class RehashableHashtable<Symbol*, mtSymbol>;
template class RehashableHashtable<oopDesc*, mtSymbol>; template class RehashableHashtable<oopDesc*, mtSymbol>;
template class Hashtable<Symbol*, mtInternal>;
template class Hashtable<Symbol*, mtSymbol>; template class Hashtable<Symbol*, mtSymbol>;
template class Hashtable<Klass*, mtClass>; template class Hashtable<Klass*, mtClass>;
template class Hashtable<oop, mtClass>; template class Hashtable<oop, mtClass>;
...@@ -408,3 +409,7 @@ template class BasicHashtable<mtClass>; ...@@ -408,3 +409,7 @@ template class BasicHashtable<mtClass>;
template class BasicHashtable<mtSymbol>; template class BasicHashtable<mtSymbol>;
template class BasicHashtable<mtCode>; template class BasicHashtable<mtCode>;
template class BasicHashtable<mtInternal>; template class BasicHashtable<mtInternal>;
template class Hashtable<Method*, mtInternal>;
template class Hashtable<Method*, mtNone>;
template class BasicHashtable<mtNone>;
template class Hashtable<Symbol*, mtNone>;
...@@ -754,6 +754,39 @@ void fileStream::flush() { ...@@ -754,6 +754,39 @@ void fileStream::flush() {
fflush(_file); fflush(_file);
} }
randomAccessFileStream::randomAccessFileStream() : fileStream() { }
randomAccessFileStream::randomAccessFileStream(const char* file_name)
: fileStream(file_name) { }
randomAccessFileStream::randomAccessFileStream(const char* file_name, const char* opentype)
: fileStream(file_name, opentype) { }
randomAccessFileStream::randomAccessFileStream(FILE* file, bool need_close)
: fileStream(file, need_close) { }
void randomAccessFileStream::write(const char* s, size_t len, long pos) {
assert(pos <= fileSize(), "pos check");
if (_file != NULL) {
long old_pos = ::ftell(_file);
if (old_pos != pos) {
int ret = fseek(pos, SEEK_SET);
assert(ret != -1, "fseek return value check");
}
size_t count = fwrite(s, 1, len, _file);
if (old_pos != pos) {
fseek(old_pos, SEEK_SET);
}
}
}
void randomAccessFileStream::write(const char* s, size_t len) {
if (_file != NULL) {
// Make an unused local variable to avoid warning from gcc 4.x compiler.
size_t count = fwrite(s, 1, len, _file);
}
}
fdStream::fdStream(const char* file_name) { fdStream::fdStream(const char* file_name) {
_fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
_need_close = true; _need_close = true;
......
...@@ -202,7 +202,7 @@ class fileStream : public outputStream { ...@@ -202,7 +202,7 @@ class fileStream : public outputStream {
fileStream(const char* file_name); fileStream(const char* file_name);
fileStream(const char* file_name, const char* opentype); fileStream(const char* file_name, const char* opentype);
fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; } fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; }
~fileStream(); virtual ~fileStream();
bool is_open() const { return _file != NULL; } bool is_open() const { return _file != NULL; }
void set_need_close(bool b) { _need_close = b;} void set_need_close(bool b) { _need_close = b;}
virtual void write(const char* c, size_t len); virtual void write(const char* c, size_t len);
...@@ -214,6 +214,20 @@ class fileStream : public outputStream { ...@@ -214,6 +214,20 @@ class fileStream : public outputStream {
void flush(); void flush();
}; };
class randomAccessFileStream : public fileStream {
public:
randomAccessFileStream();
randomAccessFileStream(const char* file_name);
randomAccessFileStream(const char* file_name, const char* opentype);
randomAccessFileStream(FILE* file, bool need_close = false);
virtual ~randomAccessFileStream() { }
virtual void write(const char* c, size_t len);
// random write support, write data to specified position
virtual void write(const char* c, size_t len, long pos);
int fseek(long offset, int pos) { return ::fseek(_file, offset, pos); }
long ftell() { return ::ftell(_file); }
};
CDS_ONLY(extern fileStream* classlist_file;) CDS_ONLY(extern fileStream* classlist_file;)
// unlike fileStream, fdStream does unbuffered I/O by calling // unlike fileStream, fdStream does unbuffered I/O by calling
......
/*
* Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
* 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. Alibaba 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.
*/
#include "precompiled.hpp"
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/symbolMatcher.hpp"
template <MEMFLAGS F> SymbolMatcher<F>::SymbolMatcher(const char* regexes)
: _patterns(new (ResourceObj::C_HEAP, F)
GrowableArray<SymbolRegexPattern>(4, true, F)) {
assert(regexes != NULL, "illegal regexes");
int size = (int)strlen(regexes);
int pattern_size = 0;
char* pattern_begin = (char*)&regexes[0];
for (int i = 0; i < size + 1; i++) {
if (regexes[i] == ',' || regexes[i] == ';' || i == size) {
add_pattern(pattern_begin, pattern_size);
// reset
pattern_size = -1;
pattern_begin = (char*)&regexes[i+1];
}
pattern_size++;
}
}
template <MEMFLAGS F> SymbolMatcher<F>::~SymbolMatcher() {
delete _patterns;
}
template <MEMFLAGS F> void SymbolMatcher<F>::add_pattern(const char* s, int len) {
if (len == 0) {
return;
}
_patterns->push(SymbolRegexPattern(s, len));
}
template <MEMFLAGS F> bool SymbolMatcher<F>::match(Symbol* symbol) {
ResourceMark rm;
char* s = symbol->as_C_string();
return match(s);
}
template <MEMFLAGS F> bool SymbolMatcher<F>::match(const char* s) {
int regex_num = _patterns->length();
for (int i = 0; i < regex_num; i++) {
const char* regex = _patterns->at(i).origin_regex();
int regex_len = _patterns->at(i).length();
if (pattern_match(regex, regex_len, s)) {
return true;
}
}
return false;
}
template <MEMFLAGS F> bool SymbolMatcher<F>::pattern_match(const char* regex, int regex_len, const char* s) {
int s_len = (int)strlen(s);
if (s_len < regex_len - 1) {
return false;
}
for (int i =0; i < regex_len; i++) {
if (regex[i] == '*') {
return true;
}
if (regex[i] == s[i]) {
continue;
}
if ((regex[i] == '.' && s[i] == '/')
|| (regex[i] == '/' && s[i] == '.')) {
continue;
}
if (regex[i] != '*' && regex[i] != s[i]) {
return false;
}
}
return (s_len == regex_len);
}
void test_symbol_matcher() {
const char* str = NULL;
const char* regexes1 = "com.alibaba.Test,org.*,org.apache.logging*";
SymbolMatcher<mtClass>* matcher1 = new (ResourceObj::C_HEAP, mtClass) SymbolMatcher<mtClass>(regexes1);
str = "com/alibaba/Test";
assert(matcher1->match(str) == true, "");
str = "com/alibaba/Test2";
assert(matcher1->match(str) == false, "");
str = "org/alibaba/Test2";
assert(matcher1->match(str) == true, "");
str = "org/A";
assert(matcher1->match(str) == true, "");
str = "org.";
assert(matcher1->match(str) == true, "");
str = ".";
assert(matcher1->match(str) == false, "");
str = "";
assert(matcher1->match(str) == false, "");
str = "org/apache/logging/Flag";
assert(matcher1->match(str) == true, "");
const char* regexes2 = "com/alibaba.Test,,a.,";
SymbolMatcher<mtClass>* matcher2 = new (ResourceObj::C_HEAP, mtClass) SymbolMatcher<mtClass>(regexes2);
str = "";
assert(matcher2->match(str) == false, "");
str = "com.alibaba.Test";
assert(matcher2->match(str) == true, "");
str = "a.a";
assert(matcher2->match(str) == false, "");
const char* regexes3 = "org.apache.logging*";
SymbolMatcher<mtClass>* matcher3 = new (ResourceObj::C_HEAP, mtClass) SymbolMatcher<mtClass>(regexes3);
str = "org/apache/logging/x";
assert(matcher3->match(str) == true, "");
str = "org/apache/loggingxx";
assert(matcher3->match(str) == true, "");
delete matcher1;
delete matcher2;
}
template class SymbolMatcher<mtClass>;
/*
* Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
* 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. Alibaba 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.
*/
#ifndef SHARED_VM_UTILITIES_SYMBOLMATCHER_HPP
#define SHARED_VM_UTILITIES_SYMBOLMATCHER_HPP
#include "memory/allocation.hpp"
#include "utilities/growableArray.hpp"
class SymbolRegexPattern {
public:
SymbolRegexPattern() { }
SymbolRegexPattern(const char* pattern, int length)
: _pattern(pattern),
_length(length) {
}
~SymbolRegexPattern() { }
const char* origin_regex() { return _pattern; }
void set_origin_regex(char* s) { _pattern = s; }
int length() { return _length; }
void set_length(int value) { _length = value; }
private:
const char* _pattern;
int _length;
};
template <MEMFLAGS F>
class SymbolMatcher : public ResourceObj {
public:
SymbolMatcher(const char* regexes);
virtual ~SymbolMatcher();
GrowableArray<SymbolRegexPattern>* patterns() { return _patterns; }
bool match(Symbol* symbol);
bool match(const char* s);
private:
void add_pattern(const char* src, int len);
bool pattern_match(const char* regex, int regex_len, const char* s);
GrowableArray<SymbolRegexPattern>* _patterns;
};
#endif //SHARED_VM_UTILITIES_SYMBOLMATCHER_HPP
此差异已折叠。
#!/bin/sh
#
# Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
# 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. Alibaba 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.
#
# @test
# @summary test checkIfCompilationIsComplete API
# @run shell TestCheckIfCompilationIsComplete.sh
if [ "${TESTSRC}" = "" ]
then
TESTSRC=${PWD}
echo "TESTSRC not set. Using "${TESTSRC}" as default"
fi
echo "TESTSRC=${TESTSRC}"
## Adding common setup Variables for running shell tests.
. ${TESTSRC}/../test_env.sh
JAVA=${TESTJAVA}${FS}bin${FS}java
JAVAC=${TESTJAVA}${FS}bin${FS}javac
TEST_CLASS=TmpTestCheckIfCompilationComplete
TEST_SOURCE=${TEST_CLASS}.java
###################################################################################
cat > ${TESTCLASSES}${FS}$TEST_SOURCE << EOF
import java.lang.reflect.Method;
import java.util.*;
import com.alibaba.jwarmup.*;
public class TmpTestCheckIfCompilationComplete {
public static String[] aa = new String[0];
public static List<String> ls = new ArrayList<String>();
public String foo() {
for (int i = 0; i < 12000; i++) {
foo2(aa);
}
ls.add("x");
return ls.get(0);
}
public void foo2(String[] a) {
String s = "aa";
if (ls.size() > 100 && a.length < 100) {
ls.clear();
} else {
ls.add(s);
}
}
public static void doBiz() throws Exception {
TmpTestCheckIfCompilationComplete a = new TmpTestCheckIfCompilationComplete();
a.foo();
Thread.sleep(10000);
a.foo();
System.out.println("process is done!");
}
public static void main(String[] args) throws Exception {
if (args[0].equals("recording")) {
doBiz();
} else if (args[0].equals("compilation")) {
JWarmUp.notifyApplicationStartUpIsDone();
while (!JWarmUp.checkIfCompilationIsComplete()) {
Thread.sleep(1000);
}
System.out.println("the JWarmUp Compilation is Done");
System.out.println("Test Done");
}
}
}
EOF
# Do compilation
${JAVAC} -cp ${TESTCLASSES} -d ${TESTCLASSES} ${TESTCLASSES}${FS}$TEST_SOURCE >> /dev/null 2>&1
if [ $? != '0' ]
then
printf "Failed to compile ${TESTCLASSES}${FS}${TEST_SOURCE}"
exit 1
fi
#run Recording Model
${JAVA} -XX:-TieredCompilation -XX:-UseSharedSpaces -XX:+CompilationWarmUpRecording -XX:-ClassUnloading -XX:+PrintCompilation -XX:+PrintCompilationWarmUpDetail -XX:CompilationWarmUpRecordTime=10 -XX:CompilationWarmUpLogfile=./jitwarmup.log -cp ${TESTCLASSES} ${TEST_CLASS} recording > output.txt 2>&1
sleep 1
${JAVA} -XX:-TieredCompilation -XX:-UseSharedSpaces -XX:+CompilationWarmUp -XX:+PrintCompilation -XX:+PrintCompilationWarmUpDetail -XX:CompilationWarmUpLogfile=./jitwarmup.log -cp ${TESTCLASSES} ${TEST_CLASS} compilation > output.txt 2>&1
function assert()
{
i=0
notify_line_no=0
while read line
do
i=$(($i+1))
echo $i
echo $line
if [[ $line =~ "Compilation" ]]; then
notify_line_no=$i
echo "notify_line_no is $notify_line_no"
fi
done < output.txt
if [[ $notify_line_no == $(($i-1)) ]]; then
exit 0
else
exit -1
fi
}
assert
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -213,6 +213,17 @@ public class WhiteBox { ...@@ -213,6 +213,17 @@ public class WhiteBox {
public native int getContextForObject(Object obj); public native int getContextForObject(Object obj);
public native void printRegionInfo(int context); public native void printRegionInfo(int context);
// JitWarmUp
public native String[] getClassInitOrderList();
public native String[] getCompiledMethodList();
public native String[] getClassListFromLogfile();
public native String[] getClassLoadedRecordList();
public native String[] getMethodListFromLogfile();
public native boolean forceCompileInJitWarmUp(Executable method);
public native String[] getClassChainSymbolList();
public native int[] getClassChainStateList();
public native boolean testFixDanglingPointerInDeopt(String name);
// VM flags // VM flags
public native void setBooleanVMFlag(String name, boolean value); public native void setBooleanVMFlag(String name, boolean value);
public native void setIntxVMFlag(String name, long value); public native void setIntxVMFlag(String name, long value);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册