Merge branch 'perf/urgent' into perf/core, to pick up fixes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2017-12-18 18:13:00 +01:00
commit faaf95677f
6 changed files with 180 additions and 37 deletions

View File

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_S390_PERF_REGS_H
#define _ASM_S390_PERF_REGS_H
enum perf_event_s390_regs {
PERF_REG_S390_R0,
PERF_REG_S390_R1,
PERF_REG_S390_R2,
PERF_REG_S390_R3,
PERF_REG_S390_R4,
PERF_REG_S390_R5,
PERF_REG_S390_R6,
PERF_REG_S390_R7,
PERF_REG_S390_R8,
PERF_REG_S390_R9,
PERF_REG_S390_R10,
PERF_REG_S390_R11,
PERF_REG_S390_R12,
PERF_REG_S390_R13,
PERF_REG_S390_R14,
PERF_REG_S390_R15,
PERF_REG_S390_FP0,
PERF_REG_S390_FP1,
PERF_REG_S390_FP2,
PERF_REG_S390_FP3,
PERF_REG_S390_FP4,
PERF_REG_S390_FP5,
PERF_REG_S390_FP6,
PERF_REG_S390_FP7,
PERF_REG_S390_FP8,
PERF_REG_S390_FP9,
PERF_REG_S390_FP10,
PERF_REG_S390_FP11,
PERF_REG_S390_FP12,
PERF_REG_S390_FP13,
PERF_REG_S390_FP14,
PERF_REG_S390_FP15,
PERF_REG_S390_MASK,
PERF_REG_S390_PC,
PERF_REG_S390_MAX
};
#endif /* _ASM_S390_PERF_REGS_H */

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <linux/types.h>
#include <../../../../arch/s390/include/uapi/asm/perf_regs.h>
#include <asm/perf_regs.h>
void perf_regs_load(u64 *regs);

View File

@ -21,6 +21,7 @@ arch/x86/include/asm/cpufeatures.h
arch/arm/include/uapi/asm/perf_regs.h
arch/arm64/include/uapi/asm/perf_regs.h
arch/powerpc/include/uapi/asm/perf_regs.h
arch/s390/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/include/uapi/asm/kvm_perf.h

View File

@ -384,13 +384,13 @@ jvmti_write_code(void *agent, char const *sym,
}
int
jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
jvmti_line_info_t *li, int nr_lines)
jvmti_write_debug_info(void *agent, uint64_t code,
int nr_lines, jvmti_line_info_t *li,
const char * const * file_names)
{
struct jr_code_debug_info rec;
size_t sret, len, size, flen;
size_t sret, len, size, flen = 0;
uint64_t addr;
const char *fn = file;
FILE *fp = agent;
int i;
@ -405,7 +405,9 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
return -1;
}
flen = strlen(file) + 1;
for (i = 0; i < nr_lines; ++i) {
flen += strlen(file_names[i]) + 1;
}
rec.p.id = JIT_CODE_DEBUG_INFO;
size = sizeof(rec);
@ -421,7 +423,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
* file[] : source file name
*/
size += nr_lines * sizeof(struct debug_entry);
size += flen * nr_lines;
size += flen;
rec.p.total_size = size;
/*
@ -452,7 +454,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
if (sret != 1)
goto error;
sret = fwrite_unlocked(fn, flen, 1, fp);
sret = fwrite_unlocked(file_names[i], strlen(file_names[i]) + 1, 1, fp);
if (sret != 1)
goto error;
}

View File

@ -14,6 +14,7 @@ typedef struct {
unsigned long pc;
int line_number;
int discrim; /* discriminator -- 0 for now */
jmethodID methodID;
} jvmti_line_info_t;
void *jvmti_open(void);
@ -22,11 +23,9 @@ int jvmti_write_code(void *agent, char const *symbol_name,
uint64_t vma, void const *code,
const unsigned int code_size);
int jvmti_write_debug_info(void *agent,
uint64_t code,
const char *file,
int jvmti_write_debug_info(void *agent, uint64_t code, int nr_lines,
jvmti_line_info_t *li,
int nr_lines);
const char * const * file_names);
#if defined(__cplusplus)
}

View File

@ -47,6 +47,7 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
tab[lines].pc = (unsigned long)pc;
tab[lines].line_number = loc_tab[i].line_number;
tab[lines].discrim = 0; /* not yet used */
tab[lines].methodID = m;
lines++;
} else {
break;
@ -125,6 +126,99 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **
return JVMTI_ERROR_NONE;
}
static void
copy_class_filename(const char * class_sign, const char * file_name, char * result, size_t max_length)
{
/*
* Assume path name is class hierarchy, this is a common practice with Java programs
*/
if (*class_sign == 'L') {
int j, i = 0;
char *p = strrchr(class_sign, '/');
if (p) {
/* drop the 'L' prefix and copy up to the final '/' */
for (i = 0; i < (p - class_sign); i++)
result[i] = class_sign[i+1];
}
/*
* append file name, we use loops and not string ops to avoid modifying
* class_sign which is used later for the symbol name
*/
for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++)
result[i] = file_name[j];
result[i] = '\0';
} else {
/* fallback case */
size_t file_name_len = strlen(file_name);
strncpy(result, file_name, file_name_len < max_length ? file_name_len : max_length);
}
}
static jvmtiError
get_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char ** buffer)
{
jvmtiError ret;
jclass decl_class;
char *file_name = NULL;
char *class_sign = NULL;
char fn[PATH_MAX];
size_t len;
ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetMethodDeclaringClass", ret);
return ret;
}
ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetSourceFileName", ret);
return ret;
}
ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetClassSignature", ret);
goto free_file_name_error;
}
copy_class_filename(class_sign, file_name, fn, PATH_MAX);
len = strlen(fn);
*buffer = malloc((len + 1) * sizeof(char));
if (!*buffer) {
print_error(jvmti, "GetClassSignature", ret);
ret = JVMTI_ERROR_OUT_OF_MEMORY;
goto free_class_sign_error;
}
strcpy(*buffer, fn);
ret = JVMTI_ERROR_NONE;
free_class_sign_error:
(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
free_file_name_error:
(*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
return ret;
}
static jvmtiError
fill_source_filenames(jvmtiEnv *jvmti, int nr_lines,
const jvmti_line_info_t * line_tab,
char ** file_names)
{
int index;
jvmtiError ret;
for (index = 0; index < nr_lines; ++index) {
ret = get_source_filename(jvmti, line_tab[index].methodID, &(file_names[index]));
if (ret != JVMTI_ERROR_NONE)
return ret;
}
return JVMTI_ERROR_NONE;
}
static void JNICALL
compiled_method_load_cb(jvmtiEnv *jvmti,
jmethodID method,
@ -135,16 +229,18 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
const void *compile_info)
{
jvmti_line_info_t *line_tab = NULL;
char ** line_file_names = NULL;
jclass decl_class;
char *class_sign = NULL;
char *func_name = NULL;
char *func_sign = NULL;
char *file_name= NULL;
char *file_name = NULL;
char fn[PATH_MAX];
uint64_t addr = (uint64_t)(uintptr_t)code_addr;
jvmtiError ret;
int nr_lines = 0; /* in line_tab[] */
size_t len;
int output_debug_info = 0;
ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
&decl_class);
@ -158,6 +254,19 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
if (ret != JVMTI_ERROR_NONE) {
warnx("jvmti: cannot get line table for method");
nr_lines = 0;
} else if (nr_lines > 0) {
line_file_names = malloc(sizeof(char*) * nr_lines);
if (!line_file_names) {
warnx("jvmti: cannot allocate space for line table method names");
} else {
memset(line_file_names, 0, sizeof(char*) * nr_lines);
ret = fill_source_filenames(jvmti, nr_lines, line_tab, line_file_names);
if (ret != JVMTI_ERROR_NONE) {
warnx("jvmti: fill_source_filenames failed");
} else {
output_debug_info = 1;
}
}
}
}
@ -181,33 +290,14 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
goto error;
}
/*
* Assume path name is class hierarchy, this is a common practice with Java programs
*/
if (*class_sign == 'L') {
int j, i = 0;
char *p = strrchr(class_sign, '/');
if (p) {
/* drop the 'L' prefix and copy up to the final '/' */
for (i = 0; i < (p - class_sign); i++)
fn[i] = class_sign[i+1];
}
/*
* append file name, we use loops and not string ops to avoid modifying
* class_sign which is used later for the symbol name
*/
for (j = 0; i < (PATH_MAX - 1) && file_name && j < strlen(file_name); j++, i++)
fn[i] = file_name[j];
fn[i] = '\0';
} else {
/* fallback case */
strcpy(fn, file_name);
}
copy_class_filename(class_sign, file_name, fn, PATH_MAX);
/*
* write source line info record if we have it
*/
if (jvmti_write_debug_info(jvmti_agent, addr, fn, line_tab, nr_lines))
warnx("jvmti: write_debug_info() failed");
if (output_debug_info)
if (jvmti_write_debug_info(jvmti_agent, addr, nr_lines, line_tab, (const char * const *) line_file_names))
warnx("jvmti: write_debug_info() failed");
len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2;
{
@ -223,6 +313,13 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
(*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
free(line_tab);
while (line_file_names && (nr_lines > 0)) {
if (line_file_names[nr_lines - 1]) {
free(line_file_names[nr_lines - 1]);
}
nr_lines -= 1;
}
free(line_file_names);
}
static void JNICALL