--- old/src/hotspot/cpu/x86/methodHandles_x86.cpp 2018-07-06 14:15:28.826301749 -0700 +++ new/src/hotspot/cpu/x86/methodHandles_x86.cpp 2018-07-06 14:15:28.262280100 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "jvm.h" #include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" #include "classfile/javaClasses.inline.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" @@ -35,7 +36,7 @@ #include "runtime/frame.inline.hpp" #include "utilities/preserveException.hpp" -#define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ --- old/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp 2018-07-06 14:15:29.770337984 -0700 +++ new/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp 2018-07-06 14:15:29.522328465 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interp_masm.hpp" @@ -48,7 +49,7 @@ #include "utilities/debug.hpp" #include "utilities/macros.hpp" -#define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); @@ -1774,18 +1775,30 @@ address& vep) { assert(t->is_valid() && t->tos_in() == vtos, "illegal template"); Label L; - aep = __ pc(); __ push_ptr(); __ jmp(L); + aep = __ pc(); // atos entry point + __ push_ptr(); + __ jmp(L); #ifndef _LP64 - fep = __ pc(); __ push(ftos); __ jmp(L); - dep = __ pc(); __ push(dtos); __ jmp(L); + fep = __ pc(); // ftos entry point + __ push(ftos); + __ jmp(L); + dep = __ pc(); // dtos entry point + __ push(dtos); + __ jmp(L); #else - fep = __ pc(); __ push_f(xmm0); __ jmp(L); - dep = __ pc(); __ push_d(xmm0); __ jmp(L); + fep = __ pc(); // ftos entry point + __ push_f(xmm0); + __ jmp(L); + dep = __ pc(); // dtos entry point + __ push_d(xmm0); + __ jmp(L); #endif // _LP64 - lep = __ pc(); __ push_l(); __ jmp(L); - bep = cep = sep = - iep = __ pc(); __ push_i(); - vep = __ pc(); + lep = __ pc(); // ltos entry point + __ push_l(); + __ jmp(L); + bep = cep = sep = iep = __ pc(); // [bcsi]tos entry point + __ push_i(); + vep = __ pc(); // vtos entry point __ bind(L); generate_and_dispatch(t); } --- old/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp 2018-07-06 14:15:37.294626793 -0700 +++ new/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp 2018-07-06 14:15:36.218585491 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" @@ -31,7 +32,7 @@ #include "runtime/arguments.hpp" #include "runtime/sharedRuntime.hpp" -#define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> address TemplateInterpreterGenerator::generate_slow_signature_handler() { --- old/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp 2018-07-06 14:15:45.042924200 -0700 +++ new/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp 2018-07-06 14:15:42.694834072 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" @@ -31,7 +32,7 @@ #include "runtime/arguments.hpp" #include "runtime/sharedRuntime.hpp" -#define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> #ifdef _WIN64 address TemplateInterpreterGenerator::generate_slow_signature_handler() { --- old/src/hotspot/cpu/x86/templateTable_x86.cpp 2018-07-06 14:16:01.875570296 -0700 +++ new/src/hotspot/cpu/x86/templateTable_x86.cpp 2018-07-06 14:15:46.774990683 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/interp_masm.hpp" @@ -40,7 +41,7 @@ #include "runtime/synchronizer.hpp" #include "utilities/macros.hpp" -#define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> // Global Register Names static const Register rbcp = LP64_ONLY(r13) NOT_LP64(rsi); --- old/src/hotspot/share/compiler/disassembler.cpp 2018-07-06 14:16:07.083770206 -0700 +++ new/src/hotspot/share/compiler/disassembler.cpp 2018-07-06 14:16:06.379743182 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "asm/macroAssembler.hpp" #include "ci/ciUtilities.hpp" #include "classfile/javaClasses.hpp" #include "code/codeCache.hpp" @@ -36,6 +37,7 @@ #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/resourceHash.hpp" #include CPU_HEADER(depChecker) void* Disassembler::_library = NULL; @@ -49,7 +51,7 @@ static const char decode_instructions_virtual_name[] = "decode_instructions_virtual"; static const char decode_instructions_name[] = "decode_instructions"; static bool use_new_version = true; -#define COMMENT_COLUMN 40 LP64_ONLY(+8) /*could be an option*/ +#define COMMENT_COLUMN 52 LP64_ONLY(+8) /*could be an option*/ #define BYTES_COMMENT ";..." /* funky byte display comment */ bool Disassembler::load_library() { @@ -163,6 +165,7 @@ bool _print_bytes; address _cur_insn; int _bytes_per_line; // arch-specific formatting option + bool _print_file_name; static bool match(const char* event, const char* tag) { size_t taglen = strlen(tag); @@ -191,6 +194,51 @@ void print_insn_bytes(address pc0, address pc); void print_address(address value); + struct SourceFileInfo { + struct Link : public ResourceObj { + const char* file; + int line; + Link* next; + Link(const char* f, int l) : file(f), line(l), next(NULL) {} + }; + Link *head, *tail; + + static unsigned hash(const address& a) { + return primitive_hash
(a); + } + static bool equals(const address& a0, const address& a1) { + return primitive_equals
(a0, a1); + } + void append(const char* file, int line) { + if (tail != NULL && tail->file == file && tail->line == line) { + // Don't print duplicated lines at the same address. This could happen with C + // macros that end up having multiple "__" tokens on the same __LINE__. + return; + } + Link *link = new (ResourceObj::C_HEAP, mtInternal) Link(file, line); + if (head == NULL) { + head = tail = link; + } else { + tail->next = link; + tail = link; + } + } + SourceFileInfo(const char* file, int line) : head(NULL), tail(NULL) { + append(file, line); + } + }; + + typedef ResourceHashtable< + address, SourceFileInfo, + SourceFileInfo::hash, + SourceFileInfo::equals, + 15889, // prime number + ResourceObj::C_HEAP> SourceFileInfoTable; + + static SourceFileInfoTable _src_table; + static const char* _cached_src; + static GrowableArray* _cached_src_lines; + public: decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings(), ptrdiff_t offset = 0); @@ -212,6 +260,7 @@ _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc); // this calls reloc_string_for which calls oop::print_value_on } + print_hook_comments(pc0, _nm != NULL); // follow each complete insn by a nice newline st->cr(); } @@ -221,8 +270,93 @@ outputStream* output() { return _output; } address cur_insn() { return _cur_insn; } const char* options() { return _option_buf; } + static void hook(const char* file, int line, address pc); + void print_hook_comments(address pc, bool newline); }; +decode_env::SourceFileInfoTable decode_env::_src_table; +const char* decode_env::_cached_src = NULL; +GrowableArray* decode_env::_cached_src_lines = NULL; + +void decode_env::hook(const char* file, int line, address pc) { + // For simplication, we never free from this table. It's really not + // necessary as we add to the table only when PrintInterpreter is true, + // which means we are debugging the VM and a little bit of extra + // memory usage doesn't matter. + SourceFileInfo* found = _src_table.get(pc); + if (found != NULL) { + found->append(file, line); + } else { + SourceFileInfo sfi(file, line); + _src_table.put(pc, sfi); // sfi is copied by value + } +} + +void decode_env::print_hook_comments(address pc, bool newline) { + SourceFileInfo* found = _src_table.get(pc); + outputStream* st = output(); + if (found != NULL) { + for (SourceFileInfo::Link *link = found->head; link; link = link->next) { + const char* file = link->file; + int line = link->line; + if (_cached_src == NULL || strcmp(_cached_src, file) != 0) { + FILE* fp; + + if (_cached_src_lines != NULL) { + for (int i=0; i<_cached_src_lines->length(); i++) { + os::free((void*)_cached_src_lines->at(i)); + } + _cached_src_lines->clear(); + } else { + _cached_src_lines = new (ResourceObj::C_HEAP, mtInternal)GrowableArray(0, true); + } + + if ((fp = fopen(file, "r")) == NULL) { + _cached_src = NULL; + return; + } + _cached_src = file; + + char line[500]; // don't write lines that are too long! + while (fgets(line, sizeof(line), fp) != NULL) { + size_t len = strlen(line); + if (len > 0 && line[len-1] == '\n') { + line[len-1] = '\0'; + } + _cached_src_lines->append(os::strdup(line)); + } + fclose(fp); + _print_file_name = true; + } + + if (_print_file_name) { + // We print the file name whenever we switch to a new file, or when + // Disassembler::decode is called to disassemble a new block of code. + _print_file_name = false; + if (newline) { + st->cr(); + } + st->move_to(COMMENT_COLUMN); + st->print(";;@FILE: %s", file); + newline = true; + } + + int index = line - 1; // 1-based line number -> 0-based index. + if (index >= _cached_src_lines->length()) { + // This could happen if source file is mismatched. + } else { + const char* source_line = _cached_src_lines->at(index); + if (newline) { + st->cr(); + } + st->move_to(COMMENT_COLUMN); + st->print(";;%5d: %s", line, source_line); + newline = true; + } + } + } +} + decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c, ptrdiff_t offset) { memset(this, 0, sizeof(*this)); // Beware, this zeroes bits of fields. @@ -237,6 +371,7 @@ _print_pc = true; _print_bytes = false; _bytes_per_line = Disassembler::pd_instruction_alignment(); + _print_file_name= true; // parse the global option string: collect_options(Disassembler::pd_cpu_opts()); @@ -558,3 +693,9 @@ env.decode_instructions(p, end); } + +// To prevent excessive code expansion in the interpreter generator, we +// do not inline this function into Disassembler::hook(). +void Disassembler::_hook(const char* file, int line, MacroAssembler* masm) { + decode_env::hook(file, line, masm->code_section()->end()); +} --- old/src/hotspot/share/compiler/disassembler.hpp 2018-07-06 14:16:08.955842062 -0700 +++ new/src/hotspot/share/compiler/disassembler.hpp 2018-07-06 14:16:08.103809358 -0700 @@ -77,6 +77,17 @@ static void decode(nmethod* nm, outputStream* st = NULL); static void decode(address begin, address end, outputStream* st = NULL, CodeStrings c = CodeStrings(), ptrdiff_t offset = 0); + static void _hook(const char* file, int line, class MacroAssembler* masm); + + // This functions makes it easy to generate comments in the generated + // interpreter code, by riding on the customary __ macro in the interpreter generator. + // See templateTable_x86.cpp for an example. + template inline static T* hook(const char* file, int line, T* masm) { + if (PrintInterpreter) { + _hook(file, line, masm); + } + return masm; + } }; #endif // SHARE_VM_COMPILER_DISASSEMBLER_HPP --- old/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp 2018-07-06 14:16:11.575942631 -0700 +++ new/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp 2018-07-06 14:16:10.931917911 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/interp_masm.hpp" @@ -33,7 +34,7 @@ #ifndef CC_INTERP -# define __ _masm-> +#define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) { _unimplemented_bytecode = NULL;