--- a/hotspot/agent/src/os/linux/libproc_impl.c Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/agent/src/os/linux/libproc_impl.c Thu Mar 18 06:36:43 2010 -0700
@@ -174,7 +174,7 @@
return NULL;
}
- newlib->symtab = build_symtab(newlib->fd);
+ newlib->symtab = build_symtab(newlib->fd, libname);
if (newlib->symtab == NULL) {
print_debug("symbol table build failed for %s\n", newlib->name);
}
--- a/hotspot/agent/src/os/linux/symtab.c Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/agent/src/os/linux/symtab.c Thu Mar 18 06:36:43 2010 -0700
@@ -53,8 +53,274 @@
struct hsearch_data *hash_table;
} symtab_t;
-// read symbol table from given fd.
-struct symtab* build_symtab(int fd) {
+
+// Directory that contains global debuginfo files. In theory it
+// should be possible to change this, but in a Java environment there
+// is no obvious place to put a user interface to do it. Maybe this
+// could be set with an environment variable.
+static const char debug_file_directory[] = "/usr/lib/debug";
+
+/* The CRC used in gnu_debuglink, retrieved from
+ http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files. */
+unsigned int gnu_debuglink_crc32 (unsigned int crc,
+ unsigned char *buf, size_t len)
+{
+ static const unsigned int crc32_table[256] =
+ {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d
+ };
+ unsigned char *end;
+
+ crc = ~crc & 0xffffffff;
+ for (end = buf + len; buf < end; ++buf)
+ crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+ return ~crc & 0xffffffff;
+}
+
+/* Open a debuginfo file and check its CRC. If it exists and the CRC
+ matches return its fd. */
+static int
+open_debug_file (const char *pathname, unsigned int crc)
+{
+ unsigned int file_crc = 0;
+ unsigned char buffer[8 * 1024];
+
+ int fd = pathmap_open(pathname);
+
+ if (fd < 0)
+ return -1;
+
+ lseek(fd, 0, SEEK_SET);
+
+ for (;;) {
+ int len = read(fd, buffer, sizeof buffer);
+ if (len <= 0)
+ break;
+ file_crc = gnu_debuglink_crc32(file_crc, buffer, len);
+ }
+
+ if (crc == file_crc)
+ return fd;
+ else {
+ close(fd);
+ return -1;
+ }
+}
+
+/* Find an ELF section. */
+static struct elf_section *find_section_by_name(char *name,
+ int fd,
+ ELF_EHDR *ehdr,
+ ELF_SHDR *shbuf,
+ struct elf_section *scn_cache)
+{
+ ELF_SHDR* cursct = NULL;
+ char *strtab;
+ int cnt;
+
+ if (scn_cache[ehdr->e_shstrndx].c_data == NULL) {
+ if ((scn_cache[ehdr->e_shstrndx].c_data
+ = read_section_data(fd, ehdr, cursct)) == NULL) {
+ return NULL;
+ }
+ }
+
+ strtab = scn_cache[ehdr->e_shstrndx].c_data;
+
+ for (cursct = shbuf, cnt = 0;
+ cnt < ehdr->e_shnum;
+ cnt++, cursct++) {
+ if (strcmp(cursct->sh_name + strtab, name) == 0) {
+ scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct);
+ return &scn_cache[cnt];
+ }
+ }
+
+ return NULL;
+}
+
+/* Look for a ".gnu_debuglink" section. If one exists, try to open a
+ suitable debuginfo file. */
+static int open_file_from_debug_link(const char *name,
+ int fd,
+ ELF_EHDR *ehdr,
+ ELF_SHDR *shbuf,
+ struct elf_section *scn_cache)
+{
+ int debug_fd;
+ struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr,
+ shbuf, scn_cache);
+ if (debug_link == NULL)
+ return -1;
+ char *debug_filename = debug_link->c_data;
+ int offset = (strlen(debug_filename) + 4) >> 2;
+ static unsigned int crc;
+ crc = ((unsigned int*)debug_link->c_data)[offset];
+ char *debug_pathname = malloc(strlen(debug_filename)
+ + strlen(name)
+ + strlen(".debug/")
+ + strlen(debug_file_directory)
+ + 2);
+ strcpy(debug_pathname, name);
+ char *last_slash = strrchr(debug_pathname, '/');
+ if (last_slash == NULL)
+ return -1;
+
+ /* Look in the same directory as the object. */
+ strcpy(last_slash+1, debug_filename);
+
+ debug_fd = open_debug_file(debug_pathname, crc);
+ if (debug_fd >= 0) {
+ free(debug_pathname);
+ return debug_fd;
+ }
+
+ /* Look in a subdirectory named ".debug". */
+ strcpy(last_slash+1, ".debug/");
+ strcat(last_slash, debug_filename);
+
+ debug_fd = open_debug_file(debug_pathname, crc);
+ if (debug_fd >= 0) {
+ free(debug_pathname);
+ return debug_fd;
+ }
+
+ /* Look in /usr/lib/debug + the full pathname. */
+ strcpy(debug_pathname, debug_file_directory);
+ strcat(debug_pathname, name);
+ last_slash = strrchr(debug_pathname, '/');
+ strcpy(last_slash+1, debug_filename);
+
+ debug_fd = open_debug_file(debug_pathname, crc);
+ if (debug_fd >= 0) {
+ free(debug_pathname);
+ return debug_fd;
+ }
+
+ free(debug_pathname);
+ return -1;
+}
+
+static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo);
+
+/* Look for a ".gnu_debuglink" section. If one exists, try to open a
+ suitable debuginfo file and read a symbol table from it. */
+static struct symtab *build_symtab_from_debug_link(const char *name,
+ int fd,
+ ELF_EHDR *ehdr,
+ ELF_SHDR *shbuf,
+ struct elf_section *scn_cache)
+{
+ fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache);
+
+ if (fd >= 0) {
+ struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
+ close(fd);
+ return symtab;
+ }
+
+ return NULL;
+}
+
+// Given a build_id, find the associated debuginfo file
+static char *
+build_id_to_debug_filename (size_t size, unsigned char *data)
+{
+ char *filename, *s;
+
+ filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
+ + 2 * size + (sizeof ".debug" - 1) + 1);
+ s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory);
+ if (size > 0)
+ {
+ size--;
+ s += sprintf (s, "%02x", *data++);
+ }
+ if (size > 0)
+ *s++ = '/';
+ while (size-- > 0)
+ s += sprintf (s, "%02x", *data++);
+ strcpy (s, ".debug");
+
+ return filename;
+}
+
+// Read a build ID note. Try to open any associated debuginfo file
+// and return its symtab
+static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note)
+{
+ int fd;
+ struct symtab *symtab = NULL;
+
+ unsigned char *bytes
+ = (unsigned char*)(note+1) + note->n_namesz;
+ unsigned char *filename
+ = (build_id_to_debug_filename (note->n_descsz, bytes));
+
+ fd = pathmap_open(filename);
+ if (fd >= 0) {
+ symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
+ close(fd);
+ }
+ free(filename);
+
+ return symtab;
+}
+
+// read symbol table from given fd. If try_debuginfo) is true, also
+// try to open an associated debuginfo file
+static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) {
ELF_EHDR ehdr;
char *names = NULL;
struct symtab* symtab = NULL;
@@ -66,6 +332,7 @@
ELF_SHDR* cursct = NULL;
ELF_PHDR* phbuf = NULL;
ELF_PHDR* phdr = NULL;
+ int sym_section = SHT_DYNSYM;
uintptr_t baseaddr = (uintptr_t)-1;
@@ -90,18 +357,23 @@
for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
scn_cache[cnt].c_shdr = cursct;
- if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB) {
+ if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB
+ || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) {
if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
goto quit;
}
}
+ if (cursct->sh_type == SHT_SYMTAB) {
+ // Full symbol table available so use that
+ sym_section = cursct->sh_type;
+ }
cursct++;
}
for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
- if (shdr->sh_type == SHT_SYMTAB) {
+ if (shdr->sh_type == sym_section) {
ELF_SYM *syms;
int j, n, rslt;
size_t size;
@@ -163,6 +435,45 @@
}
}
+ // Look for a separate debuginfo file.
+ if (try_debuginfo) {
+
+ // We prefer a debug symtab to an object's own symtab, so look in
+ // the debuginfo file. We stash a copy of the old symtab in case
+ // there is no debuginfo.
+ struct symtab* prev_symtab = symtab;
+ symtab = NULL;
+
+#ifdef NT_GNU_BUILD_ID
+ // First we look for a Build ID
+ for (cursct = shbuf, cnt = 0;
+ symtab == NULL && cnt < ehdr.e_shnum;
+ cnt++) {
+ if (cursct->sh_type == SHT_NOTE) {
+ Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data;
+ if (note->n_type == NT_GNU_BUILD_ID) {
+ symtab = build_symtab_from_build_id(note);
+ }
+ }
+ cursct++;
+ }
+#endif
+
+ // Then, if that doesn't work, the debug link
+ if (symtab == NULL) {
+ symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf,
+ scn_cache);
+ }
+
+ // If we still haven't found a symtab, use the object's own symtab.
+ if (symtab != NULL) {
+ if (prev_symtab != NULL)
+ destroy_symtab(prev_symtab);
+ } else {
+ symtab = prev_symtab;
+ }
+ }
+
quit:
if (shbuf) free(shbuf);
if (phbuf) free(phbuf);
@@ -177,6 +488,11 @@
return symtab;
}
+struct symtab* build_symtab(int fd, const char *filename) {
+ return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
+}
+
+
void destroy_symtab(struct symtab* symtab) {
if (!symtab) return;
if (symtab->strs) free(symtab->strs);
--- a/hotspot/agent/src/os/linux/symtab.h Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/agent/src/os/linux/symtab.h Thu Mar 18 06:36:43 2010 -0700
@@ -32,7 +32,7 @@
struct symtab;
// build symbol table for a given ELF file descriptor
-struct symtab* build_symtab(int fd);
+struct symtab* build_symtab(int fd, const char *filename);
// destroy the symbol table
void destroy_symtab(struct symtab* symtab);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/make/linux/makefiles/build_vm_def.sh Thu Mar 18 06:36:43 2010 -0700
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+nm --defined-only $* | awk '
+ { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" }
+ '
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug Thu Mar 18 06:36:43 2010 -0700
@@ -290,6 +290,9 @@
# This is for Forte Analyzer profiling support.
AsyncGetCallTrace;
+
+ # INSERT VTABLE SYMBOLS HERE
+
local:
*;
};
--- a/hotspot/make/linux/makefiles/mapfile-vers-product Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product Thu Mar 18 06:36:43 2010 -0700
@@ -285,6 +285,9 @@
# This is for Forte Analyzer profiling support.
AsyncGetCallTrace;
+
+ # INSERT VTABLE SYMBOLS HERE
+
local:
*;
};
--- a/hotspot/make/linux/makefiles/vm.make Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/make/linux/makefiles/vm.make Thu Mar 18 06:36:43 2010 -0700
@@ -121,14 +121,21 @@
vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES))
-mapfile : $(MAPFILE)
+mapfile : $(MAPFILE) vm.def
rm -f $@
- cat $^ > $@
+ awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \
+ { system ("cat vm.def"); } \
+ else \
+ { print $$0 } \
+ }' > $@ < $(MAPFILE)
mapfile_reorder : mapfile $(REORDERFILE)
rm -f $@
cat $^ > $@
+vm.def: $(Res_Files) $(Obj_Files)
+ sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
+
ifeq ($(ZERO_LIBARCH), ppc64)
STATIC_CXX = false
else
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -377,6 +377,16 @@
}
+
+void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
+ __ bind(_entry);
+ __ call(SharedRuntime::deopt_blob()->unpack_with_reexecution());
+ __ delayed()->nop();
+ ce->add_call_info_here(_info);
+ debug_only(__ should_not_reach_here());
+}
+
+
void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
//---------------slow case: call to native-----------------
__ bind(_entry);
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -143,3 +143,6 @@
static bool is_caller_save_register (LIR_Opr reg);
static bool is_caller_save_register (Register r);
+
+ // JSR 292
+ static LIR_Opr& method_handle_invoke_SP_save_opr() { return L7_opr; }
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -378,12 +378,7 @@
int offset = code_offset();
- if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) {
- __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
- __ delayed()->nop();
- }
-
- __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type);
+ __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
__ delayed()->nop();
debug_only(__ stop("should have gone to the caller");)
assert(code_offset() - offset <= exception_handler_size, "overflow");
@@ -685,29 +680,29 @@
}
-void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) {
- __ call(entry, rtype);
+void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
+ __ call(op->addr(), rtype);
// the peephole pass fills the delay slot
}
-void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) {
+void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
RelocationHolder rspec = virtual_call_Relocation::spec(pc());
__ set_oop((jobject)Universe::non_oop_word(), G5_inline_cache_reg);
__ relocate(rspec);
- __ call(entry, relocInfo::none);
+ __ call(op->addr(), relocInfo::none);
// the peephole pass fills the delay slot
}
-void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) {
- add_debug_info_for_null_check_here(info);
+void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
+ add_debug_info_for_null_check_here(op->info());
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
- if (__ is_simm13(vtable_offset) ) {
- __ ld_ptr(G3_scratch, vtable_offset, G5_method);
+ if (__ is_simm13(op->vtable_offset())) {
+ __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
} else {
// This will generate 2 instructions
- __ set(vtable_offset, G5_method);
+ __ set(op->vtable_offset(), G5_method);
// ld_ptr, set_hi, set
__ ld_ptr(G3_scratch, G5_method, G5_method);
}
@@ -717,6 +712,16 @@
}
+void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) {
+ Unimplemented();
+}
+
+
+void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) {
+ Unimplemented();
+}
+
+
// load with 32-bit displacement
int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) {
int load_offset = code_offset();
@@ -1067,7 +1072,8 @@
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
case T_INT:
- case T_FLOAT: {
+ case T_FLOAT:
+ case T_ADDRESS: {
Register src_reg = O7;
int value = c->as_jint_bits();
if (value == 0) {
@@ -1123,7 +1129,8 @@
}
switch (c->type()) {
case T_INT:
- case T_FLOAT: {
+ case T_FLOAT:
+ case T_ADDRESS: {
LIR_Opr tmp = FrameMap::O7_opr;
int value = c->as_jint_bits();
if (value == 0) {
@@ -1195,6 +1202,7 @@
switch (c->type()) {
case T_INT:
+ case T_ADDRESS:
{
jint con = c->as_jint();
if (to_reg->is_single_cpu()) {
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,17 +42,6 @@
}
-void C1_MacroAssembler::method_exit(bool restore_frame) {
- // this code must be structured this way so that the return
- // instruction can be a safepoint.
- if (restore_frame) {
- restore();
- }
- retl();
- delayed()->nop();
-}
-
-
void C1_MacroAssembler::explicit_null_check(Register base) {
Unimplemented();
}
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -677,7 +677,7 @@
__ add(I7, frame::pc_return_offset, Oissuing_pc->after_save());
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address),
- Oissuing_pc->after_save());
+ G2_thread, Oissuing_pc->after_save());
__ verify_not_null_oop(Oexception->after_save());
__ jmp(O0, 0);
__ delayed()->restore();
@@ -985,7 +985,6 @@
void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) {
Label no_deopt;
- Label no_handler;
__ verify_not_null_oop(Oexception);
@@ -1003,9 +1002,14 @@
// whether it had a handler or not we will deoptimize
// by entering the deopt blob with a pending exception.
+#ifdef ASSERT
+ Label done;
__ tst(O0);
- __ br(Assembler::zero, false, Assembler::pn, no_handler);
+ __ br(Assembler::notZero, false, Assembler::pn, done);
__ delayed()->nop();
+ __ stop("should have found address");
+ __ bind(done);
+#endif
// restore the registers that were saved at the beginning and jump to the exception handler.
restore_live_registers(sasm);
@@ -1013,20 +1017,6 @@
__ jmp(O0, 0);
__ delayed()->restore();
- __ bind(no_handler);
- __ mov(L0, I7); // restore return address
-
- // restore exception oop
- __ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), Oexception->after_save());
- __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_oop_offset()));
-
- __ restore();
-
- AddressLiteral exc(Runtime1::entry_for(Runtime1::unwind_exception_id));
- __ jump_to(exc, G4);
- __ delayed()->nop();
-
-
oop_maps->add_gc_map(call_offset, oop_map);
}
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -244,9 +244,10 @@
}
-void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) {
+void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) {
mov(arg_1, O0);
- MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 1);
+ mov(arg_2, O1);
+ MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 2);
}
#endif /* CC_INTERP */
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -121,7 +121,7 @@
bool check_exception = true);
#ifndef CC_INTERP
- void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1);
+ void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2);
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. Blows registers tmp1, tmp2 and tmp3.
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -379,7 +379,7 @@
__ save_frame(0); // compensates for compiler weakness
__ add(O7->after_save(), frame::pc_return_offset, Lscratch); // save the issuing PC
BLOCK_COMMENT("call exception_handler_for_return_address");
- __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), Lscratch);
+ __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Lscratch);
__ mov(O0, handler_reg);
__ restore(); // compensates for compiler weakness
--- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,8 +37,13 @@
enum /* platform_dependent_constants */ {
// %%%%%%%% May be able to shrink this a lot
- code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 20000 // simply increase if too small (assembler will crash if too small)
+ code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
+ code_size2 = 20000 // simply increase if too small (assembler will crash if too small)
+};
+
+// MethodHandles adapters
+enum method_handles_platform_dependent_constants {
+ method_handles_adapters_code_size = 5000
};
class Sparc {
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1822,7 +1822,7 @@
__ add(issuing_pc_addr, Oissuing_pc->after_save()); // likewise set I1 to a value local to the caller
__ super_call_VM_leaf(L7_thread_cache,
CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address),
- Oissuing_pc->after_save());
+ G2_thread, Oissuing_pc->after_save());
// The caller's SP was adjusted upon method entry to accomodate
// the callee's non-argument locals. Undo that adjustment.
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -8460,6 +8460,7 @@
subptr(str1, result); // Restore counter
shrl(str1, 1);
addl(cnt1, str1);
+ decrementl(cnt1);
lea(str1, Address(result, 2)); // Reload string
// Load substr
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -373,6 +373,14 @@
}
+void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
+ __ bind(_entry);
+ __ call(RuntimeAddress(SharedRuntime::deopt_blob()->unpack_with_reexecution()));
+ ce->add_call_info_here(_info);
+ debug_only(__ should_not_reach_here());
+}
+
+
void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
__ bind(_entry);
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,3 +126,6 @@
assert(i >= 0 && i < nof_caller_save_xmm_regs, "out of bounds");
return _caller_save_xmm_regs[i];
}
+
+ // JSR 292
+ static LIR_Opr& method_handle_invoke_SP_save_opr() { return rbp_opr; }
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -436,40 +436,18 @@
int offset = code_offset();
- // if the method does not have an exception handler, then there is
- // no reason to search for one
- if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) {
- // the exception oop and pc are in rax, and rdx
- // no other registers need to be preserved, so invalidate them
- __ invalidate_registers(false, true, true, false, true, true);
-
- // check that there is really an exception
- __ verify_not_null_oop(rax);
-
- // search an exception handler (rax: exception oop, rdx: throwing pc)
- __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));
-
- // if the call returns here, then the exception handler for particular
- // exception doesn't exist -> unwind activation and forward exception to caller
- }
-
- // the exception oop is in rax,
+ // the exception oop and pc are in rax, and rdx
// no other registers need to be preserved, so invalidate them
- __ invalidate_registers(false, true, true, true, true, true);
+ __ invalidate_registers(false, true, true, false, true, true);
// check that there is really an exception
__ verify_not_null_oop(rax);
- // unlock the receiver/klass if necessary
- // rax,: exception
- ciMethod* method = compilation()->method();
- if (method->is_synchronized() && GenerateSynchronizationCode) {
- monitorexit(FrameMap::rbx_oop_opr, FrameMap::rcx_opr, SYNC_header, 0, rax);
- }
-
- // unwind activation and forward exception to caller
- // rax,: exception
- __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));
+ // search an exception handler (rax: exception oop, rdx: throwing pc)
+ __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));
+
+ __ stop("should not reach here");
+
assert(code_offset() - offset <= exception_handler_size, "overflow");
__ end_a_stub();
@@ -495,8 +473,10 @@
int offset = code_offset();
InternalAddress here(__ pc());
+
__ pushptr(here.addr());
__ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
+
assert(code_offset() - offset <= deopt_handler_size, "overflow");
__ end_a_stub();
@@ -593,7 +573,7 @@
}
// Pop the stack before the safepoint code
- __ leave();
+ __ remove_frame(initial_frame_size_in_bytes());
bool result_is_oop = result->is_valid() ? result->is_oop() : false;
@@ -648,7 +628,8 @@
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
- case T_INT: {
+ case T_INT:
+ case T_ADDRESS: {
assert(patch_code == lir_patch_none, "no patching handled here");
__ movl(dest->as_register(), c->as_jint());
break;
@@ -731,6 +712,7 @@
switch (c->type()) {
case T_INT: // fall through
case T_FLOAT:
+ case T_ADDRESS:
__ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
break;
@@ -766,6 +748,7 @@
switch (type) {
case T_INT: // fall through
case T_FLOAT:
+ case T_ADDRESS:
__ movl(as_Address(addr), c->as_jint_bits());
break;
@@ -2738,6 +2721,7 @@
switch (code) {
case lir_static_call:
case lir_optvirtual_call:
+ case lir_dynamic_call:
offset += NativeCall::displacement_offset;
break;
case lir_icvirtual_call:
@@ -2753,30 +2737,41 @@
}
-void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) {
+void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0,
"must be aligned");
- __ call(AddressLiteral(entry, rtype));
- add_call_info(code_offset(), info);
+ __ call(AddressLiteral(op->addr(), rtype));
+ add_call_info(code_offset(), op->info(), op->is_method_handle_invoke());
}
-void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) {
+void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
RelocationHolder rh = virtual_call_Relocation::spec(pc());
__ movoop(IC_Klass, (jobject)Universe::non_oop_word());
assert(!os::is_MP() ||
(__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0,
"must be aligned");
- __ call(AddressLiteral(entry, rh));
- add_call_info(code_offset(), info);
+ __ call(AddressLiteral(op->addr(), rh));
+ add_call_info(code_offset(), op->info(), op->is_method_handle_invoke());
}
/* Currently, vtable-dispatch is only enabled for sparc platforms */
-void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) {
+void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
ShouldNotReachHere();
}
+
+void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) {
+ __ movptr(FrameMap::method_handle_invoke_SP_save_opr()->as_register(), rsp);
+}
+
+
+void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) {
+ __ movptr(rsp, FrameMap::method_handle_invoke_SP_save_opr()->as_register());
+}
+
+
void LIR_Assembler::emit_static_call_stub() {
address call_pc = __ pc();
address stub = __ start_a_stub(call_stub_size);
@@ -2829,10 +2824,12 @@
} else {
unwind_id = Runtime1::handle_exception_nofpu_id;
}
+ __ call(RuntimeAddress(Runtime1::entry_for(unwind_id)));
} else {
- unwind_id = Runtime1::unwind_exception_id;
+ // remove the activation
+ __ remove_frame(initial_frame_size_in_bytes());
+ __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));
}
- __ call(RuntimeAddress(Runtime1::entry_for(unwind_id)));
// enough room for two byte trap
__ nop();
--- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -317,14 +317,6 @@
}
-void C1_MacroAssembler::method_exit(bool restore_frame) {
- if (restore_frame) {
- leave();
- }
- ret(0);
-}
-
-
void C1_MacroAssembler::build_frame(int frame_size_in_bytes) {
// Make sure there is enough stack space for this method's activation.
// Note that we do this before doing an enter(). This matches the
@@ -333,7 +325,7 @@
// between the two compilers.
generate_stack_overflow_check(frame_size_in_bytes);
- enter();
+ push(rbp);
#ifdef TIERED
// c2 leaves fpu stack dirty. Clean it on entry
if (UseSSE < 2 ) {
@@ -344,6 +336,12 @@
}
+void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) {
+ increment(rsp, frame_size_in_bytes); // Does not emit code for frame_size == 0
+ pop(rbp);
+}
+
+
void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
if (C1Breakpoint) int3();
inline_cache_check(receiver, ic_klass);
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -688,18 +688,21 @@
int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc));
oop_maps->add_gc_map(call_offset, oop_map);
- // rax,: handler address or NULL if no handler exists
+ // rax,: handler address
// will be the deopt blob if nmethod was deoptimized while we looked up
// handler regardless of whether handler existed in the nmethod.
// only rax, is valid at this time, all other registers have been destroyed by the runtime call
__ invalidate_registers(false, true, true, true, true, true);
+#ifdef ASSERT
// Do we have an exception handler in the nmethod?
- Label no_handler;
Label done;
__ testptr(rax, rax);
- __ jcc(Assembler::zero, no_handler);
+ __ jcc(Assembler::notZero, done);
+ __ stop("no handler found");
+ __ bind(done);
+#endif
// exception handler found
// patch the return address -> the stub will directly return to the exception handler
@@ -712,36 +715,14 @@
__ leave();
__ ret(0);
- __ bind(no_handler);
- // no exception handler found in this method, so the exception is
- // forwarded to the caller (using the unwind code of the nmethod)
- // there is no need to restore the registers
-
- // restore the real return address that was saved before the RT-call
- __ movptr(real_return_addr, Address(rsp, temp_1_off * VMRegImpl::stack_slot_size));
- __ movptr(Address(rbp, 1*BytesPerWord), real_return_addr);
-
- // load address of JavaThread object for thread-local data
- NOT_LP64(__ get_thread(thread);)
- // restore exception oop into rax, (convention for unwind code)
- __ movptr(exception_oop, Address(thread, JavaThread::exception_oop_offset()));
-
- // clear exception fields in JavaThread because they are no longer needed
- // (fields must be cleared because they are processed by GC otherwise)
- __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD);
- __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD);
-
- // pop the stub frame off
- __ leave();
-
- generate_unwind_exception(sasm);
- __ stop("should not reach here");
}
void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
// incoming parameters
const Register exception_oop = rax;
+ // callee-saved copy of exception_oop during runtime call
+ const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14);
// other registers used in this stub
const Register exception_pc = rdx;
const Register handler_addr = rbx;
@@ -769,38 +750,39 @@
// clear the FPU stack in case any FPU results are left behind
__ empty_FPU_stack();
- // leave activation of nmethod
- __ leave();
- // store return address (is on top of stack after leave)
+ // save exception_oop in callee-saved register to preserve it during runtime calls
+ __ verify_not_null_oop(exception_oop);
+ __ movptr(exception_oop_callee_saved, exception_oop);
+
+ NOT_LP64(__ get_thread(thread);)
+ // Get return address (is on top of stack after leave).
__ movptr(exception_pc, Address(rsp, 0));
- __ verify_oop(exception_oop);
-
- // save exception oop from rax, to stack before call
- __ push(exception_oop);
+ // search the exception handler address of the caller (using the return address)
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc);
+ // rax: exception handler address of the caller
- // search the exception handler address of the caller (using the return address)
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), exception_pc);
- // rax,: exception handler address of the caller
-
- // only rax, is valid at this time, all other registers have been destroyed by the call
- __ invalidate_registers(false, true, true, true, true, true);
+ // Only RAX and RSI are valid at this time, all other registers have been destroyed by the call.
+ __ invalidate_registers(false, true, true, true, false, true);
// move result of call into correct register
__ movptr(handler_addr, rax);
- // restore exception oop in rax, (required convention of exception handler)
- __ pop(exception_oop);
+ // Restore exception oop to RAX (required convention of exception handler).
+ __ movptr(exception_oop, exception_oop_callee_saved);
- __ verify_oop(exception_oop);
+ // verify that there is really a valid exception in rax
+ __ verify_not_null_oop(exception_oop);
// get throwing pc (= return address).
// rdx has been destroyed by the call, so it must be set again
// the pop is also necessary to simulate the effect of a ret(0)
__ pop(exception_pc);
- // verify that that there is really a valid exception in rax,
- __ verify_not_null_oop(exception_oop);
+ // Restore SP from BP if the exception PC is a MethodHandle call site.
+ NOT_LP64(__ get_thread(thread);)
+ __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0);
+ __ cmovptr(Assembler::notEqual, rsp, rbp);
// continue at exception handler (return address removed)
// note: do *not* remove arguments when unwinding the
@@ -808,9 +790,9 @@
// all arguments on the stack when entering the
// runtime to determine the exception handler
// (GC happens at call site with arguments!)
- // rax,: exception oop
+ // rax: exception oop
// rdx: throwing pc
- // rbx,: exception handler
+ // rbx: exception handler
__ jmp(handler_addr);
}
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,13 +60,13 @@
}
#ifdef ASSERT
-static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
+static void verify_argslot(MacroAssembler* _masm, Register argslot_reg,
const char* error_message) {
// Verify that argslot lies within (rsp, rbp].
Label L_ok, L_bad;
- __ cmpptr(rax_argslot, rbp);
+ __ cmpptr(argslot_reg, rbp);
__ jccb(Assembler::above, L_bad);
- __ cmpptr(rsp, rax_argslot);
+ __ cmpptr(rsp, argslot_reg);
__ jccb(Assembler::below, L_ok);
__ bind(L_bad);
__ stop(error_message);
@@ -178,22 +178,6 @@
// Now move the argslot down, to point to the opened-up space.
__ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
-
- if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) {
- // The caller has specified a bitmask of tags to put into the opened space.
- // This only works when the arg_slots value is an assembly-time constant.
- int constant_arg_slots = arg_slots.as_constant() / stack_move_unit();
- int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
- for (int slot = 0; slot < constant_arg_slots; slot++) {
- BasicType slot_type = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT);
- int slot_offset = Interpreter::stackElementSize() * slot;
- Address tag_addr(rax_argslot, slot_offset + tag_offset);
- __ movptr(tag_addr, frame::tag_for_basic_type(slot_type));
- }
- // Note that the new argument slots are tagged properly but contain
- // garbage at this point. The value portions must be initialized
- // by the caller. (Especially references!)
- }
}
// Helper to remove argument slots from the stack.
@@ -206,18 +190,9 @@
(!arg_slots.is_register() ? rsp : arg_slots.as_register()));
#ifdef ASSERT
- {
- // Verify that [argslot..argslot+size) lies within (rsp, rbp).
- Label L_ok, L_bad;
- __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
- __ cmpptr(rbx_temp, rbp);
- __ jccb(Assembler::above, L_bad);
- __ cmpptr(rsp, rax_argslot);
- __ jccb(Assembler::below, L_ok);
- __ bind(L_bad);
- __ stop("deleted argument(s) must fall within current frame");
- __ bind(L_ok);
- }
+ // Verify that [argslot..argslot+size) lies within (rsp, rbp).
+ __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
+ verify_argslot(_masm, rbx_temp, "deleted argument(s) must fall within current frame");
if (arg_slots.is_register()) {
Label L_ok, L_bad;
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
@@ -321,12 +296,6 @@
Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() );
Address vmarg; // __ argument_address(vmargslot)
- int tag_offset = -1;
- if (TaggedStackInterpreter) {
- tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
- assert(tag_offset = wordSize, "stack grows as expected");
- }
-
const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
if (have_entry(ek)) {
@@ -372,11 +341,8 @@
__ mov(rsp, rsi); // cut the stack back to where the caller started
// Repush the arguments as if coming from the interpreter.
- if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT));
__ push(rdx_code);
- if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
__ push(rcx_fail);
- if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
__ push(rax_want);
Register rbx_method = rbx_temp;
@@ -397,7 +363,6 @@
// Do something that is at least causes a valid throw from the interpreter.
__ bind(no_method);
__ pop(rax_want);
- if (TaggedStackInterpreter) __ pop(rcx_fail);
__ pop(rcx_fail);
__ push(rax_want);
__ push(rcx_fail);
@@ -510,18 +475,10 @@
case _bound_long_direct_mh:
{
bool direct_to_method = (ek >= _bound_ref_direct_mh);
- BasicType arg_type = T_ILLEGAL;
- if (ek == _bound_long_mh || ek == _bound_long_direct_mh) {
- arg_type = T_LONG;
- } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) {
- arg_type = T_INT;
- } else {
- assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref");
- arg_type = T_OBJECT;
- }
- int arg_slots = type2size[arg_type];
- int arg_mask = (arg_type == T_OBJECT ? _INSERT_REF_MASK :
- arg_slots == 1 ? _INSERT_INT_MASK : _INSERT_LONG_MASK);
+ BasicType arg_type = T_ILLEGAL;
+ int arg_mask = _INSERT_NO_MASK;
+ int arg_slots = -1;
+ get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots);
// make room for the new argument:
__ movl(rax_argslot, rcx_bmh_vmargslot);
@@ -660,13 +617,10 @@
}
break;
default:
- assert(false, "");
+ ShouldNotReachHere();
}
- goto finish_int_conversion;
- }
- finish_int_conversion:
- {
+ // Do the requested conversion and store the value.
Register rbx_vminfo = rbx_temp;
__ movl(rbx_vminfo, rcx_amh_conversion);
assert(CONV_VMINFO_SHIFT == 0, "preshifted");
@@ -692,7 +646,7 @@
__ shrl(rdx_temp /*, rcx*/);
__ bind(done);
- __ movl(vmarg, rdx_temp);
+ __ movl(vmarg, rdx_temp); // Store the value.
__ xchgptr(rcx, rbx_vminfo); // restore rcx_recv
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
@@ -715,9 +669,14 @@
switch (ek) {
case _adapter_opt_i2l:
{
+#ifdef _LP64
+ __ movslq(rdx_temp, vmarg1); // Load sign-extended
+ __ movq(vmarg1, rdx_temp); // Store into first slot
+#else
__ movl(rdx_temp, vmarg1);
- __ sarl(rdx_temp, 31); // __ extend_sign()
+ __ sarl(rdx_temp, BitsPerInt - 1); // __ extend_sign()
__ movl(vmarg2, rdx_temp); // store second word
+#endif
}
break;
case _adapter_opt_unboxl:
@@ -727,14 +686,19 @@
int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG);
assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), "");
__ null_check(rdx_temp, value_offset);
+#ifdef _LP64
+ __ movq(rbx_temp, Address(rdx_temp, value_offset));
+ __ movq(vmarg1, rbx_temp);
+#else
__ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt));
__ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt));
__ movl(vmarg1, rbx_temp);
__ movl(vmarg2, rdx_temp);
+#endif
}
break;
default:
- assert(false, "");
+ ShouldNotReachHere();
}
__ movptr(rcx_recv, rcx_mh_vmtarget);
@@ -768,20 +732,9 @@
if (ek == _adapter_opt_f2d) {
__ fld_s(vmarg); // load float to ST0
__ fstp_s(vmarg); // store single
- } else if (!TaggedStackInterpreter) {
+ } else {
__ fld_d(vmarg); // load double to ST0
__ fstp_s(vmarg); // store single
- } else {
- Address vmarg_tag = vmarg.plus_disp(tag_offset);
- Address vmarg2 = vmarg.plus_disp(Interpreter::stackElementSize());
- // vmarg2_tag does not participate in this code
- Register rbx_tag = rbx_temp;
- __ movl(rbx_tag, vmarg_tag); // preserve tag
- __ movl(rdx_temp, vmarg2); // get second word of double
- __ movl(vmarg_tag, rdx_temp); // align with first word
- __ fld_d(vmarg); // load double to ST0
- __ movl(vmarg_tag, rbx_tag); // restore tag
- __ fstp_s(vmarg); // store single
}
#endif //_LP64
@@ -812,19 +765,8 @@
case _adapter_opt_rot_2_up:
case _adapter_opt_rot_2_down:
{
- int rotate = 0, swap_slots = 0;
- switch ((int)ek) {
- case _adapter_opt_swap_1: swap_slots = 1; break;
- case _adapter_opt_swap_2: swap_slots = 2; break;
- case _adapter_opt_rot_1_up: swap_slots = 1; rotate++; break;
- case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break;
- case _adapter_opt_rot_2_up: swap_slots = 2; rotate++; break;
- case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break;
- default: assert(false, "");
- }
-
- // the real size of the move must be doubled if TaggedStackInterpreter:
- int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize );
+ int swap_bytes = 0, rotate = 0;
+ get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate);
// 'argslot' is the position of the first argument to swap
__ movl(rax_argslot, rcx_amh_vmargslot);
@@ -925,8 +867,8 @@
// 'stack_move' is negative number of words to duplicate
Register rdx_stack_move = rdx_temp;
- __ movl(rdx_stack_move, rcx_amh_conversion);
- __ sarl(rdx_stack_move, CONV_STACK_MOVE_SHIFT);
+ __ movl2ptr(rdx_stack_move, rcx_amh_conversion);
+ __ sarptr(rdx_stack_move, CONV_STACK_MOVE_SHIFT);
int argslot0_num = 0;
Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num));
@@ -988,8 +930,8 @@
// 'stack_move' is number of words to drop
Register rdi_stack_move = rdi;
- __ movl(rdi_stack_move, rcx_amh_conversion);
- __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
+ __ movl2ptr(rdi_stack_move, rcx_amh_conversion);
+ __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
remove_arg_slots(_masm, rdi_stack_move,
rax_argslot, rbx_temp, rdx_temp);
@@ -1014,11 +956,7 @@
case _adapter_opt_spread_more:
{
// spread an array out into a group of arguments
- int length_constant = -1;
- switch (ek) {
- case _adapter_opt_spread_0: length_constant = 0; break;
- case _adapter_opt_spread_1: length_constant = 1; break;
- }
+ int length_constant = get_ek_adapter_opt_spread_info(ek);
// find the address of the array argument
__ movl(rax_argslot, rcx_amh_vmargslot);
@@ -1079,8 +1017,8 @@
__ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize()));
// 'stack_move' is negative number of words to insert
Register rdi_stack_move = rdi;
- __ movl(rdi_stack_move, rcx_amh_conversion);
- __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
+ __ movl2ptr(rdi_stack_move, rcx_amh_conversion);
+ __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
Register rsi_temp = rsi_array; // spill this
insert_arg_slots(_masm, rdi_stack_move, -1,
rax_argslot, rbx_temp, rsi_temp);
@@ -1114,10 +1052,6 @@
__ movptr(rbx_temp, Address(rsi_source, 0));
__ movptr(Address(rax_argslot, 0), rbx_temp);
__ addptr(rsi_source, type2aelembytes(elem_type));
- if (TaggedStackInterpreter) {
- __ movptr(Address(rax_argslot, tag_offset),
- frame::tag_for_basic_type(elem_type));
- }
__ addptr(rax_argslot, Interpreter::stackElementSize());
__ cmpptr(rax_argslot, rdx_argslot_limit);
__ jccb(Assembler::less, loop);
@@ -1131,10 +1065,6 @@
__ movptr(rbx_temp, Address(rsi_array, elem_offset));
__ movptr(Address(rax_argslot, slot_offset), rbx_temp);
elem_offset += type2aelembytes(elem_type);
- if (TaggedStackInterpreter) {
- __ movptr(Address(rax_argslot, slot_offset + tag_offset),
- frame::tag_for_basic_type(elem_type));
- }
slot_offset += Interpreter::stackElementSize();
}
}
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -369,7 +369,7 @@
// The pending exception in Thread is converted into a Java-level exception.
//
// Contract with Java-level exception handlers:
- // rax,: exception
+ // rax: exception
// rdx: throwing pc
//
// NOTE: At entry of this stub, exception-pc must be on stack !!
@@ -377,6 +377,12 @@
address generate_forward_exception() {
StubCodeMark mark(this, "StubRoutines", "forward exception");
address start = __ pc();
+ const Register thread = rcx;
+
+ // other registers used in this stub
+ const Register exception_oop = rax;
+ const Register handler_addr = rbx;
+ const Register exception_pc = rdx;
// Upon entry, the sp points to the return address returning into Java
// (interpreted or compiled) code; i.e., the return address becomes the
@@ -389,8 +395,8 @@
#ifdef ASSERT
// make sure this code is only executed if there is a pending exception
{ Label L;
- __ get_thread(rcx);
- __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
+ __ get_thread(thread);
+ __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
__ jcc(Assembler::notEqual, L);
__ stop("StubRoutines::forward exception: no pending exception (1)");
__ bind(L);
@@ -398,33 +404,40 @@
#endif
// compute exception handler into rbx,
- __ movptr(rax, Address(rsp, 0));
+ __ get_thread(thread);
+ __ movptr(exception_pc, Address(rsp, 0));
BLOCK_COMMENT("call exception_handler_for_return_address");
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rax);
- __ mov(rbx, rax);
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc);
+ __ mov(handler_addr, rax);
- // setup rax, & rdx, remove return address & clear pending exception
- __ get_thread(rcx);
- __ pop(rdx);
- __ movptr(rax, Address(rcx, Thread::pending_exception_offset()));
- __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD);
+ // setup rax & rdx, remove return address & clear pending exception
+ __ get_thread(thread);
+ __ pop(exception_pc);
+ __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset()));
+ __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);
#ifdef ASSERT
// make sure exception is set
{ Label L;
- __ testptr(rax, rax);
+ __ testptr(exception_oop, exception_oop);
__ jcc(Assembler::notEqual, L);
__ stop("StubRoutines::forward exception: no pending exception (2)");
__ bind(L);
}
#endif
+ // Verify that there is really a valid exception in RAX.
+ __ verify_oop(exception_oop);
+
+ // Restore SP from BP if the exception PC is a MethodHandle call site.
+ __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0);
+ __ cmovptr(Assembler::notEqual, rsp, rbp);
+
// continue at exception handler (return address removed)
- // rax,: exception
- // rbx,: exception handler
+ // rax: exception
+ // rbx: exception handler
// rdx: throwing pc
- __ verify_oop(rax);
- __ jmp(rbx);
+ __ jmp(handler_addr);
return start;
}
@@ -2263,16 +2276,6 @@
// arraycopy stubs used by compilers
generate_arraycopy_stubs();
- // generic method handle stubs
- if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
- for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
- ek < MethodHandles::_EK_LIMIT;
- ek = MethodHandles::EntryKind(1 + (int)ek)) {
- StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
- MethodHandles::generate_method_handle_stub(_masm, ek);
- }
- }
-
generate_math_stubs();
}
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -466,7 +466,7 @@
BLOCK_COMMENT("call exception_handler_for_return_address");
__ call_VM_leaf(CAST_FROM_FN_PTR(address,
SharedRuntime::exception_handler_for_return_address),
- c_rarg0);
+ r15_thread, c_rarg0);
__ mov(rbx, rax);
// setup rax & rdx, remove return address & clear pending exception
@@ -3009,16 +3009,6 @@
// arraycopy stubs used by compilers
generate_arraycopy_stubs();
- // generic method handle stubs
- if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
- for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
- ek < MethodHandles::_EK_LIMIT;
- ek = MethodHandles::EntryKind(1 + (int)ek)) {
- StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
- MethodHandles::generate_method_handle_stub(_masm, ek);
- }
- }
-
generate_math_stubs();
}
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,11 @@
code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
};
+// MethodHandles adapters
+enum method_handles_platform_dependent_constants {
+ method_handles_adapters_code_size = 5000
+};
+
class x86 {
friend class StubGenerator;
friend class VMStructs;
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,14 @@
static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; }
-enum platform_dependent_constants
-{
- code_size1 = 19000, // simply increase if too small (assembler will
- // crash if too small)
- code_size2 = 22000 // simply increase if too small (assembler will
- // crash if too small)
+enum platform_dependent_constants {
+ code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
+ code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
+};
+
+// MethodHandles adapters
+enum method_handles_platform_dependent_constants {
+ method_handles_adapters_code_size = 13000
};
class x86 {
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1550,6 +1550,7 @@
void TemplateInterpreterGenerator::generate_throw_exception() {
// Entry point in previous activation (i.e., if the caller was interpreted)
Interpreter::_rethrow_exception_entry = __ pc();
+ const Register thread = rcx;
// Restore sp to interpreter_frame_last_sp even though we are going
// to empty the expression stack for the exception processing.
@@ -1598,10 +1599,10 @@
// Set the popframe_processing bit in pending_popframe_condition indicating that we are
// currently handling popframe, so that call_VMs that may happen later do not trigger new
// popframe handling cycles.
- __ get_thread(rcx);
- __ movl(rdx, Address(rcx, JavaThread::popframe_condition_offset()));
+ __ get_thread(thread);
+ __ movl(rdx, Address(thread, JavaThread::popframe_condition_offset()));
__ orl(rdx, JavaThread::popframe_processing_bit);
- __ movl(Address(rcx, JavaThread::popframe_condition_offset()), rdx);
+ __ movl(Address(thread, JavaThread::popframe_condition_offset()), rdx);
{
// Check to see whether we are returning to a deoptimized frame.
@@ -1629,8 +1630,8 @@
__ subptr(rdi, rax);
__ addptr(rdi, wordSize);
// Save these arguments
- __ get_thread(rcx);
- __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), rcx, rax, rdi);
+ __ get_thread(thread);
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), thread, rax, rdi);
__ remove_activation(vtos, rdx,
/* throw_monitor_exception */ false,
@@ -1638,8 +1639,8 @@
/* notify_jvmdi */ false);
// Inform deoptimization that it is responsible for restoring these arguments
- __ get_thread(rcx);
- __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit);
+ __ get_thread(thread);
+ __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit);
// Continue in deoptimization handler
__ jmp(rdx);
@@ -1665,12 +1666,12 @@
// expression stack if necessary.
__ mov(rax, rsp);
__ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
- __ get_thread(rcx);
+ __ get_thread(thread);
// PC must point into interpreter here
- __ set_last_Java_frame(rcx, noreg, rbp, __ pc());
- __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), rcx, rax, rbx);
- __ get_thread(rcx);
- __ reset_last_Java_frame(rcx, true, true);
+ __ set_last_Java_frame(thread, noreg, rbp, __ pc());
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), thread, rax, rbx);
+ __ get_thread(thread);
+ __ reset_last_Java_frame(thread, true, true);
// Restore the last_sp and null it out
__ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD);
@@ -1684,8 +1685,8 @@
}
// Clear the popframe condition flag
- __ get_thread(rcx);
- __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive);
+ __ get_thread(thread);
+ __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive);
__ dispatch_next(vtos);
// end of PopFrame support
@@ -1694,27 +1695,27 @@
// preserve exception over this code sequence
__ pop_ptr(rax);
- __ get_thread(rcx);
- __ movptr(Address(rcx, JavaThread::vm_result_offset()), rax);
+ __ get_thread(thread);
+ __ movptr(Address(thread, JavaThread::vm_result_offset()), rax);
// remove the activation (without doing throws on illegalMonitorExceptions)
__ remove_activation(vtos, rdx, false, true, false);
// restore exception
- __ get_thread(rcx);
- __ movptr(rax, Address(rcx, JavaThread::vm_result_offset()));
- __ movptr(Address(rcx, JavaThread::vm_result_offset()), NULL_WORD);
+ __ get_thread(thread);
+ __ movptr(rax, Address(thread, JavaThread::vm_result_offset()));
+ __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD);
__ verify_oop(rax);
// Inbetween activations - previous activation type unknown yet
// compute continuation point - the continuation point expects
// the following registers set up:
//
- // rax,: exception
+ // rax: exception
// rdx: return address/pc that threw exception
// rsp: expression stack of caller
- // rbp,: rbp, of caller
+ // rbp: rbp, of caller
__ push(rax); // save exception
__ push(rdx); // save return address
- __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rdx);
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, rdx);
__ mov(rbx, rax); // save exception handler
__ pop(rdx); // restore return address
__ pop(rax); // restore exception
@@ -1728,6 +1729,7 @@
//
address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) {
address entry = __ pc();
+ const Register thread = rcx;
__ restore_bcp();
__ restore_locals();
@@ -1735,8 +1737,8 @@
__ empty_FPU_stack();
__ load_earlyret_value(state);
- __ get_thread(rcx);
- __ movptr(rcx, Address(rcx, JavaThread::jvmti_thread_state_offset()));
+ __ get_thread(thread);
+ __ movptr(rcx, Address(thread, JavaThread::jvmti_thread_state_offset()));
const Address cond_addr(rcx, JvmtiThreadState::earlyret_state_offset());
// Clear the earlyret state
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1741,7 +1741,7 @@
__ push(rdx); // save return address
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address,
SharedRuntime::exception_handler_for_return_address),
- rdx);
+ r15_thread, rdx);
__ mov(rbx, rax); // save exception handler
__ pop(rdx); // restore return address
__ pop(rax); // restore exception
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2915,12 +2915,8 @@
__ andl(recv, 0xFF);
// recv count is 0 based?
Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1));
- if (is_invokedynamic) {
- __ lea(recv, recv_addr);
- } else {
- __ movptr(recv, recv_addr);
- __ verify_oop(recv);
- }
+ __ movptr(recv, recv_addr);
+ __ verify_oop(recv);
}
// do null check if needed
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2860,12 +2860,8 @@
__ andl(recv, 0xFF);
if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1));
- if (is_invokedynamic) {
- __ lea(recv, recv_addr);
- } else {
- __ movptr(recv, recv_addr);
- __ verify_oop(recv);
- }
+ __ movptr(recv, recv_addr);
+ __ verify_oop(recv);
}
// do null check if needed
--- a/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,6 +1,6 @@
/*
* Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,11 +29,10 @@
//
define_pd_global(bool, DontYieldALot, false);
+define_pd_global(intx, ThreadStackSize, 1536);
#ifdef _LP64
-define_pd_global(intx, ThreadStackSize, 1536);
define_pd_global(intx, VMThreadStackSize, 1024);
#else
-define_pd_global(intx, ThreadStackSize, 1024);
define_pd_global(intx, VMThreadStackSize, 512);
#endif // _LP64
define_pd_global(intx, SurvivorRatio, 8);
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -222,11 +222,15 @@
}
} else {
LoadField* lf = x->array()->as_LoadField();
- if (lf != NULL && lf->field()->is_constant()) {
- ciObject* c = lf->field()->constant_value().as_object();
- if (c->is_array()) {
- ciArray* array = (ciArray*) c;
- set_constant(array->length());
+ if (lf != NULL) {
+ ciField* field = lf->field();
+ if (field->is_constant() && field->is_static()) {
+ // final static field
+ ciObject* c = field->constant_value().as_object();
+ if (c->is_array()) {
+ ciArray* array = (ciArray*) c;
+ set_constant(array->length());
+ }
}
}
}
--- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -415,6 +415,28 @@
};
+//------------------------------------------------------------------------------
+// DeoptimizeStub
+//
+class DeoptimizeStub : public CodeStub {
+private:
+ CodeEmitInfo* _info;
+
+public:
+ DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {}
+
+ virtual void emit_code(LIR_Assembler* e);
+ virtual CodeEmitInfo* info() const { return _info; }
+ virtual bool is_exception_throw_stub() const { return true; }
+ virtual void visit(LIR_OpVisitState* visitor) {
+ visitor->do_slow_case(_info);
+ }
+#ifndef PRODUCT
+ virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }
+#endif // PRODUCT
+};
+
+
class SimpleExceptionStub: public CodeStub {
private:
LIR_Opr _obj;
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1524,18 +1524,14 @@
code = Bytecodes::_invokespecial;
}
- if (code == Bytecodes::_invokedynamic) {
- BAILOUT("invokedynamic NYI"); // FIXME
- return;
- }
-
// NEEDS_CLEANUP
// I've added the target-is_loaded() test below but I don't really understand
// how klass->is_loaded() can be true and yet target->is_loaded() is false.
// this happened while running the JCK invokevirtual tests under doit. TKR
ciMethod* cha_monomorphic_target = NULL;
ciMethod* exact_target = NULL;
- if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded()) {
+ if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() &&
+ !target->is_method_handle_invoke()) {
Value receiver = NULL;
ciInstanceKlass* receiver_klass = NULL;
bool type_is_exact = false;
@@ -1681,11 +1677,20 @@
CHECK_BAILOUT();
// inlining not successful => standard invoke
- bool is_static = code == Bytecodes::_invokestatic;
+ bool is_loaded = target->is_loaded();
+ bool has_receiver =
+ code == Bytecodes::_invokespecial ||
+ code == Bytecodes::_invokevirtual ||
+ code == Bytecodes::_invokeinterface;
+ bool is_invokedynamic = code == Bytecodes::_invokedynamic;
ValueType* result_type = as_ValueType(target->return_type());
+
+ // We require the debug info to be the "state before" because
+ // invokedynamics may deoptimize.
+ ValueStack* state_before = is_invokedynamic ? state()->copy() : NULL;
+
Values* args = state()->pop_arguments(target->arg_size_no_receiver());
- Value recv = is_static ? NULL : apop();
- bool is_loaded = target->is_loaded();
+ Value recv = has_receiver ? apop() : NULL;
int vtable_index = methodOopDesc::invalid_vtable_index;
#ifdef SPARC
@@ -1723,7 +1728,7 @@
profile_call(recv, target_klass);
}
- Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target);
+ Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before);
// push result
append_split(result);
@@ -2862,20 +2867,18 @@
_initial_state = state_at_entry();
start_block->merge(_initial_state);
- BlockBegin* sync_handler = NULL;
- if (method()->is_synchronized() || _compilation->env()->dtrace_method_probes()) {
- // setup an exception handler to do the unlocking and/or notification
- sync_handler = new BlockBegin(-1);
- sync_handler->set(BlockBegin::exception_entry_flag);
- sync_handler->set(BlockBegin::is_on_work_list_flag);
- sync_handler->set(BlockBegin::default_exception_handler_flag);
-
- ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0);
- XHandler* h = new XHandler(desc);
- h->set_entry_block(sync_handler);
- scope_data()->xhandlers()->append(h);
- scope_data()->set_has_handler();
- }
+ // setup an exception handler to do the unlocking and/or
+ // notification and unwind the frame.
+ BlockBegin* sync_handler = new BlockBegin(-1);
+ sync_handler->set(BlockBegin::exception_entry_flag);
+ sync_handler->set(BlockBegin::is_on_work_list_flag);
+ sync_handler->set(BlockBegin::default_exception_handler_flag);
+
+ ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0);
+ XHandler* h = new XHandler(desc);
+ h->set_entry_block(sync_handler);
+ scope_data()->xhandlers()->append(h);
+ scope_data()->set_has_handler();
// complete graph
_vmap = new ValueMap();
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -259,10 +259,10 @@
}
-void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) {
+void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke) {
// record the safepoint before recording the debug info for enclosing scopes
recorder->add_safepoint(pc_offset, _oop_map->deep_copy());
- _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/);
+ _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, is_method_handle_invoke);
recorder->end_safepoint(pc_offset);
}
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -242,7 +242,7 @@
//Whether we should reexecute this bytecode for deopt
bool should_reexecute();
- void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost) {
+ void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) {
if (caller() != NULL) {
// Order is significant: Must record caller first.
caller()->record_debug_info(recorder, pc_offset, false/*topmost*/);
@@ -252,7 +252,6 @@
DebugToken* monvals = recorder->create_monitor_values(monitors());
// reexecute allowed only for the topmost frame
bool reexecute = topmost ? should_reexecute() : false;
- bool is_method_handle_invoke = false;
bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
}
@@ -303,7 +302,7 @@
int bci() const { return _bci; }
void add_register_oop(LIR_Opr opr);
- void record_debug_info(DebugInformationRecorder* recorder, int pc_offset);
+ void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke = false);
CodeEmitInfo* next() const { return _next; }
void set_next(CodeEmitInfo* next) { _next = next; }
--- a/hotspot/src/share/vm/c1/c1_Instruction.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -334,13 +334,14 @@
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
- int vtable_index, ciMethod* target)
+ int vtable_index, ciMethod* target, ValueStack* state_before)
: StateSplit(result_type)
, _code(code)
, _recv(recv)
, _args(args)
, _vtable_index(vtable_index)
, _target(target)
+ , _state_before(state_before)
{
set_flag(TargetIsLoadedFlag, target->is_loaded());
set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method());
@@ -355,6 +356,9 @@
_signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
if (has_receiver()) {
_signature->append(as_BasicType(receiver()->type()));
+ } else if (is_invokedynamic()) {
+ // Add the synthetic MethodHandle argument to the signature.
+ _signature->append(T_OBJECT);
}
for (int i = 0; i < number_of_arguments(); i++) {
ValueType* t = argument_at(i)->type();
@@ -364,6 +368,13 @@
}
+void Invoke::state_values_do(void f(Value*)) {
+ StateSplit::state_values_do(f);
+ if (state_before() != NULL) state_before()->values_do(f);
+ if (state() != NULL) state()->values_do(f);
+}
+
+
// Implementation of Contant
intx Constant::hash() const {
if (_state == NULL) {
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1134,17 +1134,18 @@
LEAF(Invoke, StateSplit)
private:
- Bytecodes::Code _code;
- Value _recv;
- Values* _args;
- BasicTypeList* _signature;
- int _vtable_index;
- ciMethod* _target;
+ Bytecodes::Code _code;
+ Value _recv;
+ Values* _args;
+ BasicTypeList* _signature;
+ int _vtable_index;
+ ciMethod* _target;
+ ValueStack* _state_before; // Required for deoptimization.
public:
// creation
Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
- int vtable_index, ciMethod* target);
+ int vtable_index, ciMethod* target, ValueStack* state_before);
// accessors
Bytecodes::Code code() const { return _code; }
@@ -1155,6 +1156,7 @@
int vtable_index() const { return _vtable_index; }
BasicTypeList* signature() const { return _signature; }
ciMethod* target() const { return _target; }
+ ValueStack* state_before() const { return _state_before; }
// Returns false if target is not loaded
bool target_is_final() const { return check_flag(TargetIsFinalFlag); }
@@ -1162,6 +1164,9 @@
// Returns false if target is not loaded
bool target_is_strictfp() const { return check_flag(TargetIsStrictfpFlag); }
+ // JSR 292 support
+ bool is_invokedynamic() const { return code() == Bytecodes::_invokedynamic; }
+
// generic
virtual bool can_trap() const { return true; }
virtual void input_values_do(void f(Value*)) {
@@ -1169,6 +1174,7 @@
if (has_receiver()) f(&_recv);
for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i));
}
+ virtual void state_values_do(void f(Value*));
};
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,7 @@
return LIR_OprFact::oopConst(type->as_ObjectType()->encoding());
}
}
- case addressTag: return LIR_OprFact::intConst(type->as_AddressConstant()->value());
+ case addressTag: return LIR_OprFact::addressConst(type->as_AddressConstant()->value());
case intTag : return LIR_OprFact::intConst(type->as_IntConstant()->value());
case floatTag : return LIR_OprFact::floatConst(type->as_FloatConstant()->value());
case longTag : return LIR_OprFact::longConst(type->as_LongConstant()->value());
@@ -89,7 +89,7 @@
LIR_Opr LIR_OprFact::dummy_value_type(ValueType* type) {
switch (type->tag()) {
case objectTag: return LIR_OprFact::oopConst(NULL);
- case addressTag:
+ case addressTag:return LIR_OprFact::addressConst(0);
case intTag: return LIR_OprFact::intConst(0);
case floatTag: return LIR_OprFact::floatConst(0.0);
case longTag: return LIR_OprFact::longConst(0);
@@ -689,9 +689,10 @@
case lir_static_call:
case lir_optvirtual_call:
case lir_icvirtual_call:
- case lir_virtual_call: {
- assert(op->as_OpJavaCall() != NULL, "must be");
- LIR_OpJavaCall* opJavaCall = (LIR_OpJavaCall*)op;
+ case lir_virtual_call:
+ case lir_dynamic_call: {
+ LIR_OpJavaCall* opJavaCall = op->as_OpJavaCall();
+ assert(opJavaCall != NULL, "must be");
if (opJavaCall->_receiver->is_valid()) do_input(opJavaCall->_receiver);
@@ -704,6 +705,7 @@
}
if (opJavaCall->_info) do_info(opJavaCall->_info);
+ if (opJavaCall->is_method_handle_invoke()) do_temp(FrameMap::method_handle_invoke_SP_save_opr());
do_call();
if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result);
@@ -1410,6 +1412,7 @@
// LIR_Address
void LIR_Const::print_value_on(outputStream* out) const {
switch (type()) {
+ case T_ADDRESS:out->print("address:%d",as_jint()); break;
case T_INT: out->print("int:%d", as_jint()); break;
case T_LONG: out->print("lng:%lld", as_jlong()); break;
case T_FLOAT: out->print("flt:%f", as_jfloat()); break;
@@ -1590,6 +1593,7 @@
case lir_optvirtual_call: s = "optvirtual"; break;
case lir_icvirtual_call: s = "icvirtual"; break;
case lir_virtual_call: s = "virtual"; break;
+ case lir_dynamic_call: s = "dynamic"; break;
// LIR_OpArrayCopy
case lir_arraycopy: s = "arraycopy"; break;
// LIR_OpLock
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -85,9 +85,10 @@
void type_check(BasicType t) const { assert(type() == t, "type check"); }
void type_check(BasicType t1, BasicType t2) const { assert(type() == t1 || type() == t2, "type check"); }
+ void type_check(BasicType t1, BasicType t2, BasicType t3) const { assert(type() == t1 || type() == t2 || type() == t3, "type check"); }
public:
- LIR_Const(jint i) { _value.set_type(T_INT); _value.set_jint(i); }
+ LIR_Const(jint i, bool is_address=false) { _value.set_type(is_address?T_ADDRESS:T_INT); _value.set_jint(i); }
LIR_Const(jlong l) { _value.set_type(T_LONG); _value.set_jlong(l); }
LIR_Const(jfloat f) { _value.set_type(T_FLOAT); _value.set_jfloat(f); }
LIR_Const(jdouble d) { _value.set_type(T_DOUBLE); _value.set_jdouble(d); }
@@ -105,7 +106,7 @@
virtual BasicType type() const { return _value.get_type(); }
virtual LIR_Const* as_constant() { return this; }
- jint as_jint() const { type_check(T_INT ); return _value.get_jint(); }
+ jint as_jint() const { type_check(T_INT, T_ADDRESS); return _value.get_jint(); }
jlong as_jlong() const { type_check(T_LONG ); return _value.get_jlong(); }
jfloat as_jfloat() const { type_check(T_FLOAT ); return _value.get_jfloat(); }
jdouble as_jdouble() const { type_check(T_DOUBLE); return _value.get_jdouble(); }
@@ -120,7 +121,7 @@
#endif
- jint as_jint_bits() const { type_check(T_FLOAT, T_INT); return _value.get_jint(); }
+ jint as_jint_bits() const { type_check(T_FLOAT, T_INT, T_ADDRESS); return _value.get_jint(); }
jint as_jint_lo_bits() const {
if (type() == T_DOUBLE) {
return low(jlong_cast(_value.get_jdouble()));
@@ -718,6 +719,7 @@
static LIR_Opr intptrConst(void* p) { return (LIR_Opr)(new LIR_Const(p)); }
static LIR_Opr intptrConst(intptr_t v) { return (LIR_Opr)(new LIR_Const((void*)v)); }
static LIR_Opr illegal() { return (LIR_Opr)-1; }
+ static LIR_Opr addressConst(jint i) { return (LIR_Opr)(new LIR_Const(i, true)); }
static LIR_Opr value_type(ValueType* type);
static LIR_Opr dummy_value_type(ValueType* type);
@@ -840,6 +842,7 @@
, lir_optvirtual_call
, lir_icvirtual_call
, lir_virtual_call
+ , lir_dynamic_call
, end_opJavaCall
, begin_opArrayCopy
, lir_arraycopy
@@ -1052,6 +1055,16 @@
LIR_Opr receiver() const { return _receiver; }
ciMethod* method() const { return _method; }
+ // JSR 292 support.
+ bool is_invokedynamic() const { return code() == lir_dynamic_call; }
+ bool is_method_handle_invoke() const {
+ return
+ is_invokedynamic() // An invokedynamic is always a MethodHandle call site.
+ ||
+ (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() &&
+ method()->name() == ciSymbol::invoke_name());
+ }
+
intptr_t vtable_offset() const {
assert(_code == lir_virtual_call, "only have vtable for real vcall");
return (intptr_t) addr();
@@ -1766,6 +1779,10 @@
intptr_t vtable_offset, LIR_OprList* arguments, CodeEmitInfo* info) {
append(new LIR_OpJavaCall(lir_virtual_call, method, receiver, result, vtable_offset, arguments, info));
}
+ void call_dynamic(ciMethod* method, LIR_Opr receiver, LIR_Opr result,
+ address dest, LIR_OprList* arguments, CodeEmitInfo* info) {
+ append(new LIR_OpJavaCall(lir_dynamic_call, method, receiver, result, dest, arguments, info));
+ }
void get_thread(LIR_Opr result) { append(new LIR_Op0(lir_get_thread, result)); }
void word_align() { append(new LIR_Op0(lir_word_align)); }
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -301,9 +301,9 @@
}
-void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo) {
+void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke) {
flush_debug_info(pc_offset);
- cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset);
+ cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset, is_method_handle_invoke);
if (cinfo->exception_handlers() != NULL) {
compilation()->add_exception_handlers_for_pco(pc_offset, cinfo->exception_handlers());
}
@@ -413,6 +413,12 @@
void LIR_Assembler::emit_call(LIR_OpJavaCall* op) {
verify_oop_map(op->info());
+ // JSR 292
+ // Preserve the SP over MethodHandle call sites.
+ if (op->is_method_handle_invoke()) {
+ preserve_SP(op);
+ }
+
if (os::is_MP()) {
// must align calls sites, otherwise they can't be updated atomically on MP hardware
align_call(op->code());
@@ -423,19 +429,25 @@
switch (op->code()) {
case lir_static_call:
- call(op->addr(), relocInfo::static_call_type, op->info());
+ call(op, relocInfo::static_call_type);
break;
case lir_optvirtual_call:
- call(op->addr(), relocInfo::opt_virtual_call_type, op->info());
+ case lir_dynamic_call:
+ call(op, relocInfo::opt_virtual_call_type);
break;
case lir_icvirtual_call:
- ic_call(op->addr(), op->info());
+ ic_call(op);
break;
case lir_virtual_call:
- vtable_call(op->vtable_offset(), op->info());
+ vtable_call(op);
break;
default: ShouldNotReachHere();
}
+
+ if (op->is_method_handle_invoke()) {
+ restore_SP(op);
+ }
+
#if defined(X86) && defined(TIERED)
// C2 leave fpu stack dirty clean it
if (UseSSE < 2) {
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -82,7 +82,7 @@
Address as_Address_hi(LIR_Address* addr);
// debug information
- void add_call_info(int pc_offset, CodeEmitInfo* cinfo);
+ void add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke = false);
void add_debug_info_for_branch(CodeEmitInfo* info);
void add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo);
void add_debug_info_for_div0_here(CodeEmitInfo* info);
@@ -205,9 +205,13 @@
void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op);
void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result);
- void ic_call(address destination, CodeEmitInfo* info);
- void vtable_call(int vtable_offset, CodeEmitInfo* info);
- void call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info);
+ void call( LIR_OpJavaCall* op, relocInfo::relocType rtype);
+ void ic_call( LIR_OpJavaCall* op);
+ void vtable_call( LIR_OpJavaCall* op);
+
+ // JSR 292
+ void preserve_SP(LIR_OpJavaCall* op);
+ void restore_SP( LIR_OpJavaCall* op);
void osr_entry();
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -2284,7 +2284,7 @@
void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) {
- int i = x->has_receiver() ? 1 : 0;
+ int i = (x->has_receiver() || x->is_invokedynamic()) ? 1 : 0;
for (; i < args->length(); i++) {
LIRItem* param = args->at(i);
LIR_Opr loc = arg_list->at(i);
@@ -2322,6 +2322,10 @@
LIRItem* receiver = new LIRItem(x->receiver(), this);
argument_items->append(receiver);
}
+ if (x->is_invokedynamic()) {
+ // Insert a dummy for the synthetic MethodHandle argument.
+ argument_items->append(NULL);
+ }
int idx = x->has_receiver() ? 1 : 0;
for (int i = 0; i < x->number_of_arguments(); i++) {
LIRItem* param = new LIRItem(x->argument_at(i), this);
@@ -2371,6 +2375,9 @@
CodeEmitInfo* info = state_for(x, x->state());
+ // invokedynamics can deoptimize.
+ CodeEmitInfo* deopt_info = x->is_invokedynamic() ? state_for(x, x->state_before()) : NULL;
+
invoke_load_arguments(x, args, arg_list);
if (x->has_receiver()) {
@@ -2407,6 +2414,47 @@
__ call_virtual(x->target(), receiver, result_register, vtable_offset, arg_list, info);
}
break;
+ case Bytecodes::_invokedynamic: {
+ ciBytecodeStream bcs(x->scope()->method());
+ bcs.force_bci(x->bci());
+ assert(bcs.cur_bc() == Bytecodes::_invokedynamic, "wrong stream");
+ ciCPCache* cpcache = bcs.get_cpcache();
+
+ // Get CallSite offset from constant pool cache pointer.
+ int index = bcs.get_method_index();
+ size_t call_site_offset = cpcache->get_f1_offset(index);
+
+ // If this invokedynamic call site hasn't been executed yet in
+ // the interpreter, the CallSite object in the constant pool
+ // cache is still null and we need to deoptimize.
+ if (cpcache->is_f1_null_at(index)) {
+ // Cannot re-use same xhandlers for multiple CodeEmitInfos, so
+ // clone all handlers. This is handled transparently in other
+ // places by the CodeEmitInfo cloning logic but is handled
+ // specially here because a stub isn't being used.
+ x->set_exception_handlers(new XHandlers(x->exception_handlers()));
+
+ DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info);
+ __ jump(deopt_stub);
+ }
+
+ // Use the receiver register for the synthetic MethodHandle
+ // argument.
+ receiver = LIR_Assembler::receiverOpr();
+ LIR_Opr tmp = new_register(objectType);
+
+ // Load CallSite object from constant pool cache.
+ __ oop2reg(cpcache->constant_encoding(), tmp);
+ __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp);
+
+ // Load target MethodHandle from CallSite object.
+ __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver);
+
+ __ call_dynamic(x->target(), receiver, result_register,
+ SharedRuntime::get_resolve_opt_virtual_call_stub(),
+ arg_list, info);
+ break;
+ }
default:
ShouldNotReachHere();
break;
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -2479,6 +2479,15 @@
return 2;
}
+ case T_ADDRESS: {
+#ifdef _LP64
+ scope_values->append(new ConstantLongValue(c->as_jint()));
+#else
+ scope_values->append(new ConstantIntValue(c->as_jint()));
+#endif
+ return 1;
+ }
+
default:
ShouldNotReachHere();
return -1;
--- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
void inline_cache_check(Register receiver, Register iCache);
void build_frame(int frame_size_in_bytes);
- void method_exit(bool restore_frame);
+ void remove_frame(int frame_size_in_bytes);
void unverified_entry(Register receiver, Register ic_klass);
void verified_entry();
--- a/hotspot/src/share/vm/ci/ciCPCache.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/ci/ciCPCache.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,16 @@
// ------------------------------------------------------------------
+// ciCPCache::is_f1_null_at
+bool ciCPCache::is_f1_null_at(int index) {
+ VM_ENTRY_MARK;
+ constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop();
+ oop f1 = cpcache->secondary_entry_at(index)->f1();
+ return (f1 == NULL);
+}
+
+
+// ------------------------------------------------------------------
// ciCPCache::print
//
// Print debugging information about the cache.
--- a/hotspot/src/share/vm/ci/ciCPCache.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/ci/ciCPCache.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,5 +39,7 @@
// requested entry.
size_t get_f1_offset(int index);
+ bool is_f1_null_at(int index);
+
void print();
};
--- a/hotspot/src/share/vm/code/codeBlob.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -249,7 +249,6 @@
size += round_to(buffer_size, oopSize);
assert(name != NULL, "must provide a name");
{
-
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) BufferBlob(name, size);
}
@@ -271,7 +270,6 @@
unsigned int size = allocation_size(cb, sizeof(BufferBlob));
assert(name != NULL, "must provide a name");
{
-
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) BufferBlob(name, size, cb);
}
@@ -298,10 +296,48 @@
MemoryService::track_code_cache_memory_usage();
}
-bool BufferBlob::is_adapter_blob() const {
- return (strcmp(AdapterHandlerEntry::name, name()) == 0);
+
+//----------------------------------------------------------------------------------------------------
+// Implementation of AdapterBlob
+
+AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
+ ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
+
+ AdapterBlob* blob = NULL;
+ unsigned int size = allocation_size(cb, sizeof(AdapterBlob));
+ {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ blob = new (size) AdapterBlob(size, cb);
+ }
+ // Track memory usage statistic after releasing CodeCache_lock
+ MemoryService::track_code_cache_memory_usage();
+
+ return blob;
}
+
+//----------------------------------------------------------------------------------------------------
+// Implementation of MethodHandlesAdapterBlob
+
+MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) {
+ ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
+
+ MethodHandlesAdapterBlob* blob = NULL;
+ unsigned int size = sizeof(MethodHandlesAdapterBlob);
+ // align the size to CodeEntryAlignment
+ size = align_code_offset(size);
+ size += round_to(buffer_size, oopSize);
+ {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ blob = new (size) MethodHandlesAdapterBlob(size);
+ }
+ // Track memory usage statistic after releasing CodeCache_lock
+ MemoryService::track_code_cache_memory_usage();
+
+ return blob;
+}
+
+
//----------------------------------------------------------------------------------------------------
// Implementation of RuntimeStub
--- a/hotspot/src/share/vm/code/codeBlob.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/code/codeBlob.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -90,14 +90,15 @@
void flush();
// Typing
- virtual bool is_buffer_blob() const { return false; }
- virtual bool is_nmethod() const { return false; }
- virtual bool is_runtime_stub() const { return false; }
- virtual bool is_deoptimization_stub() const { return false; }
- virtual bool is_uncommon_trap_stub() const { return false; }
- virtual bool is_exception_stub() const { return false; }
- virtual bool is_safepoint_stub() const { return false; }
- virtual bool is_adapter_blob() const { return false; }
+ virtual bool is_buffer_blob() const { return false; }
+ virtual bool is_nmethod() const { return false; }
+ virtual bool is_runtime_stub() const { return false; }
+ virtual bool is_deoptimization_stub() const { return false; }
+ virtual bool is_uncommon_trap_stub() const { return false; }
+ virtual bool is_exception_stub() const { return false; }
+ virtual bool is_safepoint_stub() const { return false; }
+ virtual bool is_adapter_blob() const { return false; }
+ virtual bool is_method_handles_adapter_blob() const { return false; }
virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() const { return false; }
@@ -221,6 +222,9 @@
class BufferBlob: public CodeBlob {
friend class VMStructs;
+ friend class AdapterBlob;
+ friend class MethodHandlesAdapterBlob;
+
private:
// Creation support
BufferBlob(const char* name, int size);
@@ -236,8 +240,7 @@
static void free(BufferBlob* buf);
// Typing
- bool is_buffer_blob() const { return true; }
- bool is_adapter_blob() const;
+ virtual bool is_buffer_blob() const { return true; }
// GC/Verification support
void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
@@ -255,6 +258,40 @@
//----------------------------------------------------------------------------------------------------
+// AdapterBlob: used to hold C2I/I2C adapters
+
+class AdapterBlob: public BufferBlob {
+private:
+ AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {}
+ AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {}
+
+public:
+ // Creation
+ static AdapterBlob* create(CodeBuffer* cb);
+
+ // Typing
+ virtual bool is_adapter_blob() const { return true; }
+};
+
+
+//----------------------------------------------------------------------------------------------------
+// MethodHandlesAdapterBlob: used to hold MethodHandles adapters
+
+class MethodHandlesAdapterBlob: public BufferBlob {
+private:
+ MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {}
+ MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {}
+
+public:
+ // Creation
+ static MethodHandlesAdapterBlob* create(int buffer_size);
+
+ // Typing
+ virtual bool is_method_handles_adapter_blob() const { return true; }
+};
+
+
+//----------------------------------------------------------------------------------------------------
// RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine
class RuntimeStub: public CodeBlob {
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -988,10 +988,12 @@
}
if (method->is_not_compilable(comp_level)) return NULL;
- nmethod* saved = CodeCache::find_and_remove_saved_code(method());
- if (saved != NULL) {
- method->set_code(method, saved);
- return saved;
+ if (UseCodeCacheFlushing) {
+ nmethod* saved = CodeCache::find_and_remove_saved_code(method());
+ if (saved != NULL) {
+ method->set_code(method, saved);
+ return saved;
+ }
}
} else {
--- a/hotspot/src/share/vm/includeDB_compiler1 Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/includeDB_compiler1 Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
//
-// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+// Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -246,6 +246,7 @@
c1_LIRGenerator.cpp c1_LIRGenerator.hpp
c1_LIRGenerator.cpp c1_ValueStack.hpp
c1_LIRGenerator.cpp ciArrayKlass.hpp
+c1_LIRGenerator.cpp ciCPCache.hpp
c1_LIRGenerator.cpp ciInstance.hpp
c1_LIRGenerator.cpp heapRegion.hpp
c1_LIRGenerator.cpp sharedRuntime.hpp
--- a/hotspot/src/share/vm/includeDB_core Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/includeDB_core Thu Mar 18 06:36:43 2010 -0700
@@ -541,6 +541,7 @@
ciCPCache.cpp cpCacheOop.hpp
ciCPCache.cpp ciCPCache.hpp
+ciCPCache.cpp ciUtilities.hpp
ciCPCache.hpp ciClassList.hpp
ciCPCache.hpp ciObject.hpp
@@ -2016,6 +2017,7 @@
init.cpp icBuffer.hpp
init.cpp icache.hpp
init.cpp init.hpp
+init.cpp methodHandles.hpp
init.cpp safepoint.hpp
init.cpp sharedRuntime.hpp
init.cpp universe.hpp
@@ -2870,6 +2872,7 @@
methodHandles.cpp oopFactory.hpp
methodHandles.cpp reflection.hpp
methodHandles.cpp signature.hpp
+methodHandles.cpp stubRoutines.hpp
methodHandles.cpp symbolTable.hpp
methodHandles_<arch>.cpp allocation.inline.hpp
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2088,29 +2088,41 @@
BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, Node* stride,
- Node* range) {
+ Node* range, bool upper) {
+ DEBUG_ONLY(ttyLocker ttyl);
+ if (TraceLoopPredicate) tty->print("rc_predicate ");
+
Node* max_idx_expr = init;
int stride_con = stride->get_int();
- if ((stride_con > 0) == (scale > 0)) {
+ if ((stride_con > 0) == (scale > 0) == upper) {
max_idx_expr = new (C, 3) SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
+ if (TraceLoopPredicate) tty->print("(limit - stride) ");
+ } else {
+ if (TraceLoopPredicate) tty->print("init ");
}
if (scale != 1) {
ConNode* con_scale = _igvn.intcon(scale);
max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
register_new_node(max_idx_expr, ctrl);
+ if (TraceLoopPredicate) tty->print("* %d ", scale);
}
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
register_new_node(max_idx_expr, ctrl);
+ if (TraceLoopPredicate)
+ if (offset->is_Con()) tty->print("+ %d ", offset->get_int());
+ else tty->print("+ offset ");
}
CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
register_new_node(cmp, ctrl);
BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
register_new_node(bol, ctrl);
+
+ if (TraceLoopPredicate) tty->print_cr("<u range");
return bol;
}
@@ -2187,7 +2199,6 @@
while (if_proj_list.size() > 0) {
// Following are changed to nonnull when a predicate can be hoisted
ProjNode* new_predicate_proj = NULL;
- BoolNode* new_predicate_bol = NULL;
ProjNode* proj = if_proj_list.pop()->as_Proj();
IfNode* iff = proj->in(0)->as_If();
@@ -2218,93 +2229,120 @@
// Invariant test
new_predicate_proj = create_new_if_for_predicate(predicate_proj);
Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0);
- new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
- if (TraceLoopPredicate) tty->print("invariant");
+ BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
+
+ // Negate test if necessary
+ bool negated = false;
+ if (proj->_con != predicate_proj->_con) {
+ new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
+ register_new_node(new_predicate_bol, ctrl);
+ negated = true;
+ }
+ IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If();
+ _igvn.hash_delete(new_predicate_iff);
+ new_predicate_iff->set_req(1, new_predicate_bol);
+ if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx);
+
} else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) {
- // Range check (only for counted loops)
- new_predicate_proj = create_new_if_for_predicate(predicate_proj);
- Node *ctrl = new_predicate_proj->in(0)->as_If()->in(0);
+ assert(proj->_con == predicate_proj->_con, "must match");
+
+ // Range check for counted loops
const Node* cmp = bol->in(1)->as_Cmp();
Node* idx = cmp->in(1);
assert(!invar.is_invariant(idx), "index is variant");
assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be");
- LoadRangeNode* ld_rng = (LoadRangeNode*)cmp->in(2); // LoadRangeNode
+ Node* ld_rng = cmp->in(2); // LoadRangeNode
assert(invar.is_invariant(ld_rng), "load range must be invariant");
- ld_rng = (LoadRangeNode*)invar.clone(ld_rng, ctrl);
int scale = 1;
Node* offset = zero;
bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset);
assert(ok, "must be index expression");
+
+ Node* init = cl->init_trip();
+ Node* limit = cl->limit();
+ Node* stride = cl->stride();
+
+ // Build if's for the upper and lower bound tests. The
+ // lower_bound test will dominate the upper bound test and all
+ // cloned or created nodes will use the lower bound test as
+ // their declared control.
+ ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj);
+ ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj);
+ assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
+ Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
+
+ // Perform cloning to keep Invariance state correct since the
+ // late schedule will place invariant things in the loop.
+ ld_rng = invar.clone(ld_rng, ctrl);
if (offset && offset != zero) {
assert(invar.is_invariant(offset), "offset must be loop invariant");
offset = invar.clone(offset, ctrl);
}
- Node* init = cl->init_trip();
- Node* limit = cl->limit();
- Node* stride = cl->stride();
- new_predicate_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng);
- if (TraceLoopPredicate) tty->print("range check");
- }
+
+ // Test the lower bound
+ Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, false);
+ IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
+ _igvn.hash_delete(lower_bound_iff);
+ lower_bound_iff->set_req(1, lower_bound_bol);
+ if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx);
- if (new_predicate_proj == NULL) {
+ // Test the upper bound
+ Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, true);
+ IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
+ _igvn.hash_delete(upper_bound_iff);
+ upper_bound_iff->set_req(1, upper_bound_bol);
+ if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx);
+
+ // Fall through into rest of the clean up code which will move
+ // any dependent nodes onto the upper bound test.
+ new_predicate_proj = upper_bound_proj;
+ } else {
// The other proj of the "iff" is a uncommon trap projection, and we can assume
// the other proj will not be executed ("executed" means uct raised).
continue;
- } else {
- // Success - attach condition (new_predicate_bol) to predicate if
- invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
- IfNode* new_iff = new_predicate_proj->in(0)->as_If();
+ }
- // Negate test if necessary
- if (proj->_con != predicate_proj->_con) {
- new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
- register_new_node(new_predicate_bol, new_iff->in(0));
- if (TraceLoopPredicate) tty->print_cr(" if negated: %d", iff->_idx);
- } else {
- if (TraceLoopPredicate) tty->print_cr(" if: %d", iff->_idx);
- }
+ // Success - attach condition (new_predicate_bol) to predicate if
+ invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
- _igvn.hash_delete(new_iff);
- new_iff->set_req(1, new_predicate_bol);
-
- _igvn.hash_delete(iff);
- iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
+ // Eliminate the old if in the loop body
+ _igvn.hash_delete(iff);
+ iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
- Node* ctrl = new_predicate_proj; // new control
- ProjNode* dp = proj; // old control
- assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj");
- // Find nodes (depends only on the test) off the surviving projection;
- // move them outside the loop with the control of proj_clone
- for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
- Node* cd = dp->fast_out(i); // Control-dependent node
- if (cd->depends_only_on_test()) {
- assert(cd->in(0) == dp, "");
- _igvn.hash_delete(cd);
- cd->set_req(0, ctrl); // ctrl, not NULL
- set_early_ctrl(cd);
- _igvn._worklist.push(cd);
- IdealLoopTree *new_loop = get_loop(get_ctrl(cd));
- if (new_loop != loop) {
- if (!loop->_child) loop->_body.yank(cd);
- if (!new_loop->_child ) new_loop->_body.push(cd);
- }
- --i;
- --imax;
+ Node* ctrl = new_predicate_proj; // new control
+ ProjNode* dp = proj; // old control
+ assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj");
+ // Find nodes (depends only on the test) off the surviving projection;
+ // move them outside the loop with the control of proj_clone
+ for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
+ Node* cd = dp->fast_out(i); // Control-dependent node
+ if (cd->depends_only_on_test()) {
+ assert(cd->in(0) == dp, "");
+ _igvn.hash_delete(cd);
+ cd->set_req(0, ctrl); // ctrl, not NULL
+ set_early_ctrl(cd);
+ _igvn._worklist.push(cd);
+ IdealLoopTree *new_loop = get_loop(get_ctrl(cd));
+ if (new_loop != loop) {
+ if (!loop->_child) loop->_body.yank(cd);
+ if (!new_loop->_child ) new_loop->_body.push(cd);
}
+ --i;
+ --imax;
}
+ }
- hoisted = true;
- C->set_major_progress();
- }
+ hoisted = true;
+ C->set_major_progress();
} // end while
#ifndef PRODUCT
- // report that the loop predication has been actually performed
- // for this loop
- if (TraceLoopPredicate && hoisted) {
- tty->print("Loop Predication Performed:");
- loop->dump_head();
- }
+ // report that the loop predication has been actually performed
+ // for this loop
+ if (TraceLoopPredicate && hoisted) {
+ tty->print("Loop Predication Performed:");
+ loop->dump_head();
+ }
#endif
return hoisted;
--- a/hotspot/src/share/vm/opto/loopnode.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -821,7 +821,7 @@
BoolNode* rc_predicate(Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, Node* stride,
- Node* range);
+ Node* range, bool upper);
// Implementation of the loop predication to promote checks outside the loop
bool loop_predication_impl(IdealLoopTree *loop);
--- a/hotspot/src/share/vm/opto/runtime.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/opto/runtime.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -864,7 +864,7 @@
thread->set_exception_handler_pc(handler_address);
thread->set_exception_stack_size(0);
- // Check if the exception PC is a MethodHandle call.
+ // Check if the exception PC is a MethodHandle call site.
thread->set_is_method_handle_exception(nm->is_method_handle_return(pc));
}
@@ -952,7 +952,7 @@
thread->set_vm_result(exception);
// Frame not compiled (handles deoptimization blob)
- return SharedRuntime::raw_exception_handler_for_return_address(ret_pc);
+ return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc);
}
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,6 +82,10 @@
NULL
};
+// Adapters.
+MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL;
+int MethodHandles::_adapter_code_size = StubRoutines::method_handles_adapters_code_size;
+
jobject MethodHandles::_raise_exception_method;
#ifdef ASSERT
@@ -95,6 +99,41 @@
}
#endif
+
+//------------------------------------------------------------------------------
+// MethodHandles::generate_adapters
+//
+void MethodHandles::generate_adapters() {
+ if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return;
+
+ assert(_adapter_code == NULL, "generate only once");
+
+ ResourceMark rm;
+ TraceTime timer("MethodHandles adapters generation", TraceStartupTime);
+ _adapter_code = MethodHandlesAdapterBlob::create(_adapter_code_size);
+ if (_adapter_code == NULL)
+ vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters");
+ CodeBuffer code(_adapter_code->instructions_begin(), _adapter_code->instructions_size());
+
+ MethodHandlesAdapterGenerator g(&code);
+ g.generate();
+}
+
+
+//------------------------------------------------------------------------------
+// MethodHandlesAdapterGenerator::generate
+//
+void MethodHandlesAdapterGenerator::generate() {
+ // Generate generic method handle adapters.
+ for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
+ ek < MethodHandles::_EK_LIMIT;
+ ek = MethodHandles::EntryKind(1 + (int)ek)) {
+ StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
+ MethodHandles::generate_method_handle_stub(_masm, ek);
+ }
+}
+
+
void MethodHandles::set_enabled(bool z) {
if (_enabled != z) {
guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles");
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,6 +115,10 @@
static const char* _entry_names[_EK_LIMIT+1];
static jobject _raise_exception_method;
+ // Adapters.
+ static MethodHandlesAdapterBlob* _adapter_code;
+ static int _adapter_code_size;
+
static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; }
static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; }
@@ -133,6 +137,43 @@
_entries[ek] = me;
}
+ // Some adapter helper functions.
+ static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) {
+ switch (ek) {
+ case _bound_int_mh : // fall-thru
+ case _bound_int_direct_mh : arg_type = T_INT; arg_mask = _INSERT_INT_MASK; break;
+ case _bound_long_mh : // fall-thru
+ case _bound_long_direct_mh: arg_type = T_LONG; arg_mask = _INSERT_LONG_MASK; break;
+ case _bound_ref_mh : // fall-thru
+ case _bound_ref_direct_mh : arg_type = T_OBJECT; arg_mask = _INSERT_REF_MASK; break;
+ default: ShouldNotReachHere();
+ }
+ arg_slots = type2size[arg_type];
+ }
+
+ static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) {
+ int swap_slots = 0;
+ switch (ek) {
+ case _adapter_opt_swap_1: swap_slots = 1; rotate = 0; break;
+ case _adapter_opt_swap_2: swap_slots = 2; rotate = 0; break;
+ case _adapter_opt_rot_1_up: swap_slots = 1; rotate = 1; break;
+ case _adapter_opt_rot_1_down: swap_slots = 1; rotate = -1; break;
+ case _adapter_opt_rot_2_up: swap_slots = 2; rotate = 1; break;
+ case _adapter_opt_rot_2_down: swap_slots = 2; rotate = -1; break;
+ default: ShouldNotReachHere();
+ }
+ // Return the size of the stack slots to move in bytes.
+ swap_bytes = swap_slots * Interpreter::stackElementSize();
+ }
+
+ static int get_ek_adapter_opt_spread_info(EntryKind ek) {
+ switch (ek) {
+ case _adapter_opt_spread_0: return 0;
+ case _adapter_opt_spread_1: return 1;
+ default : return -1;
+ }
+ }
+
static methodOop raise_exception_method() {
oop rem = JNIHandles::resolve(_raise_exception_method);
assert(rem == NULL || rem->is_method(), "");
@@ -230,7 +271,10 @@
// bit values for suppress argument to expand_MemberName:
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
- // called from InterpreterGenerator and StubGenerator
+ // Generate MethodHandles adapters.
+ static void generate_adapters();
+
+ // Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
@@ -385,13 +429,13 @@
static void insert_arg_slots(MacroAssembler* _masm,
RegisterOrConstant arg_slots,
int arg_mask,
- Register rax_argslot,
- Register rbx_temp, Register rdx_temp);
+ Register argslot_reg,
+ Register temp_reg, Register temp2_reg);
static void remove_arg_slots(MacroAssembler* _masm,
RegisterOrConstant arg_slots,
- Register rax_argslot,
- Register rbx_temp, Register rdx_temp);
+ Register argslot_reg,
+ Register temp_reg, Register temp2_reg);
};
@@ -447,3 +491,14 @@
address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); }
address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); }
+
+
+//------------------------------------------------------------------------------
+// MethodHandlesAdapterGenerator
+//
+class MethodHandlesAdapterGenerator : public StubCodeGenerator {
+public:
+ MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
+
+ void generate();
+};
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -2859,6 +2859,12 @@
}
#endif // _LP64
+ // MethodHandles code does not support TaggedStackInterpreter.
+ if (EnableMethodHandles && TaggedStackInterpreter) {
+ warning("TaggedStackInterpreter is not supported by MethodHandles code. Disabling TaggedStackInterpreter.");
+ TaggedStackInterpreter = false;
+ }
+
// Check the GC selections again.
if (!check_gc_consistency()) {
return JNI_EINVAL;
--- a/hotspot/src/share/vm/runtime/init.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/runtime/init.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -118,6 +118,9 @@
javaClasses_init(); // must happen after vtable initialization
stubRoutines_init2(); // note: StubRoutines need 2-phase init
+ // Generate MethodHandles adapters.
+ MethodHandles::generate_adapters();
+
// Although we'd like to, we can't easily do a heap verify
// here because the main thread isn't yet a JavaThread, so
// its TLAB may not be made parseable from the usual interfaces.
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -256,7 +256,7 @@
// The continuation address is the entry point of the exception handler of the
// previous frame depending on the return address.
-address SharedRuntime::raw_exception_handler_for_return_address(address return_address) {
+address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {
assert(frame::verify_return_pc(return_address), "must be a return pc");
// the fastest case first
@@ -264,6 +264,8 @@
if (blob != NULL && blob->is_nmethod()) {
nmethod* code = (nmethod*)blob;
assert(code != NULL, "nmethod must be present");
+ // Check if the return address is a MethodHandle call site.
+ thread->set_is_method_handle_exception(code->is_method_handle_return(return_address));
// native nmethods don't have exception handlers
assert(!code->is_native_method(), "no exception handler");
assert(code->header_begin() != code->exception_begin(), "no exception handler");
@@ -289,6 +291,8 @@
if (blob->is_nmethod()) {
nmethod* code = (nmethod*)blob;
assert(code != NULL, "nmethod must be present");
+ // Check if the return address is a MethodHandle call site.
+ thread->set_is_method_handle_exception(code->is_method_handle_return(return_address));
assert(code->header_begin() != code->exception_begin(), "no exception handler");
return code->exception_begin();
}
@@ -309,10 +313,11 @@
}
-JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(address return_address))
- return raw_exception_handler_for_return_address(return_address);
+JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(JavaThread* thread, address return_address))
+ return raw_exception_handler_for_return_address(thread, return_address);
JRT_END
+
address SharedRuntime::get_poll_stub(address pc) {
address stub;
// Look up the code blob
@@ -465,16 +470,6 @@
t = table.entry_for(catch_pco, -1, 0);
}
-#ifdef COMPILER1
- if (nm->is_compiled_by_c1() && t == NULL && handler_bci == -1) {
- // Exception is not handled by this frame so unwind. Note that
- // this is not the same as how C2 does this. C2 emits a table
- // entry that dispatches to the unwind code in the nmethod.
- return NULL;
- }
-#endif /* COMPILER1 */
-
-
if (t == NULL) {
tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d", ret_pc, handler_bci);
tty->print_cr(" Exception:");
@@ -587,7 +582,7 @@
// 3. Implict null exception in nmethod
if (!cb->is_nmethod()) {
- guarantee(cb->is_adapter_blob(),
+ guarantee(cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(),
"exception happened outside interpreter, nmethods and vtable stubs (1)");
// There is no handler here, so we will simply unwind.
return StubRoutines::throw_NullPointerException_at_call_entry();
@@ -892,12 +887,13 @@
RegisterMap cbl_map(thread, false);
frame caller_frame = thread->last_frame().sender(&cbl_map);
- CodeBlob* cb = caller_frame.cb();
- guarantee(cb != NULL && cb->is_nmethod(), "must be called from nmethod");
+ CodeBlob* caller_cb = caller_frame.cb();
+ guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod");
+ nmethod* caller_nm = caller_cb->as_nmethod_or_null();
// make sure caller is not getting deoptimized
// and removed before we are done with it.
// CLEANUP - with lazy deopt shouldn't need this lock
- nmethodLocker caller_lock((nmethod*)cb);
+ nmethodLocker caller_lock(caller_nm);
// determine call info & receiver
@@ -929,6 +925,13 @@
}
#endif
+ // JSR 292
+ // If the resolved method is a MethodHandle invoke target the call
+ // site must be a MethodHandle call site.
+ if (callee_method->is_method_handle_invoke()) {
+ assert(caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site");
+ }
+
// Compute entry points. This might require generation of C2I converter
// frames, so we cannot be holding any locks here. Furthermore, the
// computation of the entry points is independent of patching the call. We
@@ -940,13 +943,12 @@
StaticCallInfo static_call_info;
CompiledICInfo virtual_call_info;
-
// Make sure the callee nmethod does not get deoptimized and removed before
// we are done patching the code.
- nmethod* nm = callee_method->code();
- nmethodLocker nl_callee(nm);
+ nmethod* callee_nm = callee_method->code();
+ nmethodLocker nl_callee(callee_nm);
#ifdef ASSERT
- address dest_entry_point = nm == NULL ? 0 : nm->entry_point(); // used below
+ address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below
#endif
if (is_virtual) {
@@ -2077,7 +2079,6 @@
// ---------------------------------------------------------------------------
// Implementation of AdapterHandlerLibrary
-const char* AdapterHandlerEntry::name = "I2C/C2I adapters";
AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL;
const int AdapterHandlerLibrary_size = 16*K;
@@ -2129,7 +2130,7 @@
ResourceMark rm;
NOT_PRODUCT(int code_size);
- BufferBlob *B = NULL;
+ AdapterBlob* B = NULL;
AdapterHandlerEntry* entry = NULL;
AdapterFingerPrint* fingerprint = NULL;
{
@@ -2179,7 +2180,7 @@
// Create I2C & C2I handlers
- BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
+ BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
if (buf != NULL) {
CodeBuffer buffer(buf->instructions_begin(), buf->instructions_size());
short buffer_locs[20];
@@ -2208,7 +2209,7 @@
}
#endif
- B = BufferBlob::create(AdapterHandlerEntry::name, &buffer);
+ B = AdapterBlob::create(&buffer);
NOT_PRODUCT(code_size = buffer.code_size());
}
if (B == NULL) {
@@ -2240,7 +2241,7 @@
jio_snprintf(blob_id,
sizeof(blob_id),
"%s(%s)@" PTR_FORMAT,
- AdapterHandlerEntry::name,
+ B->name(),
fingerprint->as_string(),
B->instructions_begin());
VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Mar 18 06:36:43 2010 -0700
@@ -96,10 +96,9 @@
static jdouble dexp(jdouble x);
static jdouble dpow(jdouble x, jdouble y);
-
// exception handling across interpreter/compiler boundaries
- static address raw_exception_handler_for_return_address(address return_address);
- static address exception_handler_for_return_address(address return_address);
+ static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address);
+ static address exception_handler_for_return_address(JavaThread* thread, address return_address);
#ifndef SERIALGC
// G1 write barriers
@@ -568,9 +567,6 @@
AdapterHandlerEntry();
public:
- // The name we give all buffer blobs
- static const char* name;
-
address get_i2c_entry() { return _i2c_entry; }
address get_c2i_entry() { return _c2i_entry; }
address get_c2i_unverified_entry() { return _c2i_unverified_entry; }
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Mar 11 14:41:29 2010 -0500
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Mar 18 06:36:43 2010 -0700
@@ -223,7 +223,7 @@
break;
case Deoptimization::Unpack_exception:
// exception is pending
- pc = SharedRuntime::raw_exception_handler_for_return_address(pc);
+ pc = SharedRuntime::raw_exception_handler_for_return_address(thread, pc);
// [phh] We're going to end up in some handler or other, so it doesn't
// matter what mdp we point to. See exception_handler_for_exception()
// in interpreterRuntime.cpp.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6930043/Test6930043.java Thu Mar 18 06:36:43 2010 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6930043
+ * @summary C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
+ *
+ * @run main Test6930043
+ */
+
+import java.io.PrintStream;
+
+public class Test6930043 {
+ int[] a;
+ int idx;
+
+ public int loop_back(int i, int i_0_) {
+ int i_1_ = 0;
+ int[] is = a;
+ if (is == null) return 0;
+ for (int i_2_ = i; i_2_ >= i_0_; i_2_--)
+ i_1_ += is[idx = i_2_];
+ return i_1_;
+ }
+
+ public int loop_forw(int start, int end) {
+ int result = 0;
+ int[] is = a;
+ if (is == null) return 0;
+ for (int index = start; index < end; index++)
+ result += is[index];
+ // result += is[idx = index];
+ return result;
+ }
+
+ public static void main(String[] strings) {
+ Test6930043 var_Test6930043 = new Test6930043();
+ var_Test6930043.a = new int[1000000];
+ var_Test6930043.loop_forw(10, 999990);
+ var_Test6930043.loop_forw(10, 999990);
+ for (int i = 0; i < 3; i++) {
+ try {
+ if (var_Test6930043.loop_forw(-1, 999990) != 0) throw new InternalError();
+ } catch (ArrayIndexOutOfBoundsException e) { }
+ }
+ var_Test6930043.loop_back(999990, 10);
+ var_Test6930043.loop_back(999990, 10);
+ for (int i = 0; i < 3; i++) {
+ try {
+ if (var_Test6930043.loop_back(999990, -1) != 0) throw new InternalError();
+ } catch (ArrayIndexOutOfBoundsException e) { }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6932496/Test6932496.java Thu Mar 18 06:36:43 2010 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6932496
+ * @summary incorrect deopt of jsr subroutine on 64 bit c1
+ *
+ * @compile -source 1.5 -target 1.5 -XDjsrlimit=0 Test6932496.java
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test6932496.m Test6932496
+ */
+
+public class Test6932496 {
+ static class A {
+ volatile boolean flag = false;
+ }
+
+ static void m() {
+ try {
+ } finally {
+ A a = new A();
+ a.flag = true;
+ }
+ }
+
+
+ static public void main(String[] args) {
+ m();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6935535/Test.java Thu Mar 18 06:36:43 2010 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6935535
+ * @summary String.indexOf() returns incorrect result on x86 with SSE4.2
+ *
+ * @run main/othervm -Xcomp Test
+ */
+
+public class Test {
+
+ static int IndexOfTest(String str) {
+ return str.indexOf("1111111111111xx1x");
+ }
+
+ public static void main(String args[]) {
+ String str = "1111111111111xx1111111111111xx1x";
+ str = str.substring(0, 31);
+ int idx = IndexOfTest(str);
+ System.out.println("IndexOf(" + "1111111111111xx1x" + ") = " + idx + " in " + str);
+ if (idx != -1) {
+ System.exit(97);
+ }
+ }
+}
+