# HG changeset patch # User dcubed # Date 1299173506 28800 # Node ID 8c0d0510d36f41d38c9a4b771a3901b775cf8199 # Parent 0e531ab5ba04967a0e9aa6aef65e6eb3a0dcf632# Parent a3c0ec0428a2564a70a33a0348553e9d4c994c63 Merge diff -r 0e531ab5ba04 -r 8c0d0510d36f make/windows/makefiles/compile.make --- a/make/windows/makefiles/compile.make Tue Mar 01 11:53:36 2011 -0800 +++ b/make/windows/makefiles/compile.make Thu Mar 03 09:31:46 2011 -0800 @@ -207,6 +207,9 @@ # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe +!if "$(BUILDARCH)" == "i486" +LINK_FLAGS = /SAFESEH $(LINK_FLAGS) +!endif !endif # Compile for space above time. diff -r 0e531ab5ba04 -r 8c0d0510d36f make/windows/makefiles/launcher.make --- a/make/windows/makefiles/launcher.make Tue Mar 01 11:53:36 2011 -0800 +++ b/make/windows/makefiles/launcher.make Thu Mar 03 09:31:46 2011 -0800 @@ -1,71 +1,73 @@ -# -# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - - -LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \ - /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - /D GAMMA \ - /D LAUNCHER_TYPE=\"gamma\" \ - /D _CRT_SECURE_NO_WARNINGS \ - /D _CRT_SECURE_NO_DEPRECATE \ - /D LINK_INTO_LIBJVM \ - /I $(WorkSpace)\src\os\windows\launcher \ - /I $(WorkSpace)\src\share\tools\launcher \ - /I $(WorkSpace)\src\share\vm\prims \ - /I $(WorkSpace)\src\share\vm \ - /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ - /I $(WorkSpace)\src\os\windows\vm - -LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console - -!if "$(COMPILER_NAME)" == "VS2005" -# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib -# on the link command line, otherwise we get missing __security_check_cookie -# externals at link time. Even with /GS-, you need bufferoverflowU.lib. -BUFFEROVERFLOWLIB = bufferoverflowU.lib -LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) -!endif - -LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher -LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher - -OUTDIR = launcher - -{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h - -launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj - echo $(JAVA_HOME) > jdkpath.txt - $(LINK) $(LINK_FLAGS) /out:hotspot.exe $** - - +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + + +LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \ + /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ + /D GAMMA \ + /D LAUNCHER_TYPE=\"gamma\" \ + /D _CRT_SECURE_NO_WARNINGS \ + /D _CRT_SECURE_NO_DEPRECATE \ + /D LINK_INTO_LIBJVM \ + /I $(WorkSpace)\src\os\windows\launcher \ + /I $(WorkSpace)\src\share\tools\launcher \ + /I $(WorkSpace)\src\share\vm\prims \ + /I $(WorkSpace)\src\share\vm \ + /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ + /I $(WorkSpace)\src\os\windows\vm + +LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console + +!if "$(COMPILER_NAME)" == "VS2005" +# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib +# on the link command line, otherwise we get missing __security_check_cookie +# externals at link time. Even with /GS-, you need bufferoverflowU.lib. +BUFFEROVERFLOWLIB = bufferoverflowU.lib +LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) +!endif + +!if "$(COMPILER_NAME)" == "VS2010" && "$(BUILDARCH)" == "i486" +LINK_FLAGS = /SAFESEH $(LINK_FLAGS) +!endif + +LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher +LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher + +OUTDIR = launcher + +{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< + +{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< + +$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h + +launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj + echo $(JAVA_HOME) > jdkpath.txt + $(LINK) $(LINK_FLAGS) /out:hotspot.exe $** diff -r 0e531ab5ba04 -r 8c0d0510d36f src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/os/linux/vm/os_linux.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -2213,7 +2213,7 @@ if (rp == NULL) return; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "/jre/lib///libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and diff -r 0e531ab5ba04 -r 8c0d0510d36f src/os/posix/vm/os_posix.cpp --- a/src/os/posix/vm/os_posix.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/os/posix/vm/os_posix.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -59,3 +59,12 @@ VMError::report_coredump_status(buffer, success); } +bool os::is_debugger_attached() { + // not implemented + return false; +} + +void os::wait_for_keypress_at_exit(void) { + // don't do anything on posix platforms + return; +} diff -r 0e531ab5ba04 -r 8c0d0510d36f src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -2511,7 +2511,7 @@ assert(ret != 0, "cannot locate libjvm"); realpath((char *)dlinfo.dli_fname, buf); - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "/jre/lib///libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and diff -r 0e531ab5ba04 -r 8c0d0510d36f src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/os/windows/vm/os_windows.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -22,10 +22,8 @@ * */ -#ifdef _WIN64 -// Must be at least Windows 2000 or XP to use VectoredExceptions +// Must be at least Windows 2000 or XP to use VectoredExceptions and IsDebuggerPresent #define _WIN32_WINNT 0x500 -#endif // no precompiled headers #include "classfile/classLoader.hpp" @@ -1788,7 +1786,7 @@ } buf[0] = '\0'; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Check for an // JAVA_HOME environment variable // and fix up the path so it looks like @@ -3418,6 +3416,19 @@ } +bool os::is_debugger_attached() { + return IsDebuggerPresent() ? true : false; +} + + +void os::wait_for_keypress_at_exit(void) { + if (PauseAtExit) { + fprintf(stderr, "Press any key to continue...\n"); + fgetc(stdin); + } +} + + int os::message_box(const char* title, const char* message) { int result = MessageBox(NULL, message, title, MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY); diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/classfile/stackMapFrame.cpp --- a/src/share/vm/classfile/stackMapFrame.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/classfile/stackMapFrame.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -170,6 +170,44 @@ return true; } +bool StackMapFrame::has_flag_match_exception( + const StackMapFrame* target) const { + // We allow flags of {UninitThis} to assign to {} if-and-only-if the + // target frame does not depend upon the current type. + // This is slightly too strict, as we need only enforce that the + // slots that were initialized by the (the things that were + // UninitializedThis before initialize_object() converted them) are unused. + // However we didn't save that information so we'll enforce this upon + // anything that might have been initialized. This is a rare situation + // and javac never generates code that would end up here, but some profilers + // (such as NetBeans) might, when adding exception handlers in + // methods to cover the invokespecial instruction. See 7020118. + + assert(max_locals() == target->max_locals() && + stack_size() == target->stack_size(), "StackMap sizes must match"); + + VerificationType top = VerificationType::top_type(); + VerificationType this_type = verifier()->current_type(); + + if (!flag_this_uninit() || target->flags() != 0) { + return false; + } + + for (int i = 0; i < target->locals_size(); ++i) { + if (locals()[i] == this_type && target->locals()[i] != top) { + return false; + } + } + + for (int i = 0; i < target->stack_size(); ++i) { + if (stack()[i] == this_type && target->stack()[i] != top) { + return false; + } + } + + return true; +} + bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const { if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) { return false; @@ -182,7 +220,9 @@ bool match_stack = is_assignable_to( _stack, target->stack(), _stack_size, CHECK_false); bool match_flags = (_flags | target->flags()) == target->flags(); - return (match_locals && match_stack && match_flags); + + return match_locals && match_stack && + (match_flags || has_flag_match_exception(target)); } VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/classfile/stackMapFrame.hpp --- a/src/share/vm/classfile/stackMapFrame.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/classfile/stackMapFrame.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -228,6 +228,8 @@ bool is_assignable_to( VerificationType* src, VerificationType* target, int32_t len, TRAPS) const; + bool has_flag_match_exception(const StackMapFrame* target) const; + // Debugging void print() const PRODUCT_RETURN; }; diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/classfile/verificationType.hpp --- a/src/share/vm/classfile/verificationType.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/classfile/verificationType.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -128,6 +128,7 @@ // Create verification types static VerificationType bogus_type() { return VerificationType(Bogus); } + static VerificationType top_type() { return bogus_type(); } // alias static VerificationType null_type() { return VerificationType(Null); } static VerificationType integer_type() { return VerificationType(Integer); } static VerificationType float_type() { return VerificationType(Float); } diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/memory/allocation.cpp --- a/src/share/vm/memory/allocation.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/memory/allocation.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -422,6 +422,9 @@ return sum; // Return total consumed space. } +void Arena::signal_out_of_memory(size_t sz, const char* whence) const { + vm_exit_out_of_memory(sz, whence); +} // Grow a new Chunk void* Arena::grow( size_t x ) { @@ -431,8 +434,9 @@ Chunk *k = _chunk; // Get filled-up chunk address _chunk = new (len) Chunk(len); - if (_chunk == NULL) - vm_exit_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); + if (_chunk == NULL) { + signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); + } if (k) k->set_next(_chunk); // Append new chunk to end of linked list else _first = _chunk; @@ -529,6 +533,7 @@ // for debugging with UseMallocOnly void* Arena::internal_malloc_4(size_t x) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); + check_for_overflow(x, "Arena::internal_malloc_4"); if (_hwm + x > _max) { return grow(x); } else { diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/memory/allocation.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -207,6 +207,15 @@ debug_only(void* malloc(size_t size);) debug_only(void* internal_malloc_4(size_t x);) NOT_PRODUCT(void inc_bytes_allocated(size_t x);) + + void signal_out_of_memory(size_t request, const char* whence) const; + + void check_for_overflow(size_t request, const char* whence) const { + if (UINTPTR_MAX - request < (uintptr_t)_hwm) { + signal_out_of_memory(request, whence); + } + } + public: Arena(); Arena(size_t init_size); @@ -220,6 +229,7 @@ assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2"); x = ARENA_ALIGN(x); debug_only(if (UseMallocOnly) return malloc(x);) + check_for_overflow(x, "Arena::Amalloc"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); @@ -233,6 +243,7 @@ void *Amalloc_4(size_t x) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); debug_only(if (UseMallocOnly) return malloc(x);) + check_for_overflow(x, "Arena::Amalloc_4"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); @@ -253,6 +264,7 @@ size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm; x += delta; #endif + check_for_overflow(x, "Arena::Amalloc_D"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); // grow() returns a result aligned >= 8 bytes. diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/prims/jvmtiExport.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -1805,6 +1805,10 @@ void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) { JavaThread* thread = JavaThread::current(); + // In theory everyone coming thru here is in_vm but we need to be certain + // because a callee will do a vm->native transition + ThreadInVMfromUnknown __tiv; + EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, ("JVMTI [%s] method dynamic code generated event triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -1826,19 +1830,18 @@ } void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) { - // In theory everyone coming thru here is in_vm but we need to be certain - // because a callee will do a vm->native transition - ThreadInVMfromUnknown __tiv; jvmtiPhase phase = JvmtiEnv::get_phase(); if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) { post_dynamic_code_generated_internal(name, code_begin, code_end); - return; + } else { + // It may not be safe to post the event from this thread. Defer all + // postings to the service thread so that it can perform them in a safe + // context and in-order. + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); + JvmtiDeferredEvent event = JvmtiDeferredEvent::dynamic_code_generated_event( + name, code_begin, code_end); + JvmtiDeferredEventQueue::enqueue(event); } - - // Blocks until everything now in the queue has been posted - JvmtiDeferredEventQueue::flush_queue(Thread::current()); - - post_dynamic_code_generated_internal(name, code_begin, code_end); } diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/prims/jvmtiExport.hpp --- a/src/share/vm/prims/jvmtiExport.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/prims/jvmtiExport.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -140,12 +140,12 @@ char sig_type, jvalue *value); - private: // posts a DynamicCodeGenerated event (internal/private implementation). // The public post_dynamic_code_generated* functions make use of the - // internal implementation. + // internal implementation. Also called from JvmtiDeferredEvent::post() static void post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) KERNEL_RETURN; + private: // GenerateEvents support to allow posting of CompiledMethodLoad and // DynamicCodeGenerated events for a given environment. diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/prims/jvmtiImpl.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -918,7 +918,7 @@ JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); - event.set_compiled_method_load(nm); + event._event_data.compiled_method_load = nm; nmethodLocker::lock_nmethod(nm); // will be unlocked when posted return event; } @@ -926,23 +926,39 @@ JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event( jmethodID id, const void* code) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD); - event.set_compiled_method_unload(id, code); + event._event_data.compiled_method_unload.method_id = id; + event._event_data.compiled_method_unload.code_begin = code; + return event; +} +JvmtiDeferredEvent JvmtiDeferredEvent::dynamic_code_generated_event( + const char* name, const void* code_begin, const void* code_end) { + JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_DYNAMIC_CODE_GENERATED); + event._event_data.dynamic_code_generated.name = name; + event._event_data.dynamic_code_generated.code_begin = code_begin; + event._event_data.dynamic_code_generated.code_end = code_end; return event; } void JvmtiDeferredEvent::post() { + assert(ServiceThread::is_service_thread(Thread::current()), + "Service thread must post enqueued events"); switch(_type) { - case TYPE_COMPILED_METHOD_LOAD: - JvmtiExport::post_compiled_method_load(compiled_method_load()); - nmethodLocker::unlock_nmethod(compiled_method_load()); + case TYPE_COMPILED_METHOD_LOAD: { + nmethod* nm = _event_data.compiled_method_load; + JvmtiExport::post_compiled_method_load(nm); + nmethodLocker::unlock_nmethod(nm); break; + } case TYPE_COMPILED_METHOD_UNLOAD: JvmtiExport::post_compiled_method_unload( - compiled_method_unload_method_id(), - compiled_method_unload_code_begin()); + _event_data.compiled_method_unload.method_id, + _event_data.compiled_method_unload.code_begin); break; - case TYPE_FLUSH: - JvmtiDeferredEventQueue::flush_complete(flush_state_addr()); + case TYPE_DYNAMIC_CODE_GENERATED: + JvmtiExport::post_dynamic_code_generated_internal( + _event_data.dynamic_code_generated.name, + _event_data.dynamic_code_generated.code_begin, + _event_data.dynamic_code_generated.code_end); break; default: ShouldNotReachHere(); @@ -1065,54 +1081,4 @@ } } -enum { - // Random - used for debugging - FLUSHING = 0x50403020, - FLUSHED = 0x09080706 -}; - -void JvmtiDeferredEventQueue::flush_queue(Thread* thread) { - - volatile int flush_state = FLUSHING; - - JvmtiDeferredEvent flush(JvmtiDeferredEvent::TYPE_FLUSH); - flush.set_flush_state_addr((int*)&flush_state); - - if (ServiceThread::is_service_thread(thread)) { - // If we are the service thread we have to post all preceding events - // Use the flush event as a token to indicate when we can stop - JvmtiDeferredEvent event; - { - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - enqueue(flush); - event = dequeue(); - } - while (!event.is_flush_event() || - event.flush_state_addr() != &flush_state) { - event.post(); - { - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - event = dequeue(); - } - } - } else { - // Wake up the service thread so it will process events. When it gets - // to the flush event it will set 'flush_complete' and notify us. - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - enqueue(flush); - while (flush_state != FLUSHED) { - assert(flush_state == FLUSHING || flush_state == FLUSHED, - "only valid values for this"); - Service_lock->wait(Mutex::_no_safepoint_check_flag); - } - } -} - -void JvmtiDeferredEventQueue::flush_complete(int* state_addr) { - assert(state_addr != NULL && *state_addr == FLUSHING, "must be"); - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - *state_addr = FLUSHED; - Service_lock->notify_all(); -} - #endif // ndef KERNEL diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/prims/jvmtiImpl.hpp --- a/src/share/vm/prims/jvmtiImpl.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/prims/jvmtiImpl.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -451,7 +451,7 @@ TYPE_NONE, TYPE_COMPILED_METHOD_LOAD, TYPE_COMPILED_METHOD_UNLOAD, - TYPE_FLUSH // pseudo-event used to implement flush_queue() + TYPE_DYNAMIC_CODE_GENERATED } Type; Type _type; @@ -461,49 +461,15 @@ jmethodID method_id; const void* code_begin; } compiled_method_unload; - int* flush_state_addr; + struct { + const char* name; + const void* code_begin; + const void* code_end; + } dynamic_code_generated; } _event_data; JvmtiDeferredEvent(Type t) : _type(t) {} - void set_compiled_method_load(nmethod* nm) { - assert(_type == TYPE_COMPILED_METHOD_LOAD, "must be"); - _event_data.compiled_method_load = nm; - } - - nmethod* compiled_method_load() const { - assert(_type == TYPE_COMPILED_METHOD_LOAD, "must be"); - return _event_data.compiled_method_load; - } - - void set_compiled_method_unload(jmethodID id, const void* code) { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - _event_data.compiled_method_unload.method_id = id; - _event_data.compiled_method_unload.code_begin = code; - } - - jmethodID compiled_method_unload_method_id() const { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - return _event_data.compiled_method_unload.method_id; - } - - const void* compiled_method_unload_code_begin() const { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - return _event_data.compiled_method_unload.code_begin; - } - - bool is_flush_event() const { return _type == TYPE_FLUSH; } - - int* flush_state_addr() const { - assert(is_flush_event(), "must be"); - return _event_data.flush_state_addr; - } - - void set_flush_state_addr(int* flag) { - assert(is_flush_event(), "must be"); - _event_data.flush_state_addr = flag; - } - public: JvmtiDeferredEvent() : _type(TYPE_NONE) {} @@ -513,6 +479,9 @@ KERNEL_RETURN_(JvmtiDeferredEvent()); static JvmtiDeferredEvent compiled_method_unload_event( jmethodID id, const void* code) KERNEL_RETURN_(JvmtiDeferredEvent()); + static JvmtiDeferredEvent dynamic_code_generated_event( + const char* name, const void* begin, const void* end) + KERNEL_RETURN_(JvmtiDeferredEvent()); // Actually posts the event. void post() KERNEL_RETURN; @@ -548,25 +517,12 @@ // Transfers events from the _pending_list to the _queue. static void process_pending_events() KERNEL_RETURN; - static void flush_complete(int* flush_state) KERNEL_RETURN; - public: // Must be holding Service_lock when calling these static bool has_events() KERNEL_RETURN_(false); static void enqueue(const JvmtiDeferredEvent& event) KERNEL_RETURN; static JvmtiDeferredEvent dequeue() KERNEL_RETURN_(JvmtiDeferredEvent()); - // This call blocks until all events enqueued prior to this call - // have been posted. The Service_lock is acquired and waited upon. - // - // Implemented by creating a "flush" event and placing it in the queue. - // When the flush event is "posted" it will call flush_complete(), which - // will release the caller. - // - // Can be called by any thread (maybe even the service thread itself). - // Not necessary for the caller to be a JavaThread. - static void flush_queue(Thread* current) KERNEL_RETURN; - // Used to enqueue events without using a lock, for times (such as during // safepoint) when we can't or don't want to lock the Service_lock. // diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/arguments.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -78,6 +78,7 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG; const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; +bool Arguments::_created_by_gamma_launcher = false; // These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; @@ -1656,6 +1657,9 @@ void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { _sun_java_launcher = strdup(launcher); + if (strcmp("gamma", _sun_java_launcher) == 0) { + _created_by_gamma_launcher = true; + } } bool Arguments::created_by_java_launcher() { @@ -1663,6 +1667,10 @@ return strcmp(DEFAULT_JAVA_LAUNCHER, _sun_java_launcher) != 0; } +bool Arguments::created_by_gamma_launcher() { + return _created_by_gamma_launcher; +} + //=========================================================================================================== // Parsing of main arguments @@ -3155,6 +3163,16 @@ } } + // set PauseAtExit if the gamma launcher was used and a debugger is attached + // but only if not already set on the commandline + if (Arguments::created_by_gamma_launcher() && os::is_debugger_attached()) { + bool set = false; + CommandLineFlags::wasSetOnCmdline("PauseAtExit", &set); + if (!set) { + FLAG_SET_DEFAULT(PauseAtExit, true); + } + } + return JNI_OK; } diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/arguments.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,6 +257,9 @@ // sun.java.launcher.pid, private property static int _sun_java_launcher_pid; + // was this VM created by the gamma launcher + static bool _created_by_gamma_launcher; + // Option flags static bool _has_profile; static bool _has_alloc_profile; @@ -444,6 +447,8 @@ static const char* sun_java_launcher() { return _sun_java_launcher; } // Was VM created by a Java launcher? static bool created_by_java_launcher(); + // Was VM created by the gamma Java launcher? + static bool created_by_gamma_launcher(); // -Dsun.java.launcher.pid static int sun_java_launcher_pid() { return _sun_java_launcher_pid; } diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/globals.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -3733,6 +3733,9 @@ "The file to create and for whose removal to await when pausing " \ "at startup. (default: ./vm.paused.)") \ \ + diagnostic(bool, PauseAtExit, false, \ + "Pause and wait for keypress on exit if a debugger is attached") \ + \ product(bool, ExtendedDTraceProbes, false, \ "Enable performance-impacting dtrace probes") \ \ diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/java.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -551,6 +551,7 @@ void vm_direct_exit(int code) { notify_vm_shutdown(); + os::wait_for_keypress_at_exit(); ::exit(code); } @@ -577,11 +578,13 @@ void vm_shutdown() { vm_perform_shutdown_actions(); + os::wait_for_keypress_at_exit(); os::shutdown(); } void vm_abort(bool dump_core) { vm_perform_shutdown_actions(); + os::wait_for_keypress_at_exit(); os::abort(dump_core); ShouldNotReachHere(); } diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/os.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -492,6 +492,12 @@ static void print_location(outputStream* st, intptr_t x, bool verbose = false); static size_t lasterror(char *buf, size_t len); + // Determines whether the calling process is being debugged by a user-mode debugger. + static bool is_debugger_attached(); + + // wait for a key press if PauseAtExit is set + static void wait_for_keypress_at_exit(void); + // The following two functions are used by fatal error handler to trace // native (C) frames. They are not part of frame.hpp/frame.cpp because // frame.hpp/cpp assume thread is JavaThread, and also because different diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/runtime/thread.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -3644,6 +3644,7 @@ if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); } + os::wait_for_keypress_at_exit(); if (JDK_Version::is_jdk12x_version()) { // We are the last thread running, so check if finalizers should be run. diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/src/share/vm/utilities/globalDefinitions_gcc.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -77,6 +77,7 @@ # endif #ifdef LINUX +#define __STDC_LIMIT_MACROS #include #include #include diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -148,6 +148,17 @@ #endif #endif +// On solaris 8, UINTPTR_MAX is defined as empty. +// Everywhere else it's an actual value. +#if UINTPTR_MAX - 1 == -1 +#undef UINTPTR_MAX +#ifdef _LP64 +#define UINTPTR_MAX UINT64_MAX +#else +#define UINTPTR_MAX UINT32_MAX +#endif /* ifdef _LP64 */ +#endif + // Additional Java basic types typedef unsigned char jubyte; diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/utilities/globalDefinitions_visCPP.hpp --- a/src/share/vm/utilities/globalDefinitions_visCPP.hpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/utilities/globalDefinitions_visCPP.hpp Thu Mar 03 09:31:46 2011 -0800 @@ -41,6 +41,7 @@ # include // for va_list # include # include +# include // Need this on windows to get the math constants (e.g., M_PI). #define _USE_MATH_DEFINES # include @@ -99,6 +100,14 @@ typedef signed int ssize_t; #endif +#ifndef UINTPTR_MAX +#ifdef _WIN64 +#define UINTPTR_MAX _UI64_MAX +#else +#define UINTPTR_MAX _UI32_MAX +#endif +#endif + //---------------------------------------------------------------------------------------------------- // Additional Java basic types diff -r 0e531ab5ba04 -r 8c0d0510d36f src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Tue Mar 01 11:53:36 2011 -0800 +++ b/src/share/vm/utilities/vmError.cpp Thu Mar 03 09:31:46 2011 -0800 @@ -802,7 +802,7 @@ first_error_tid = mytid; set_error_reported(); - if (ShowMessageBoxOnError) { + if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the diff -r 0e531ab5ba04 -r 8c0d0510d36f test/runtime/6878713/Test6878713.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6878713/Test6878713.sh Thu Mar 03 09:31:46 2011 -0800 @@ -0,0 +1,74 @@ +#!/bin/sh + +## +## @test +## @bug 6878713 +## @summary Verifier heap corruption, relating to backward jsrs +## @run shell/timeout=120 Test6878713.sh +## + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +fi + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + echo "TESTJAVA not set, selecting " ${TESTJAVA} + echo "If this is incorrect, try setting the variable manually." +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + NULL=/dev/null + PS=":" + FS="/" + ## for solaris, linux it's HOME + FILE_LOCATION=$HOME + if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ] + then + BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'` + fi + ;; + Windows_* ) + NULL=NUL + PS=";" + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +JEMMYPATH=${CPAPPEND} +CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH + +THIS_DIR=`pwd` + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version + +${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} OOMCrashClass1960_2 > test.out 2>&1 + +if [ -s core -o -s "hs_*.log" ] +then + cat hs*.log + echo "Test Failed" + exit 1 +else + echo "Test Passed" + exit 0 +fi diff -r 0e531ab5ba04 -r 8c0d0510d36f test/runtime/6878713/testcase.jar Binary file test/runtime/6878713/testcase.jar has changed