src/share/vm/ci/ciReplay.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/ci/ciReplay.cpp Fri Dec 27 17:10:19 2013
--- new/src/share/vm/ci/ciReplay.cpp Fri Dec 27 17:10:19 2013
*** 22,31 ****
--- 22,33 ----
*/
#include "precompiled.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciReplay.hpp"
+ #include "ci/ciSymbol.hpp"
+ #include "ci/ciKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "compiler/compileBroker.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
*** 60,69 ****
--- 62,79 ----
int interpreter_throwout_count;
int invocation_counter;
int backedge_counter;
} ciMethodRecord;
+ typedef struct _ciInlineRecord {
+ const char* klass;
+ const char* method;
+ const char* signature;
+ int inline_depth;
+ int bci;
+ } ciInlineRecord;
+
class CompileReplay;
static CompileReplay* replay_state;
class CompileReplay : public StackObj {
private:
*** 72,81 ****
--- 82,94 ----
Handle protection_domain;
Handle loader;
GrowableArray<ciMethodRecord*> ci_method_records;
GrowableArray<ciMethodDataRecord*> ci_method_data_records;
+ // Use pointer because we may need to retirn inline records
+ // without destroying.
+ GrowableArray<ciInlineRecord*>* ci_inline_records;
const char* _error_message;
char* bufptr;
char* buffer;
*** 271,281 ****
--- 284,299 ----
// Parse a valid klass name and look it up
Klass* parse_klass(TRAPS) {
const char* str = parse_escaped_string();
Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL);
if (klass_name != NULL) {
! Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD);
! Klass* k = NULL;
+ if (_iklass != NULL) {
+ k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding();
+ } else {
+ k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD);
+ }
if (HAS_PENDING_EXCEPTION) {
oop throwable = PENDING_EXCEPTION;
java_lang_Throwable::print(throwable, tty);
tty->cr();
report_error(str);
*** 305,314 ****
--- 323,337 ----
}
// Process each line of the replay file executing each command until
// the file ends.
void process(TRAPS) {
+ _imethod = NULL;
+ _iklass = NULL;
+ _entry_bci = 0;
+ _comp_level = 0;
+
line_no = 1;
int pos = 0;
int c = getc(stream);
while(c != EOF) {
if (pos + 1 >= buffer_length) {
*** 394,404 ****
--- 417,482 ----
return false;
}
return true;
}
// compile <klass> <name> <signature> <entry_bci> <comp_level>
+ ciKlass* _iklass;
+ Method* _imethod;
+ int _entry_bci;
+ int _comp_level;
+
+ // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ...
+ void* process_inline(ciMethod* imethod, Method* m, int entry_bci, int comp_level, TRAPS) {
+ _imethod = m;
+ _iklass = imethod->holder();
+ _entry_bci = entry_bci;
+ _comp_level = comp_level;
+ line_no = 1;
+ int pos = 0;
+ int c = getc(stream);
+ while(c != EOF) {
+ if (pos + 1 >= buffer_length) {
+ int newl = buffer_length * 2;
+ char* newb = NEW_RESOURCE_ARRAY(char, newl);
+ memcpy(newb, buffer, pos);
+ buffer = newb;
+ buffer_length = newl;
+ }
+ if (c == '\n') {
+ // null terminate it, reset the pointer and process the line
+ buffer[pos] = '\0';
+ buffer_end = pos++;
+ bufptr = buffer;
+ {
+ char* cmd = parse_string();
+ if (cmd == NULL || strcmp("compile", cmd) != 0) {
+ return NULL;
+ }
+ process_compile(CHECK_NULL);
+ if (ci_inline_records != NULL && ci_inline_records->length() > 0) {
+ return ci_inline_records;
+ }
+ }
+ if (had_error()) {
+ tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
+ tty->print_cr("%s", buffer);
+ return NULL;
+ }
+ pos = 0;
+ buffer_end = 0;
+ line_no++;
+ } else if (c == '\r') {
+ // skip LF
+ } else {
+ buffer[pos++] = c;
+ }
+ c = getc(stream);
+ }
+ return NULL;
+ }
+
+ // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ...
void process_compile(TRAPS) {
Method* method = parse_method(CHECK);
if (had_error()) return;
int entry_bci = parse_int("entry_bci");
const char* comp_level_label = "comp_level";
*** 408,417 ****
--- 486,532 ----
comp_level = CompLevel_full_optimization;
}
if (!is_valid_comp_level(comp_level)) {
return;
}
+ if (_imethod != NULL) {
+ // Replay Inlinig
+ if (entry_bci != _entry_bci || comp_level != _comp_level) {
+ return;
+ }
+ const char* iklass_name = _imethod->method_holder()->name()->as_utf8();
+ const char* imethod_name = _imethod->name()->as_utf8();
+ const char* isignature = _imethod->signature()->as_utf8();
+ const char* klass_name = method->method_holder()->name()->as_utf8();
+ const char* method_name = method->name()->as_utf8();
+ const char* signature = method->signature()->as_utf8();
+ if (strcmp(iklass_name, klass_name) != 0 ||
+ strcmp(imethod_name, method_name) != 0 ||
+ strcmp(isignature, signature) != 0) {
+ return;
+ }
+ }
+ int inline_count = 0;
+ if (parse_tag_and_count("inline", inline_count)) {
+ // Record inlining data
+ ci_inline_records = new GrowableArray<ciInlineRecord*>();
+ for (int i = 0; i < inline_count; i++) {
+ int depth = parse_int("inline_depth");
+ int bci = parse_int("inline_bci");
+ if (had_error()) {
+ break;
+ }
+ Method* inl_method = parse_method(CHECK);
+ if (had_error()) {
+ break;
+ }
+ new_ciInlineRecord(inl_method, bci, depth);
+ }
+ }
+ if (_imethod != NULL) {
+ return; // Replay Inlining
+ }
Klass* k = method->method_holder();
((InstanceKlass*)k)->initialize(THREAD);
if (HAS_PENDING_EXCEPTION) {
oop throwable = PENDING_EXCEPTION;
java_lang_Throwable::print(throwable, tty);
*** 568,577 ****
--- 683,695 ----
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_NameAndType:
case JVM_CONSTANT_Utf8:
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
+ case JVM_CONSTANT_MethodHandle:
+ case JVM_CONSTANT_MethodType:
+ case JVM_CONSTANT_InvokeDynamic:
if (tag != cp->tag_at(i).value()) {
report_error("tag mismatch: wrong class files?");
return;
}
break;
*** 776,785 ****
--- 894,955 ----
}
}
return NULL;
}
+ // Create and initialize a record for a ciInlineRecord
+ ciInlineRecord* new_ciInlineRecord(Method* method, int bci, int depth) {
+ ciInlineRecord* rec = NEW_RESOURCE_OBJ(ciInlineRecord);
+ rec->klass = method->method_holder()->name()->as_utf8();
+ rec->method = method->name()->as_utf8();
+ rec->signature = method->signature()->as_utf8();
+ rec->bci = bci;
+ rec->inline_depth = depth;
+ ci_inline_records->append(rec);
+ return rec;
+ }
+
+ // Lookup inlining data for a ciMethod
+ ciInlineRecord* find_ciInlineRecord(Method* method, int bci, int inline_depth) {
+ if (ci_inline_records != NULL) {
+ const char* klass_name = method->method_holder()->name()->as_utf8();
+ const char* method_name = method->name()->as_utf8();
+ const char* signature = method->signature()->as_utf8();
+ for (int i = 0; i < ci_inline_records->length(); i++) {
+ ciInlineRecord* rec = ci_inline_records->at(i);
+ if ((rec->bci == bci) &&
+ (rec->inline_depth == inline_depth) &&
+ (strcmp(rec->klass, klass_name) == 0) &&
+ (strcmp(rec->method, method_name) == 0) &&
+ (strcmp(rec->signature, signature) == 0)) {
+ return rec;
+ }
+ }
+ }
+ return NULL;
+ }
+
+ static ciInlineRecord* find_ciInlineRecord(GrowableArray<ciInlineRecord*>* records,
+ Method* method, int bci, int inline_depth) {
+ if (records != NULL) {
+ const char* klass_name = method->method_holder()->name()->as_utf8();
+ const char* method_name = method->name()->as_utf8();
+ const char* signature = method->signature()->as_utf8();
+ for (int i = 0; i < records->length(); i++) {
+ ciInlineRecord* rec = records->at(i);
+ if ((rec->bci == bci) &&
+ (rec->inline_depth == inline_depth) &&
+ (strcmp(rec->klass, klass_name) == 0) &&
+ (strcmp(rec->method, method_name) == 0) &&
+ (strcmp(rec->signature, signature) == 0)) {
+ return rec;
+ }
+ }
+ }
+ return NULL;
+ }
+
const char* error_message() {
return _error_message;
}
void reset() {
*** 843,857 ****
--- 1013,1058 ----
Threads::destroy_vm();
vm_exit(exit_code);
}
+ void* ciReplay::load_inline_data(ciMethod* method, int entry_bci, int comp_level) {
+ if (FLAG_IS_DEFAULT(InlineDataFile)) {
+ tty->print_cr("ERROR: no inline replay data file specified (use -XX:InlineDataFile=inline_pid12345.txt).");
+ return NULL;
+ }
+
+ VM_ENTRY_MARK;
+ // Load and parse the replay data
+ CompileReplay rp(InlineDataFile, THREAD);
+ if (!rp.can_replay()) {
+ tty->print_cr("ciReplay: !rp.can_replay()");
+ return NULL;
+ }
+ void* data = rp.process_inline(method, method->get_Method(), entry_bci, comp_level, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ oop throwable = PENDING_EXCEPTION;
+ CLEAR_PENDING_EXCEPTION;
+ java_lang_Throwable::print(throwable, tty);
+ tty->cr();
+ java_lang_Throwable::print_stack_trace(throwable, tty);
+ tty->cr();
+ return NULL;
+ }
+
+ if (rp.had_error()) {
+ tty->print_cr("ciReplay: Failed on %s", rp.error_message());
+ return NULL;
+ }
+ return data;
+ }
+
int ciReplay::replay_impl(TRAPS) {
HandleMark hm;
ResourceMark rm;
// Make sure we don't run with background compilation
! // BackgroundCompilation = false;
if (ReplaySuppressInitializers > 2) {
// ReplaySuppressInitializers > 2 means that we want to allow
// normal VM bootstrap but once we get into the replay itself
// don't allow any intializers to be run.
*** 888,898 ****
--- 1089,1098 ----
exit_code = 1;
}
return exit_code;
}
void ciReplay::initialize(ciMethodData* m) {
if (replay_state == NULL) {
return;
}
*** 937,952 ****
--- 1137,1178 ----
bool ciReplay::should_not_inline(ciMethod* method) {
if (replay_state == NULL) {
return false;
}
VM_ENTRY_MARK;
// ciMethod without a record shouldn't be inlined.
return replay_state->find_ciMethodRecord(method->get_Method()) == NULL;
}
+ bool ciReplay::should_inline(void* data, ciMethod* method, int bci, int inline_depth) {
+ if (data != NULL) {
+ GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data;
+ VM_ENTRY_MARK;
+ // Inline record are ordered by bci and depth.
+ return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) != NULL;
+ } else if (replay_state != NULL) {
+ VM_ENTRY_MARK;
+ // Inline record are ordered by bci and depth.
+ return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) != NULL;
+ }
+ return false;
+ }
+
+ bool ciReplay::should_not_inline(void* data, ciMethod* method, int bci, int inline_depth) {
+ if (data != NULL) {
+ GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data;
+ VM_ENTRY_MARK;
+ // Inline record are ordered by bci and depth.
+ return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) == NULL;
+ } else if (replay_state != NULL) {
+ VM_ENTRY_MARK;
+ // Inline record are ordered by bci and depth.
+ return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) == NULL;
+ }
+ return false;
+ }
void ciReplay::initialize(ciMethod* m) {
if (replay_state == NULL) {
return;
}
src/share/vm/ci/ciReplay.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File